@threadlabs/looma 0.6.3 → 0.6.5

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 (250) hide show
  1. package/components/ui-tree-item/ui-tree-item.html +68 -12
  2. package/components/ui-tree-item/ui-tree-item.js +9 -1
  3. package/dist/index.js +1 -1
  4. package/package.json +2 -2
  5. package/styles/ui-affordance-scope.css +1 -1
  6. package/styles/ui-avatar-group.css +1 -1
  7. package/styles/ui-avatar.css +1 -1
  8. package/styles/ui-badge.css +1 -1
  9. package/styles/ui-button.css +1 -1
  10. package/styles/ui-callout.css +1 -1
  11. package/styles/ui-checkbox.css +1 -1
  12. package/styles/ui-cluster.css +1 -1
  13. package/styles/ui-combobox.css +1 -1
  14. package/styles/ui-container.css +1 -1
  15. package/styles/ui-context-menu.css +1 -1
  16. package/styles/ui-dialog.css +1 -1
  17. package/styles/ui-disclosure.css +1 -1
  18. package/styles/ui-editable.css +1 -1
  19. package/styles/ui-editor-insert-table-grid.css +1 -1
  20. package/styles/ui-editor-mention-menu.css +1 -1
  21. package/styles/ui-editor-slash-menu.css +1 -1
  22. package/styles/ui-editor-table-context-menu.css +1 -1
  23. package/styles/ui-editor-table-overlay.css +1 -1
  24. package/styles/ui-editor-table-toolbar.css +1 -1
  25. package/styles/ui-editor-toolbar.css +1 -1
  26. package/styles/ui-floating-action-button.css +1 -1
  27. package/styles/ui-form-field.css +1 -1
  28. package/styles/ui-grid.css +1 -1
  29. package/styles/ui-icon-button.css +1 -1
  30. package/styles/ui-icon.css +1 -1
  31. package/styles/ui-input.css +1 -1
  32. package/styles/ui-menu-item.css +1 -1
  33. package/styles/ui-menu.css +1 -1
  34. package/styles/ui-popover.css +1 -1
  35. package/styles/ui-radio-group.css +1 -1
  36. package/styles/ui-radio.css +1 -1
  37. package/styles/ui-reel.css +1 -1
  38. package/styles/ui-search-result-row.css +1 -1
  39. package/styles/ui-search-shell.css +1 -1
  40. package/styles/ui-select.css +1 -1
  41. package/styles/ui-separator.css +1 -1
  42. package/styles/ui-sidebar.css +1 -1
  43. package/styles/ui-stack.css +1 -1
  44. package/styles/ui-switch.css +1 -1
  45. package/styles/ui-switcher.css +1 -1
  46. package/styles/ui-tabs.css +1 -1
  47. package/styles/ui-textarea.css +1 -1
  48. package/styles/ui-toast-region.css +1 -1
  49. package/styles/ui-tooltip.css +1 -1
  50. package/styles/ui-top-bar.css +1 -1
  51. package/styles/ui-tree-item.css +75 -12
  52. package/styles/ui-tree.css +1 -1
  53. package/vanilla/UiAffordanceScope.d.ts +1 -1
  54. package/vanilla/UiAffordanceScope.js +1 -1
  55. package/vanilla/UiAvatar.d.ts +1 -1
  56. package/vanilla/UiAvatar.js +1 -1
  57. package/vanilla/UiAvatarGroup.d.ts +1 -1
  58. package/vanilla/UiAvatarGroup.js +1 -1
  59. package/vanilla/UiBadge.d.ts +1 -1
  60. package/vanilla/UiBadge.js +1 -1
  61. package/vanilla/UiButton.d.ts +1 -1
  62. package/vanilla/UiButton.js +1 -1
  63. package/vanilla/UiCallout.d.ts +1 -1
  64. package/vanilla/UiCallout.js +1 -1
  65. package/vanilla/UiCheckbox.d.ts +1 -1
  66. package/vanilla/UiCheckbox.js +1 -1
  67. package/vanilla/UiCluster.d.ts +1 -1
  68. package/vanilla/UiCluster.js +1 -1
  69. package/vanilla/UiCombobox.d.ts +1 -1
  70. package/vanilla/UiCombobox.js +1 -1
  71. package/vanilla/UiContainer.d.ts +1 -1
  72. package/vanilla/UiContainer.js +1 -1
  73. package/vanilla/UiContextMenu.d.ts +1 -1
  74. package/vanilla/UiContextMenu.js +1 -1
  75. package/vanilla/UiDialog.d.ts +1 -1
  76. package/vanilla/UiDialog.js +1 -1
  77. package/vanilla/UiDisclosure.d.ts +1 -1
  78. package/vanilla/UiDisclosure.js +1 -1
  79. package/vanilla/UiEditable.d.ts +1 -1
  80. package/vanilla/UiEditable.js +1 -1
  81. package/vanilla/UiEditorInsertTableGrid.d.ts +1 -1
  82. package/vanilla/UiEditorInsertTableGrid.js +1 -1
  83. package/vanilla/UiEditorMentionMenu.d.ts +1 -1
  84. package/vanilla/UiEditorMentionMenu.js +1 -1
  85. package/vanilla/UiEditorSlashMenu.d.ts +1 -1
  86. package/vanilla/UiEditorSlashMenu.js +1 -1
  87. package/vanilla/UiEditorTableContextMenu.d.ts +1 -1
  88. package/vanilla/UiEditorTableContextMenu.js +1 -1
  89. package/vanilla/UiEditorTableOverlay.d.ts +1 -1
  90. package/vanilla/UiEditorTableOverlay.js +1 -1
  91. package/vanilla/UiEditorTableToolbar.d.ts +1 -1
  92. package/vanilla/UiEditorTableToolbar.js +1 -1
  93. package/vanilla/UiEditorToolbar.d.ts +1 -1
  94. package/vanilla/UiEditorToolbar.js +1 -1
  95. package/vanilla/UiFloatingActionButton.d.ts +1 -1
  96. package/vanilla/UiFloatingActionButton.js +1 -1
  97. package/vanilla/UiFormField.d.ts +1 -1
  98. package/vanilla/UiFormField.js +1 -1
  99. package/vanilla/UiGrid.d.ts +1 -1
  100. package/vanilla/UiGrid.js +1 -1
  101. package/vanilla/UiIcon.d.ts +1 -1
  102. package/vanilla/UiIcon.js +1 -1
  103. package/vanilla/UiIconButton.d.ts +1 -1
  104. package/vanilla/UiIconButton.js +1 -1
  105. package/vanilla/UiInput.d.ts +1 -1
  106. package/vanilla/UiInput.js +1 -1
  107. package/vanilla/UiMenu.d.ts +1 -1
  108. package/vanilla/UiMenu.js +1 -1
  109. package/vanilla/UiMenuItem.d.ts +1 -1
  110. package/vanilla/UiMenuItem.js +1 -1
  111. package/vanilla/UiPopover.d.ts +1 -1
  112. package/vanilla/UiPopover.js +1 -1
  113. package/vanilla/UiRadio.d.ts +1 -1
  114. package/vanilla/UiRadio.js +1 -1
  115. package/vanilla/UiRadioGroup.d.ts +1 -1
  116. package/vanilla/UiRadioGroup.js +1 -1
  117. package/vanilla/UiReel.d.ts +1 -1
  118. package/vanilla/UiReel.js +1 -1
  119. package/vanilla/UiSearchResultRow.d.ts +1 -1
  120. package/vanilla/UiSearchResultRow.js +1 -1
  121. package/vanilla/UiSearchShell.d.ts +1 -1
  122. package/vanilla/UiSearchShell.js +1 -1
  123. package/vanilla/UiSelect.d.ts +1 -1
  124. package/vanilla/UiSelect.js +1 -1
  125. package/vanilla/UiSeparator.d.ts +1 -1
  126. package/vanilla/UiSeparator.js +1 -1
  127. package/vanilla/UiSidebar.d.ts +1 -1
  128. package/vanilla/UiSidebar.js +1 -1
  129. package/vanilla/UiStack.d.ts +1 -1
  130. package/vanilla/UiStack.js +1 -1
  131. package/vanilla/UiSwitch.d.ts +1 -1
  132. package/vanilla/UiSwitch.js +1 -1
  133. package/vanilla/UiSwitcher.d.ts +1 -1
  134. package/vanilla/UiSwitcher.js +1 -1
  135. package/vanilla/UiTabs.d.ts +1 -1
  136. package/vanilla/UiTabs.js +1 -1
  137. package/vanilla/UiTextarea.d.ts +1 -1
  138. package/vanilla/UiTextarea.js +1 -1
  139. package/vanilla/UiToastRegion.d.ts +1 -1
  140. package/vanilla/UiToastRegion.js +1 -1
  141. package/vanilla/UiTooltip.d.ts +1 -1
  142. package/vanilla/UiTooltip.js +1 -1
  143. package/vanilla/UiTopBar.d.ts +1 -1
  144. package/vanilla/UiTopBar.js +1 -1
  145. package/vanilla/UiTree.d.ts +1 -1
  146. package/vanilla/UiTree.js +1 -1
  147. package/vanilla/UiTreeItem.d.ts +1 -1
  148. package/vanilla/UiTreeItem.js +2 -2
  149. package/vue/UiAffordanceScope.vue +8 -84
  150. package/vue/UiAvatar.d.ts +1 -1
  151. package/vue/UiAvatar.vue +9 -106
  152. package/vue/UiAvatarGroup.vue +9 -96
  153. package/vue/UiBadge.vue +1 -1
  154. package/vue/UiButton.vue +1 -1
  155. package/vue/UiCallout.vue +1 -1
  156. package/vue/UiCheckbox.vue +22 -123
  157. package/vue/UiCluster.vue +1 -1
  158. package/vue/UiCombobox.d.ts +1 -1
  159. package/vue/UiCombobox.vue +224 -475
  160. package/vue/UiContainer.vue +1 -1
  161. package/vue/UiContextMenu.vue +34 -141
  162. package/vue/UiDialog.vue +25 -126
  163. package/vue/UiDisclosure.vue +26 -138
  164. package/vue/UiEditable.vue +46 -158
  165. package/vue/UiEditorInsertTableGrid.vue +19 -138
  166. package/vue/UiEditorMentionMenu.vue +17 -124
  167. package/vue/UiEditorSlashMenu.vue +17 -109
  168. package/vue/UiEditorTableContextMenu.vue +34 -122
  169. package/vue/UiEditorTableOverlay.vue +61 -167
  170. package/vue/UiEditorTableToolbar.vue +34 -142
  171. package/vue/UiEditorToolbar.vue +1 -1
  172. package/vue/UiFloatingActionButton.vue +1 -1
  173. package/vue/UiFormField.vue +7 -79
  174. package/vue/UiGrid.vue +1 -1
  175. package/vue/UiIcon.vue +8 -84
  176. package/vue/UiIconButton.vue +7 -79
  177. package/vue/UiInput.vue +7 -79
  178. package/vue/UiMenu.vue +42 -127
  179. package/vue/UiMenuItem.vue +1 -1
  180. package/vue/UiPopover.vue +25 -121
  181. package/vue/UiRadio.vue +22 -123
  182. package/vue/UiRadioGroup.d.ts +1 -1
  183. package/vue/UiRadioGroup.vue +32 -119
  184. package/vue/UiReel.vue +1 -1
  185. package/vue/UiSearchResultRow.vue +1 -1
  186. package/vue/UiSearchShell.vue +25 -121
  187. package/vue/UiSelect.vue +7 -79
  188. package/vue/UiSeparator.vue +1 -1
  189. package/vue/UiSidebar.vue +32 -133
  190. package/vue/UiStack.vue +1 -1
  191. package/vue/UiSwitch.vue +22 -123
  192. package/vue/UiSwitcher.vue +1 -1
  193. package/vue/UiTabs.vue +24 -128
  194. package/vue/UiTextarea.vue +7 -79
  195. package/vue/UiToastRegion.vue +37 -126
  196. package/vue/UiTooltip.vue +25 -124
  197. package/vue/UiTopBar.vue +1 -1
  198. package/vue/UiTree.vue +56 -137
  199. package/vue/UiTreeItem.vue +97 -153
  200. package/vue/chunks/UiAffordanceScope.js +9 -78
  201. package/vue/chunks/UiAvatar.js +13 -89
  202. package/vue/chunks/UiAvatarGroup.js +10 -80
  203. package/vue/chunks/UiBadge.js +1 -1
  204. package/vue/chunks/UiButton.js +1 -1
  205. package/vue/chunks/UiCallout.js +1 -1
  206. package/vue/chunks/UiCheckbox.js +17 -95
  207. package/vue/chunks/UiCluster.js +1 -1
  208. package/vue/chunks/UiCombobox.js +114 -325
  209. package/vue/chunks/UiContainer.js +1 -1
  210. package/vue/chunks/UiContextMenu.js +21 -113
  211. package/vue/chunks/UiDialog.js +20 -99
  212. package/vue/chunks/UiDisclosure.js +22 -112
  213. package/vue/chunks/UiEditable.js +32 -128
  214. package/vue/chunks/UiEditorInsertTableGrid.js +22 -116
  215. package/vue/chunks/UiEditorMentionMenu.js +18 -116
  216. package/vue/chunks/UiEditorSlashMenu.js +15 -101
  217. package/vue/chunks/UiEditorTableContextMenu.js +12 -91
  218. package/vue/chunks/UiEditorTableOverlay.js +29 -120
  219. package/vue/chunks/UiEditorTableToolbar.js +16 -111
  220. package/vue/chunks/UiEditorToolbar.js +1 -1
  221. package/vue/chunks/UiFloatingActionButton.js +1 -1
  222. package/vue/chunks/UiFormField.js +8 -73
  223. package/vue/chunks/UiGrid.js +1 -1
  224. package/vue/chunks/UiIcon.js +9 -78
  225. package/vue/chunks/UiIconButton.js +8 -73
  226. package/vue/chunks/UiInput.js +8 -73
  227. package/vue/chunks/UiMenu.js +25 -111
  228. package/vue/chunks/UiMenuItem.js +1 -1
  229. package/vue/chunks/UiPopover.js +18 -105
  230. package/vue/chunks/UiRadio.js +17 -95
  231. package/vue/chunks/UiRadioGroup.js +23 -105
  232. package/vue/chunks/UiReel.js +1 -1
  233. package/vue/chunks/UiSearchResultRow.js +1 -1
  234. package/vue/chunks/UiSearchShell.js +17 -94
  235. package/vue/chunks/UiSelect.js +8 -73
  236. package/vue/chunks/UiSeparator.js +1 -1
  237. package/vue/chunks/UiSidebar.js +23 -108
  238. package/vue/chunks/UiStack.js +1 -1
  239. package/vue/chunks/UiSwitch.js +17 -95
  240. package/vue/chunks/UiSwitcher.js +1 -1
  241. package/vue/chunks/UiTabs.js +22 -103
  242. package/vue/chunks/UiTextarea.js +8 -73
  243. package/vue/chunks/UiToastRegion.js +27 -112
  244. package/vue/chunks/UiTooltip.js +18 -106
  245. package/vue/chunks/UiTopBar.js +1 -1
  246. package/vue/chunks/UiTree.js +31 -109
  247. package/vue/chunks/UiTreeItem.js +35 -118
  248. package/vue/chunks/host.js +101 -0
  249. package/vue/components.css +759 -707
  250. package/vue/host.ts +154 -0
