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