@@ -1,7 +1,8 @@
1
- <!-- Generated by HTML Next 1.0.0-alpha.2 for Vue 3.5. Do not edit. -->
1
+ <!-- Generated by HTML Next 1.0.0-alpha.3 for Vue 3.5. Do not edit. -->
2
2
  <script setup lang="ts">
3
- import { computed, onBeforeUnmount, onMounted, ref, shallowRef, watchEffect } from 'vue'
3
+ import { computed, ref } from 'vue'
4
4
  import * as controllerModule from '../components/ui-radio-group/ui-radio-group.js'
5
+ import { createDispatch, useComponentHost } from './host'
5
6
 
6
7
  defineOptions({ inheritAttrs: false })
7
8
 
@@ -51,125 +52,37 @@ const hostState = computed(() =>
51
52
  ].filter(Boolean).join(' ')
52
53
  )
53
54
 
54
- /** Dispatches a component event to Vue listeners and, for controllers and page code, on the root. */
55
- function dispatch(name: string, detail?: unknown): boolean {
56
- const declared: Record<string, EventInit | undefined> = {
57
- select: { bubbles: true, composed: true, cancelable: false },
58
- change: { bubbles: true, composed: true, cancelable: false },
59
- }
60
- const checks: Record<string, (detail: unknown) => boolean> = {
61
- select: (detail) =>
62
- detail !== null && typeof detail === 'object' && !Array.isArray(detail)
63
- && typeof (detail as Record<string, unknown>)['value'] === 'string'
64
- && typeof (detail as Record<string, unknown>)['previousValue'] === 'string'
65
- && ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
66
- || (detail as Record<string, unknown>)['trigger'] === 'pointer'
67
- || (detail as Record<string, unknown>)['trigger'] === 'programmatic')
68
- && Object.keys(detail as object).every((key) =>
69
- ['value', 'previousValue', 'trigger'].includes(key)
70
- ),
71
- change: (detail) =>
72
- detail !== null && typeof detail === 'object' && !Array.isArray(detail)
73
- && typeof (detail as Record<string, unknown>)['checked'] === 'boolean'
74
- && typeof (detail as Record<string, unknown>)['value'] === 'string'
75
- && ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
76
- || (detail as Record<string, unknown>)['trigger'] === 'pointer'
77
- || (detail as Record<string, unknown>)['trigger'] === 'programmatic')
78
- && Object.keys(detail as object).every((key) =>
79
- ['checked', 'value', 'trigger'].includes(key)
80
- ),
81
- }
82
- if (detail !== undefined && checks[name] !== undefined && !checks[name]!(detail)) {
83
- throw new TypeError(`HR002: Event \`${name}\` detail does not satisfy its declared type.`)
84
- }
85
- const emitEvent = emit as (name: string, detail: unknown) => void
86
- emitEvent(name, detail)
87
- if (detail !== null && typeof detail === 'object' && 'value' in detail) {
88
- emitEvent('update:value', (detail as Record<string, unknown>)['value'])
89
- }
90
- return root.value?.dispatchEvent(
91
- new CustomEvent(name, { bubbles: true, composed: true, ...declared[name], detail }),
92
- ) ?? true
93
- }
94
-
95
- function read(name: string): unknown {
96
- if (name === 'internalValue') return internalValue.value
97
- return (props as Record<string, unknown>)[name]
98
- }
99
-
100
- function write(name: string, value: unknown): boolean {
101
- if (name === 'internalValue') {
102
- internalValue.value = value as never
103
- return true
104
- }
105
- throw new TypeError(`Only declared state is writable; \`${name}\` is not.`)
106
- }
107
-
108
- const stops: Array<() => void> = []
109
- const host = {
110
- get element(): Element {
111
- return root.value as Element
112
- },
113
- state: new Proxy({} as Record<string, unknown>, {
114
- get: (_target, name) => typeof name === 'string' ? read(name) : undefined,
115
- set: (_target, name, value) => typeof name === 'string' && write(name, value),
116
- }),
117
- refs: {} as Readonly<Record<string, Element>>,
118
- elements: new Proxy({} as Record<string, Element | RadioNodeList | undefined>, {
119
- get: (_target, name) => {
120
- if (typeof name !== 'string' || root.value === null) return undefined
121
- const form = root.value instanceof HTMLFormElement
122
- ? root.value
123
- : root.value.querySelector('form')
124
- return form?.elements.namedItem(name)
125
- ?? root.value.querySelector(`[name="${CSS.escape(name)}"]`) ?? undefined
126
- },
127
- }),
128
- signal<T>(initialValue: T) {
129
- const value = shallowRef(initialValue)
130
- return {
131
- get: (): T => value.value,
132
- set: (next: T): void => {
133
- if (!Object.is(value.value, next)) value.value = next
134
- },
135
- update: (next: (current: T) => T): void => {
136
- const updated = next(value.value)
137
- if (!Object.is(value.value, updated)) value.value = updated
138
- },
139
- }
55
+ const isSelectDetail = (detail: unknown): boolean =>
56
+ detail !== null && typeof detail === 'object' && !Array.isArray(detail)
57
+ && typeof (detail as Record<string, unknown>)['value'] === 'string'
58
+ && typeof (detail as Record<string, unknown>)['previousValue'] === 'string'
59
+ && ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
60
+ || (detail as Record<string, unknown>)['trigger'] === 'pointer'
61
+ || (detail as Record<string, unknown>)['trigger'] === 'programmatic')
62
+ && Object.keys(detail as object).every((key) =>
63
+ ['value', 'previousValue', 'trigger'].includes(key)
64
+ )
65
+ const isChangeDetail = (detail: unknown): boolean =>
66
+ detail !== null && typeof detail === 'object' && !Array.isArray(detail)
67
+ && typeof (detail as Record<string, unknown>)['checked'] === 'boolean'
68
+ && typeof (detail as Record<string, unknown>)['value'] === 'string'
69
+ && ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
70
+ || (detail as Record<string, unknown>)['trigger'] === 'pointer'
71
+ || (detail as Record<string, unknown>)['trigger'] === 'programmatic')
72
+ && Object.keys(detail as object).every((key) => ['checked', 'value', 'trigger'].includes(key))
73
+ const dispatch = createDispatch(root, emit as (name: string, detail: unknown) => void, {
74
+ checks: {
75
+ select: isSelectDetail,
76
+ change: isChangeDetail,
140
77
  },
141
- computed<T>(compute: () => T) {
142
- const value = computed(compute)
143
- return { get: (): T => value.value }
144
- },
145
- effect(run: () => void | (() => void)): () => void {
146
- const stop = watchEffect((onCleanup) => {
147
- const cleanup = run()
148
- if (typeof cleanup === 'function') onCleanup(cleanup)
149
- }, { flush: 'post' })
150
- stops.push(stop)
151
- return stop
152
- },
153
- on(event: string, listener: EventListener): () => void {
154
- const element = root.value
155
- element?.addEventListener(event, listener)
156
- const off = (): void => element?.removeEventListener(event, listener)
157
- stops.push(off)
158
- return off
159
- },
160
- dispatch,
161
- }
162
-
163
- let cleanup: void | (() => void)
164
- let ready: Promise<void> | undefined
165
- onMounted(() => {
166
- ready = Promise.resolve(controllerModule.default(host as never)).then((result) => {
167
- cleanup = result
168
- })
78
+ modeled: ['value'],
169
79
  })
170
- onBeforeUnmount(() => {
171
- for (const stop of stops.splice(0)) stop()
172
- if (typeof cleanup === 'function') cleanup()
80
+
81
+ useComponentHost(controllerModule.default, {
82
+ root,
83
+ dispatch,
84
+ props,
85
+ state: { internalValue },
173
86
  })
174
87
  </script>
175
88
 
package/vue/UiReel.vue CHANGED
@@ -1,4 +1,4 @@
1
- <!-- Generated by HTML Next 1.0.0-alpha.2 for Vue 3.5. Do not edit. -->
1
+ <!-- Generated by HTML Next 1.0.0-alpha.3 for Vue 3.5. Do not edit. -->
2
2
  <script setup lang="ts">
3
3
  import { computed } from 'vue'
4
4
 
@@ -1,4 +1,4 @@
1
- <!-- Generated by HTML Next 1.0.0-alpha.2 for Vue 3.5. Do not edit. -->
1
+ <!-- Generated by HTML Next 1.0.0-alpha.3 for Vue 3.5. Do not edit. -->
2
2
  <script setup lang="ts">
3
3
  import { computed } from 'vue'
4
4
 
@@ -1,15 +1,8 @@
1
- <!-- Generated by HTML Next 1.0.0-alpha.2 for Vue 3.5. Do not edit. -->
1
+ <!-- Generated by HTML Next 1.0.0-alpha.3 for Vue 3.5. Do not edit. -->
2
2
  <script setup lang="ts">
3
- import {
4
- computed,
5
- onBeforeUnmount,
6
- onMounted,
7
- ref,
8
- shallowRef,
9
- useTemplateRef,
10
- watchEffect,
11
- } from 'vue'
3
+ import { ref, useTemplateRef } from 'vue'
12
4
  import * as controllerModule from '../components/ui-search-shell/ui-search-shell.js'
5
+ import { createDispatch, useComponentHost } from './host'
13
6
 
14
7
  defineOptions({ inheritAttrs: false })
15
8
 
@@ -42,119 +35,30 @@ const root = ref<HTMLElement | null>(null)
42
35
  const dialogElement = useTemplateRef<HTMLElement>('dialog')
43
36
  const internalOpen = ref(false)
44
37
 
45
- /** Dispatches a component event to Vue listeners and, for controllers and page code, on the root. */
46
- function dispatch(name: string, detail?: unknown): boolean {
47
- const declared: Record<string, EventInit | undefined> = {
48
- close: { bubbles: true, composed: true, cancelable: false },
49
- }
50
- const checks: Record<string, (detail: unknown) => boolean> = {
51
- close: (detail) =>
52
- detail !== null && typeof detail === 'object' && !Array.isArray(detail)
53
- && typeof (detail as Record<string, unknown>)['open'] === 'boolean'
54
- && ((detail as Record<string, unknown>)['reason'] === 'action'
55
- || (detail as Record<string, unknown>)['reason'] === 'programmatic'
56
- || (detail as Record<string, unknown>)['reason'] === 'light-dismiss'
57
- || (detail as Record<string, unknown>)['reason'] === 'escape')
58
- && ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
59
- || (detail as Record<string, unknown>)['trigger'] === 'pointer'
60
- || (detail as Record<string, unknown>)['trigger'] === 'programmatic')
61
- && Object.keys(detail as object).every((key) => ['open', 'reason', 'trigger'].includes(key)),
62
- }
63
- if (detail !== undefined && checks[name] !== undefined && !checks[name]!(detail)) {
64
- throw new TypeError(`HR002: Event \`${name}\` detail does not satisfy its declared type.`)
65
- }
66
- const emitEvent = emit as (name: string, detail: unknown) => void
67
- emitEvent(name, detail)
68
- if (detail !== null && typeof detail === 'object' && 'open' in detail) {
69
- emitEvent('update:open', (detail as Record<string, unknown>)['open'])
70
- }
71
- return root.value?.dispatchEvent(
72
- new CustomEvent(name, { bubbles: true, composed: true, ...declared[name], detail }),
73
- ) ?? true
74
- }
75
-
76
- function read(name: string): unknown {
77
- if (name === 'internalOpen') return internalOpen.value
78
- return (props as Record<string, unknown>)[name]
79
- }
80
-
81
- function write(name: string, value: unknown): boolean {
82
- if (name === 'internalOpen') {
83
- internalOpen.value = value as never
84
- return true
85
- }
86
- throw new TypeError(`Only declared state is writable; \`${name}\` is not.`)
87
- }
88
-
89
- const stops: Array<() => void> = []
90
- const host = {
91
- get element(): Element {
92
- return root.value as Element
38
+ const isCloseDetail = (detail: unknown): boolean =>
39
+ detail !== null && typeof detail === 'object' && !Array.isArray(detail)
40
+ && typeof (detail as Record<string, unknown>)['open'] === 'boolean'
41
+ && ((detail as Record<string, unknown>)['reason'] === 'action'
42
+ || (detail as Record<string, unknown>)['reason'] === 'programmatic'
43
+ || (detail as Record<string, unknown>)['reason'] === 'light-dismiss'
44
+ || (detail as Record<string, unknown>)['reason'] === 'escape')
45
+ && ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
46
+ || (detail as Record<string, unknown>)['trigger'] === 'pointer'
47
+ || (detail as Record<string, unknown>)['trigger'] === 'programmatic')
48
+ && Object.keys(detail as object).every((key) => ['open', 'reason', 'trigger'].includes(key))
49
+ const dispatch = createDispatch(root, emit as (name: string, detail: unknown) => void, {
50
+ checks: {
51
+ close: isCloseDetail,
93
52
  },
94
- state: new Proxy({} as Record<string, unknown>, {
95
- get: (_target, name) => typeof name === 'string' ? read(name) : undefined,
96
- set: (_target, name, value) => typeof name === 'string' && write(name, value),
97
- }),
98
- refs: {
99
- get dialog(): Element {
100
- return dialogElement.value as Element
101
- },
102
- } as Readonly<Record<string, Element>>,
103
- elements: new Proxy({} as Record<string, Element | RadioNodeList | undefined>, {
104
- get: (_target, name) => {
105
- if (typeof name !== 'string' || root.value === null) return undefined
106
- const form = root.value instanceof HTMLFormElement
107
- ? root.value
108
- : root.value.querySelector('form')
109
- return form?.elements.namedItem(name)
110
- ?? root.value.querySelector(`[name="${CSS.escape(name)}"]`) ?? undefined
111
- },
112
- }),
113
- signal<T>(initialValue: T) {
114
- const value = shallowRef(initialValue)
115
- return {
116
- get: (): T => value.value,
117
- set: (next: T): void => {
118
- if (!Object.is(value.value, next)) value.value = next
119
- },
120
- update: (next: (current: T) => T): void => {
121
- const updated = next(value.value)
122
- if (!Object.is(value.value, updated)) value.value = updated
123
- },
124
- }
125
- },
126
- computed<T>(compute: () => T) {
127
- const value = computed(compute)
128
- return { get: (): T => value.value }
129
- },
130
- effect(run: () => void | (() => void)): () => void {
131
- const stop = watchEffect((onCleanup) => {
132
- const cleanup = run()
133
- if (typeof cleanup === 'function') onCleanup(cleanup)
134
- }, { flush: 'post' })
135
- stops.push(stop)
136
- return stop
137
- },
138
- on(event: string, listener: EventListener): () => void {
139
- const element = root.value
140
- element?.addEventListener(event, listener)
141
- const off = (): void => element?.removeEventListener(event, listener)
142
- stops.push(off)
143
- return off
144
- },
145
- dispatch,
146
- }
147
-
148
- let cleanup: void | (() => void)
149
- let ready: Promise<void> | undefined
150
- onMounted(() => {
151
- ready = Promise.resolve(controllerModule.default(host as never)).then((result) => {
152
- cleanup = result
153
- })
53
+ modeled: ['open'],
154
54
  })
155
- onBeforeUnmount(() => {
156
- for (const stop of stops.splice(0)) stop()
157
- if (typeof cleanup === 'function') cleanup()
55
+
56
+ useComponentHost(controllerModule.default, {
57
+ root,
58
+ dispatch,
59
+ props,
60
+ refs: { dialog: dialogElement },
61
+ state: { internalOpen },
158
62
  })
159
63
  </script>
160
64
 
package/vue/UiSelect.vue CHANGED
@@ -1,7 +1,8 @@
1
- <!-- Generated by HTML Next 1.0.0-alpha.2 for Vue 3.5. Do not edit. -->
1
+ <!-- Generated by HTML Next 1.0.0-alpha.3 for Vue 3.5. Do not edit. -->
2
2
  <script setup lang="ts">
3
- import { computed, onBeforeUnmount, onMounted, ref, shallowRef, watchEffect } from 'vue'
3
+ import { computed, ref } from 'vue'
4
4
  import * as controllerModule from '../components/ui-select/ui-select.js'
5
+ import { createDispatch, useComponentHost } from './host'
5
6
 
6
7
  defineOptions({ inheritAttrs: false })
7
8
 
@@ -31,85 +32,12 @@ const model = computed({
31
32
 
32
33
  const root = ref<HTMLElement | null>(null)
33
34
 
34
- /** Dispatches a component event to Vue listeners and, for controllers and page code, on the root. */
35
- function dispatch(name: string, detail?: unknown): boolean {
36
- return root.value?.dispatchEvent(new CustomEvent(name, { bubbles: true, composed: true, detail }))
37
- ?? true
38
- }
39
-
40
- function read(name: string): unknown {
41
- return (props as Record<string, unknown>)[name]
42
- }
35
+ const dispatch = createDispatch(root)
43
36
 
44
- function write(name: string, value: unknown): boolean {
45
- throw new TypeError(`Only declared state is writable; \`${name}\` is not.`)
46
- }
47
-
48
- const stops: Array<() => void> = []
49
- const host = {
50
- get element(): Element {
51
- return root.value as Element
52
- },
53
- state: new Proxy({} as Record<string, unknown>, {
54
- get: (_target, name) => typeof name === 'string' ? read(name) : undefined,
55
- set: (_target, name, value) => typeof name === 'string' && write(name, value),
56
- }),
57
- refs: {} as Readonly<Record<string, Element>>,
58
- elements: new Proxy({} as Record<string, Element | RadioNodeList | undefined>, {
59
- get: (_target, name) => {
60
- if (typeof name !== 'string' || root.value === null) return undefined
61
- const form = root.value instanceof HTMLFormElement
62
- ? root.value
63
- : root.value.querySelector('form')
64
- return form?.elements.namedItem(name)
65
- ?? root.value.querySelector(`[name="${CSS.escape(name)}"]`) ?? undefined
66
- },
67
- }),
68
- signal<T>(initialValue: T) {
69
- const value = shallowRef(initialValue)
70
- return {
71
- get: (): T => value.value,
72
- set: (next: T): void => {
73
- if (!Object.is(value.value, next)) value.value = next
74
- },
75
- update: (next: (current: T) => T): void => {
76
- const updated = next(value.value)
77
- if (!Object.is(value.value, updated)) value.value = updated
78
- },
79
- }
80
- },
81
- computed<T>(compute: () => T) {
82
- const value = computed(compute)
83
- return { get: (): T => value.value }
84
- },
85
- effect(run: () => void | (() => void)): () => void {
86
- const stop = watchEffect((onCleanup) => {
87
- const cleanup = run()
88
- if (typeof cleanup === 'function') onCleanup(cleanup)
89
- }, { flush: 'post' })
90
- stops.push(stop)
91
- return stop
92
- },
93
- on(event: string, listener: EventListener): () => void {
94
- const element = root.value
95
- element?.addEventListener(event, listener)
96
- const off = (): void => element?.removeEventListener(event, listener)
97
- stops.push(off)
98
- return off
99
- },
37
+ useComponentHost(controllerModule.default, {
38
+ root,
100
39
  dispatch,
101
- }
102
-
103
- let cleanup: void | (() => void)
104
- let ready: Promise<void> | undefined
105
- onMounted(() => {
106
- ready = Promise.resolve(controllerModule.default(host as never)).then((result) => {
107
- cleanup = result
108
- })
109
- })
110
- onBeforeUnmount(() => {
111
- for (const stop of stops.splice(0)) stop()
112
- if (typeof cleanup === 'function') cleanup()
40
+ props,
113
41
  })
114
42
  </script>
115
43
 
@@ -1,4 +1,4 @@
1
- <!-- Generated by HTML Next 1.0.0-alpha.2 for Vue 3.5. Do not edit. -->
1
+ <!-- Generated by HTML Next 1.0.0-alpha.3 for Vue 3.5. Do not edit. -->
2
2
  <script setup lang="ts">
3
3
  defineOptions({ inheritAttrs: false })
4
4
 
package/vue/UiSidebar.vue CHANGED
@@ -1,15 +1,8 @@
1
- <!-- Generated by HTML Next 1.0.0-alpha.2 for Vue 3.5. Do not edit. -->
1
+ <!-- Generated by HTML Next 1.0.0-alpha.3 for Vue 3.5. Do not edit. -->
2
2
  <script setup lang="ts">
3
- import {
4
- computed,
5
- onBeforeUnmount,
6
- onMounted,
7
- ref,
8
- shallowRef,
9
- useTemplateRef,
10
- watchEffect,
11
- } from 'vue'
3
+ import { computed, ref, useTemplateRef } from 'vue'
12
4
  import * as controllerModule from '../components/ui-sidebar/ui-sidebar.js'
5
+ import { createDispatch, useComponentHost } from './host'
13
6
 
14
7
  defineOptions({ inheritAttrs: false })
15
8
 
@@ -64,131 +57,37 @@ const hostState = computed(() =>
64
57
  ].filter(Boolean).join(' ')
65
58
  )
66
59
 
67
- /** Dispatches a component event to Vue listeners and, for controllers and page code, on the root. */
68
- function dispatch(name: string, detail?: unknown): boolean {
69
- const declared: Record<string, EventInit | undefined> = {
70
- resize: { bubbles: true, composed: true, cancelable: false },
71
- toggle: { bubbles: true, composed: true, cancelable: false },
72
- }
73
- const checks: Record<string, (detail: unknown) => boolean> = {
74
- resize: (detail) =>
75
- detail !== null && typeof detail === 'object' && !Array.isArray(detail)
76
- && (typeof (detail as Record<string, unknown>)['width'] === 'number'
77
- && Number.isFinite((detail as Record<string, unknown>)['width']))
78
- && ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
79
- || (detail as Record<string, unknown>)['trigger'] === 'pointer'
80
- || (detail as Record<string, unknown>)['trigger'] === 'programmatic')
81
- && Object.keys(detail as object).every((key) => ['width', 'trigger'].includes(key)),
82
- toggle: (detail) =>
83
- detail !== null && typeof detail === 'object' && !Array.isArray(detail)
84
- && typeof (detail as Record<string, unknown>)['open'] === 'boolean'
85
- && ((detail as Record<string, unknown>)['mode'] === 'docked'
86
- || (detail as Record<string, unknown>)['mode'] === 'drawer')
87
- && ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
88
- || (detail as Record<string, unknown>)['trigger'] === 'pointer'
89
- || (detail as Record<string, unknown>)['trigger'] === 'programmatic')
90
- && Object.keys(detail as object).every((key) => ['open', 'mode', 'trigger'].includes(key)),
91
- }
92
- if (detail !== undefined && checks[name] !== undefined && !checks[name]!(detail)) {
93
- throw new TypeError(`HR002: Event \`${name}\` detail does not satisfy its declared type.`)
94
- }
95
- const emitEvent = emit as (name: string, detail: unknown) => void
96
- emitEvent(name, detail)
97
- if (detail !== null && typeof detail === 'object' && 'width' in detail) {
98
- emitEvent('update:width', (detail as Record<string, unknown>)['width'])
99
- }
100
- return root.value?.dispatchEvent(
101
- new CustomEvent(name, { bubbles: true, composed: true, ...declared[name], detail }),
102
- ) ?? true
103
- }
104
-
105
- function read(name: string): unknown {
106
- if (name === 'internalCollapsed') return internalCollapsed.value
107
- if (name === 'drawer') return drawer.value
108
- return (props as Record<string, unknown>)[name]
109
- }
110
-
111
- function write(name: string, value: unknown): boolean {
112
- if (name === 'internalCollapsed') {
113
- internalCollapsed.value = value as never
114
- return true
115
- }
116
- if (name === 'drawer') {
117
- drawer.value = value as never
118
- return true
119
- }
120
- throw new TypeError(`Only declared state is writable; \`${name}\` is not.`)
121
- }
122
-
123
- const stops: Array<() => void> = []
124
- const host = {
125
- get element(): Element {
126
- return root.value as Element
60
+ const isResizeDetail = (detail: unknown): boolean =>
61
+ detail !== null && typeof detail === 'object' && !Array.isArray(detail)
62
+ && (typeof (detail as Record<string, unknown>)['width'] === 'number'
63
+ && Number.isFinite((detail as Record<string, unknown>)['width']))
64
+ && ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
65
+ || (detail as Record<string, unknown>)['trigger'] === 'pointer'
66
+ || (detail as Record<string, unknown>)['trigger'] === 'programmatic')
67
+ && Object.keys(detail as object).every((key) => ['width', 'trigger'].includes(key))
68
+ const isToggleDetail = (detail: unknown): boolean =>
69
+ detail !== null && typeof detail === 'object' && !Array.isArray(detail)
70
+ && typeof (detail as Record<string, unknown>)['open'] === 'boolean'
71
+ && ((detail as Record<string, unknown>)['mode'] === 'docked'
72
+ || (detail as Record<string, unknown>)['mode'] === 'drawer')
73
+ && ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
74
+ || (detail as Record<string, unknown>)['trigger'] === 'pointer'
75
+ || (detail as Record<string, unknown>)['trigger'] === 'programmatic')
76
+ && Object.keys(detail as object).every((key) => ['open', 'mode', 'trigger'].includes(key))
77
+ const dispatch = createDispatch(root, emit as (name: string, detail: unknown) => void, {
78
+ checks: {
79
+ resize: isResizeDetail,
80
+ toggle: isToggleDetail,
127
81
  },
128
- state: new Proxy({} as Record<string, unknown>, {
129
- get: (_target, name) => typeof name === 'string' ? read(name) : undefined,
130
- set: (_target, name, value) => typeof name === 'string' && write(name, value),
131
- }),
132
- refs: {
133
- get resizer(): Element {
134
- return resizerElement.value as Element
135
- },
136
- } as Readonly<Record<string, Element>>,
137
- elements: new Proxy({} as Record<string, Element | RadioNodeList | undefined>, {
138
- get: (_target, name) => {
139
- if (typeof name !== 'string' || root.value === null) return undefined
140
- const form = root.value instanceof HTMLFormElement
141
- ? root.value
142
- : root.value.querySelector('form')
143
- return form?.elements.namedItem(name)
144
- ?? root.value.querySelector(`[name="${CSS.escape(name)}"]`) ?? undefined
145
- },
146
- }),
147
- signal<T>(initialValue: T) {
148
- const value = shallowRef(initialValue)
149
- return {
150
- get: (): T => value.value,
151
- set: (next: T): void => {
152
- if (!Object.is(value.value, next)) value.value = next
153
- },
154
- update: (next: (current: T) => T): void => {
155
- const updated = next(value.value)
156
- if (!Object.is(value.value, updated)) value.value = updated
157
- },
158
- }
159
- },
160
- computed<T>(compute: () => T) {
161
- const value = computed(compute)
162
- return { get: (): T => value.value }
163
- },
164
- effect(run: () => void | (() => void)): () => void {
165
- const stop = watchEffect((onCleanup) => {
166
- const cleanup = run()
167
- if (typeof cleanup === 'function') onCleanup(cleanup)
168
- }, { flush: 'post' })
169
- stops.push(stop)
170
- return stop
171
- },
172
- on(event: string, listener: EventListener): () => void {
173
- const element = root.value
174
- element?.addEventListener(event, listener)
175
- const off = (): void => element?.removeEventListener(event, listener)
176
- stops.push(off)
177
- return off
178
- },
179
- dispatch,
180
- }
181
-
182
- let cleanup: void | (() => void)
183
- let ready: Promise<void> | undefined
184
- onMounted(() => {
185
- ready = Promise.resolve(controllerModule.default(host as never)).then((result) => {
186
- cleanup = result
187
- })
82
+ modeled: ['width'],
188
83
  })
189
- onBeforeUnmount(() => {
190
- for (const stop of stops.splice(0)) stop()
191
- if (typeof cleanup === 'function') cleanup()
84
+
85
+ useComponentHost(controllerModule.default, {
86
+ root,
87
+ dispatch,
88
+ props,
89
+ refs: { resizer: resizerElement },
90
+ state: { internalCollapsed, drawer },
192
91
  })
193
92
  </script>
194
93
 
package/vue/UiStack.vue CHANGED
@@ -1,4 +1,4 @@
1
- <!-- Generated by HTML Next 1.0.0-alpha.2 for Vue 3.5. Do not edit. -->
1
+ <!-- Generated by HTML Next 1.0.0-alpha.3 for Vue 3.5. Do not edit. -->
2
2
  <script setup lang="ts">
3
3
  import { computed } from 'vue'
4
4