@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-editor-slash-menu/ui-editor-slash-menu.js'
5
+ import { createDispatch, useComponentHost } from './host'
5
6
  import UiIcon from './UiIcon.vue'
6
7
 
7
8
  defineOptions({ inheritAttrs: false })
@@ -39,115 +40,22 @@ const root = ref<HTMLElement | null>(null)
39
40
  const visible = ref(false)
40
41
  const active = ref(0)
41
42
 
42
- /** Dispatches a component event to Vue listeners and, for controllers and page code, on the root. */
43
- function dispatch(name: string, detail?: unknown): boolean {
44
- const declared: Record<string, EventInit | undefined> = {
45
- highlight: { bubbles: true, composed: true, cancelable: false },
46
- select: { bubbles: true, composed: true, cancelable: false },
47
- }
48
- const checks: Record<string, (detail: unknown) => boolean> = {
49
- highlight: (detail) =>
50
- detail !== null && typeof detail === 'object' && !Array.isArray(detail)
51
- && Number.isInteger((detail as Record<string, unknown>)['index'])
52
- && Object.keys(detail as object).every((key) => ['index'].includes(key)),
53
- select: (detail) =>
54
- detail !== null && typeof detail === 'object' && !Array.isArray(detail)
55
- && Number.isInteger((detail as Record<string, unknown>)['index'])
56
- && Object.keys(detail as object).every((key) => ['index'].includes(key)),
57
- }
58
- if (detail !== undefined && checks[name] !== undefined && !checks[name]!(detail)) {
59
- throw new TypeError(`HR002: Event \`${name}\` detail does not satisfy its declared type.`)
60
- }
61
- const emitEvent = emit as (name: string, detail: unknown) => void
62
- emitEvent(name, detail)
63
- return root.value?.dispatchEvent(
64
- new CustomEvent(name, { bubbles: true, composed: true, ...declared[name], detail }),
65
- ) ?? true
66
- }
67
-
68
- function read(name: string): unknown {
69
- if (name === 'visible') return visible.value
70
- if (name === 'active') return active.value
71
- return (props as Record<string, unknown>)[name]
72
- }
73
-
74
- function write(name: string, value: unknown): boolean {
75
- if (name === 'visible') {
76
- visible.value = value as never
77
- return true
78
- }
79
- if (name === 'active') {
80
- active.value = value as never
81
- return true
82
- }
83
- throw new TypeError(`Only declared state is writable; \`${name}\` is not.`)
84
- }
85
-
86
- const stops: Array<() => void> = []
87
- const host = {
88
- get element(): Element {
89
- return root.value as Element
90
- },
91
- state: new Proxy({} as Record<string, unknown>, {
92
- get: (_target, name) => typeof name === 'string' ? read(name) : undefined,
93
- set: (_target, name, value) => typeof name === 'string' && write(name, value),
94
- }),
95
- refs: {} as Readonly<Record<string, Element>>,
96
- elements: new Proxy({} as Record<string, Element | RadioNodeList | undefined>, {
97
- get: (_target, name) => {
98
- if (typeof name !== 'string' || root.value === null) return undefined
99
- const form = root.value instanceof HTMLFormElement
100
- ? root.value
101
- : root.value.querySelector('form')
102
- return form?.elements.namedItem(name)
103
- ?? root.value.querySelector(`[name="${CSS.escape(name)}"]`) ?? undefined
104
- },
105
- }),
106
- signal<T>(initialValue: T) {
107
- const value = shallowRef(initialValue)
108
- return {
109
- get: (): T => value.value,
110
- set: (next: T): void => {
111
- if (!Object.is(value.value, next)) value.value = next
112
- },
113
- update: (next: (current: T) => T): void => {
114
- const updated = next(value.value)
115
- if (!Object.is(value.value, updated)) value.value = updated
116
- },
117
- }
118
- },
119
- computed<T>(compute: () => T) {
120
- const value = computed(compute)
121
- return { get: (): T => value.value }
122
- },
123
- effect(run: () => void | (() => void)): () => void {
124
- const stop = watchEffect((onCleanup) => {
125
- const cleanup = run()
126
- if (typeof cleanup === 'function') onCleanup(cleanup)
127
- }, { flush: 'post' })
128
- stops.push(stop)
129
- return stop
130
- },
131
- on(event: string, listener: EventListener): () => void {
132
- const element = root.value
133
- element?.addEventListener(event, listener)
134
- const off = (): void => element?.removeEventListener(event, listener)
135
- stops.push(off)
136
- return off
43
+ const isHighlightDetail = (detail: unknown): boolean =>
44
+ detail !== null && typeof detail === 'object' && !Array.isArray(detail)
45
+ && Number.isInteger((detail as Record<string, unknown>)['index'])
46
+ && Object.keys(detail as object).every((key) => ['index'].includes(key))
47
+ const dispatch = createDispatch(root, emit as (name: string, detail: unknown) => void, {
48
+ checks: {
49
+ highlight: isHighlightDetail,
50
+ select: isHighlightDetail,
137
51
  },
138
- dispatch,
139
- }
140
-
141
- let cleanup: void | (() => void)
142
- let ready: Promise<void> | undefined
143
- onMounted(() => {
144
- ready = Promise.resolve(controllerModule.default(host as never)).then((result) => {
145
- cleanup = result
146
- })
147
52
  })
148
- onBeforeUnmount(() => {
149
- for (const stop of stops.splice(0)) stop()
150
- if (typeof cleanup === 'function') cleanup()
53
+
54
+ useComponentHost(controllerModule.default, {
55
+ root,
56
+ dispatch,
57
+ props,
58
+ state: { visible, active },
151
59
  })
152
60
  </script>
153
61
 
@@ -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-editor-table-context-menu/ui-editor-table-context-menu.js'
5
+ import { createDispatch, useComponentHost } from './host'
5
6
  import UiIcon from './UiIcon.vue'
6
7
 
7
8
  defineOptions({ inheritAttrs: false })
@@ -73,128 +74,39 @@ const sections = ref<
73
74
  { heading: string; items: { action: string; label: string; icon: string; danger: boolean }[] }[]
74
75
  >([])
75
76
 
76
- /** Dispatches a component event to Vue listeners and, for controllers and page code, on the root. */
77
- function dispatch(name: string, detail?: unknown): boolean {
78
- const declared: Record<string, EventInit | undefined> = {
79
- action: { bubbles: true, composed: true, cancelable: false },
80
- }
81
- const checks: Record<string, (detail: unknown) => boolean> = {
82
- action: (detail) =>
83
- detail !== null && typeof detail === 'object' && !Array.isArray(detail)
84
- && ((detail as Record<string, unknown>)['action'] === 'align-left'
85
- || (detail as Record<string, unknown>)['action'] === 'align-center'
86
- || (detail as Record<string, unknown>)['action'] === 'align-right'
87
- || (detail as Record<string, unknown>)['action'] === 'background-none'
88
- || (detail as Record<string, unknown>)['action'] === 'background-gray'
89
- || (detail as Record<string, unknown>)['action'] === 'background-yellow'
90
- || (detail as Record<string, unknown>)['action'] === 'background-blue'
91
- || (detail as Record<string, unknown>)['action'] === 'background-green'
92
- || (detail as Record<string, unknown>)['action'] === 'background-red'
93
- || (detail as Record<string, unknown>)['action'] === 'add-row-before'
94
- || (detail as Record<string, unknown>)['action'] === 'add-row-after'
95
- || (detail as Record<string, unknown>)['action'] === 'add-column-before'
96
- || (detail as Record<string, unknown>)['action'] === 'add-column-after'
97
- || (detail as Record<string, unknown>)['action'] === 'clear-cells'
98
- || (detail as Record<string, unknown>)['action'] === 'merge-cells'
99
- || (detail as Record<string, unknown>)['action'] === 'split-cell'
100
- || (detail as Record<string, unknown>)['action'] === 'delete-row'
101
- || (detail as Record<string, unknown>)['action'] === 'delete-column'
102
- || (detail as Record<string, unknown>)['action'] === 'delete-table')
103
- && Object.keys(detail as object).every((key) => ['action'].includes(key)),
104
- }
105
- if (detail !== undefined && checks[name] !== undefined && !checks[name]!(detail)) {
106
- throw new TypeError(`HR002: Event \`${name}\` detail does not satisfy its declared type.`)
107
- }
108
- const emitEvent = emit as (name: string, detail: unknown) => void
109
- emitEvent(name, detail)
110
- return root.value?.dispatchEvent(
111
- new CustomEvent(name, { bubbles: true, composed: true, ...declared[name], detail }),
112
- ) ?? true
113
- }
114
-
115
- function read(name: string): unknown {
116
- if (name === 'swatches') return swatches.value
117
- if (name === 'sections') return sections.value
118
- return (props as Record<string, unknown>)[name]
119
- }
120
-
121
- function write(name: string, value: unknown): boolean {
122
- if (name === 'swatches') {
123
- swatches.value = value as never
124
- return true
125
- }
126
- if (name === 'sections') {
127
- sections.value = value as never
128
- return true
129
- }
130
- throw new TypeError(`Only declared state is writable; \`${name}\` is not.`)
131
- }
132
-
133
- const stops: Array<() => void> = []
134
- const host = {
135
- get element(): Element {
136
- return root.value as Element
137
- },
138
- state: new Proxy({} as Record<string, unknown>, {
139
- get: (_target, name) => typeof name === 'string' ? read(name) : undefined,
140
- set: (_target, name, value) => typeof name === 'string' && write(name, value),
141
- }),
142
- refs: {} as Readonly<Record<string, Element>>,
143
- elements: new Proxy({} as Record<string, Element | RadioNodeList | undefined>, {
144
- get: (_target, name) => {
145
- if (typeof name !== 'string' || root.value === null) return undefined
146
- const form = root.value instanceof HTMLFormElement
147
- ? root.value
148
- : root.value.querySelector('form')
149
- return form?.elements.namedItem(name)
150
- ?? root.value.querySelector(`[name="${CSS.escape(name)}"]`) ?? undefined
151
- },
152
- }),
153
- signal<T>(initialValue: T) {
154
- const value = shallowRef(initialValue)
155
- return {
156
- get: (): T => value.value,
157
- set: (next: T): void => {
158
- if (!Object.is(value.value, next)) value.value = next
159
- },
160
- update: (next: (current: T) => T): void => {
161
- const updated = next(value.value)
162
- if (!Object.is(value.value, updated)) value.value = updated
163
- },
164
- }
77
+ const isActionDetail = (detail: unknown): boolean =>
78
+ detail !== null && typeof detail === 'object' && !Array.isArray(detail)
79
+ && ((detail as Record<string, unknown>)['action'] === 'align-left'
80
+ || (detail as Record<string, unknown>)['action'] === 'align-center'
81
+ || (detail as Record<string, unknown>)['action'] === 'align-right'
82
+ || (detail as Record<string, unknown>)['action'] === 'background-none'
83
+ || (detail as Record<string, unknown>)['action'] === 'background-gray'
84
+ || (detail as Record<string, unknown>)['action'] === 'background-yellow'
85
+ || (detail as Record<string, unknown>)['action'] === 'background-blue'
86
+ || (detail as Record<string, unknown>)['action'] === 'background-green'
87
+ || (detail as Record<string, unknown>)['action'] === 'background-red'
88
+ || (detail as Record<string, unknown>)['action'] === 'add-row-before'
89
+ || (detail as Record<string, unknown>)['action'] === 'add-row-after'
90
+ || (detail as Record<string, unknown>)['action'] === 'add-column-before'
91
+ || (detail as Record<string, unknown>)['action'] === 'add-column-after'
92
+ || (detail as Record<string, unknown>)['action'] === 'clear-cells'
93
+ || (detail as Record<string, unknown>)['action'] === 'merge-cells'
94
+ || (detail as Record<string, unknown>)['action'] === 'split-cell'
95
+ || (detail as Record<string, unknown>)['action'] === 'delete-row'
96
+ || (detail as Record<string, unknown>)['action'] === 'delete-column'
97
+ || (detail as Record<string, unknown>)['action'] === 'delete-table')
98
+ && Object.keys(detail as object).every((key) => ['action'].includes(key))
99
+ const dispatch = createDispatch(root, emit as (name: string, detail: unknown) => void, {
100
+ checks: {
101
+ action: isActionDetail,
165
102
  },
166
- computed<T>(compute: () => T) {
167
- const value = computed(compute)
168
- return { get: (): T => value.value }
169
- },
170
- effect(run: () => void | (() => void)): () => void {
171
- const stop = watchEffect((onCleanup) => {
172
- const cleanup = run()
173
- if (typeof cleanup === 'function') onCleanup(cleanup)
174
- }, { flush: 'post' })
175
- stops.push(stop)
176
- return stop
177
- },
178
- on(event: string, listener: EventListener): () => void {
179
- const element = root.value
180
- element?.addEventListener(event, listener)
181
- const off = (): void => element?.removeEventListener(event, listener)
182
- stops.push(off)
183
- return off
184
- },
185
- dispatch,
186
- }
187
-
188
- let cleanup: void | (() => void)
189
- let ready: Promise<void> | undefined
190
- onMounted(() => {
191
- ready = Promise.resolve(controllerModule.default(host as never)).then((result) => {
192
- cleanup = result
193
- })
194
103
  })
195
- onBeforeUnmount(() => {
196
- for (const stop of stops.splice(0)) stop()
197
- if (typeof cleanup === 'function') cleanup()
104
+
105
+ useComponentHost(controllerModule.default, {
106
+ root,
107
+ dispatch,
108
+ props,
109
+ state: { swatches, sections },
198
110
  })
199
111
  </script>
200
112
 
@@ -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-editor-table-overlay/ui-editor-table-overlay.js'
5
+ import { createDispatch, useComponentHost } from './host'
5
6
  import UiIcon from './UiIcon.vue'
6
7
 
7
8
  defineOptions({ inheritAttrs: false })
@@ -104,174 +105,67 @@ const active = ref<
104
105
  >(null)
105
106
  const activeKey = ref('')
106
107
 
107
- /** Dispatches a component event to Vue listeners and, for controllers and page code, on the root. */
108
- function dispatch(name: string, detail?: unknown): boolean {
109
- const declared: Record<string, EventInit | undefined> = {
110
- action: { bubbles: true, composed: true, cancelable: false },
111
- }
112
- const checks: Record<string, (detail: unknown) => boolean> = {
113
- action: (detail) =>
114
- (detail !== null && typeof detail === 'object' && !Array.isArray(detail)
115
- && ((detail as Record<string, unknown>)['action'] === 'add-row-before'
116
- || (detail as Record<string, unknown>)['action'] === 'add-row-after'
117
- || (detail as Record<string, unknown>)['action'] === 'add-column-before'
118
- || (detail as Record<string, unknown>)['action'] === 'add-column-after')
119
- && Number.isInteger((detail as Record<string, unknown>)['boundaryIndex'])
120
- && Object.keys(detail as object).every((key) => ['action', 'boundaryIndex'].includes(key)))
121
- || (detail !== null && typeof detail === 'object' && !Array.isArray(detail)
122
- && ((detail as Record<string, unknown>)['action'] === 'select-row'
123
- || (detail as Record<string, unknown>)['action'] === 'select-column')
124
- && Number.isInteger((detail as Record<string, unknown>)['rowIndex'])
125
- && Number.isInteger((detail as Record<string, unknown>)['columnIndex'])
126
- && Object.keys(detail as object).every((key) =>
127
- ['action', 'rowIndex', 'columnIndex'].includes(key)
108
+ const isActionDetail = (detail: unknown): boolean =>
109
+ (detail !== null && typeof detail === 'object' && !Array.isArray(detail)
110
+ && ((detail as Record<string, unknown>)['action'] === 'add-row-before'
111
+ || (detail as Record<string, unknown>)['action'] === 'add-row-after'
112
+ || (detail as Record<string, unknown>)['action'] === 'add-column-before'
113
+ || (detail as Record<string, unknown>)['action'] === 'add-column-after')
114
+ && Number.isInteger((detail as Record<string, unknown>)['boundaryIndex'])
115
+ && Object.keys(detail as object).every((key) => ['action', 'boundaryIndex'].includes(key)))
116
+ || (detail !== null && typeof detail === 'object' && !Array.isArray(detail)
117
+ && ((detail as Record<string, unknown>)['action'] === 'select-row'
118
+ || (detail as Record<string, unknown>)['action'] === 'select-column')
119
+ && Number.isInteger((detail as Record<string, unknown>)['rowIndex'])
120
+ && Number.isInteger((detail as Record<string, unknown>)['columnIndex'])
121
+ && Object.keys(detail as object).every((key) =>
122
+ ['action', 'rowIndex', 'columnIndex'].includes(key)
123
+ ))
124
+ || (detail !== null && typeof detail === 'object' && !Array.isArray(detail)
125
+ && (detail as Record<string, unknown>)['action'] === 'open-cell-menu'
126
+ && Number.isInteger((detail as Record<string, unknown>)['rowIndex'])
127
+ && Number.isInteger((detail as Record<string, unknown>)['columnIndex'])
128
+ && ((detail as Record<string, unknown>)['anchor'] !== null
129
+ && typeof (detail as Record<string, unknown>)['anchor'] === 'object'
130
+ && !Array.isArray((detail as Record<string, unknown>)['anchor'])
131
+ && (typeof ((detail as Record<string, unknown>)['anchor'] as Record<string, unknown>)['left']
132
+ === 'number'
133
+ && Number.isFinite(
134
+ ((detail as Record<string, unknown>)['anchor'] as Record<string, unknown>)['left'],
128
135
  ))
129
- || (detail !== null && typeof detail === 'object' && !Array.isArray(detail)
130
- && (detail as Record<string, unknown>)['action'] === 'open-cell-menu'
131
- && Number.isInteger((detail as Record<string, unknown>)['rowIndex'])
132
- && Number.isInteger((detail as Record<string, unknown>)['columnIndex'])
133
- && ((detail as Record<string, unknown>)['anchor'] !== null
134
- && typeof (detail as Record<string, unknown>)['anchor'] === 'object'
135
- && !Array.isArray((detail as Record<string, unknown>)['anchor'])
136
- && (typeof ((detail as Record<string, unknown>)['anchor'] as Record<string, unknown>)[
137
- 'left'
138
- ] === 'number'
139
- && Number.isFinite(
140
- ((detail as Record<string, unknown>)['anchor'] as Record<string, unknown>)['left'],
141
- ))
142
- && (typeof ((detail as Record<string, unknown>)['anchor'] as Record<string, unknown>)[
143
- 'top'
144
- ] === 'number'
145
- && Number.isFinite(
146
- ((detail as Record<string, unknown>)['anchor'] as Record<string, unknown>)['top'],
147
- ))
148
- && (typeof ((detail as Record<string, unknown>)['anchor'] as Record<string, unknown>)[
149
- 'right'
150
- ] === 'number'
151
- && Number.isFinite(
152
- ((detail as Record<string, unknown>)['anchor'] as Record<string, unknown>)['right'],
153
- ))
154
- && (typeof ((detail as Record<string, unknown>)['anchor'] as Record<string, unknown>)[
155
- 'bottom'
156
- ] === 'number'
157
- && Number.isFinite(
158
- ((detail as Record<string, unknown>)['anchor'] as Record<string, unknown>)['bottom'],
159
- ))
160
- && Object.keys((detail as Record<string, unknown>)['anchor'] as object).every((key) =>
161
- ['left', 'top', 'right', 'bottom'].includes(key)
162
- ))
163
- && Object.keys(detail as object).every((key) =>
164
- ['action', 'rowIndex', 'columnIndex', 'anchor'].includes(key)
165
- )),
166
- }
167
- if (detail !== undefined && checks[name] !== undefined && !checks[name]!(detail)) {
168
- throw new TypeError(`HR002: Event \`${name}\` detail does not satisfy its declared type.`)
169
- }
170
- const emitEvent = emit as (name: string, detail: unknown) => void
171
- emitEvent(name, detail)
172
- return root.value?.dispatchEvent(
173
- new CustomEvent(name, { bubbles: true, composed: true, ...declared[name], detail }),
174
- ) ?? true
175
- }
176
-
177
- function read(name: string): unknown {
178
- if (name === 'rows') return rows.value
179
- if (name === 'cols') return cols.value
180
- if (name === 'hovered') return hovered.value
181
- if (name === 'active') return active.value
182
- if (name === 'activeKey') return activeKey.value
183
- return (props as Record<string, unknown>)[name]
184
- }
185
-
186
- function write(name: string, value: unknown): boolean {
187
- if (name === 'rows') {
188
- rows.value = value as never
189
- return true
190
- }
191
- if (name === 'cols') {
192
- cols.value = value as never
193
- return true
194
- }
195
- if (name === 'hovered') {
196
- hovered.value = value as never
197
- return true
198
- }
199
- if (name === 'active') {
200
- active.value = value as never
201
- return true
202
- }
203
- if (name === 'activeKey') {
204
- activeKey.value = value as never
205
- return true
206
- }
207
- throw new TypeError(`Only declared state is writable; \`${name}\` is not.`)
208
- }
209
-
210
- const stops: Array<() => void> = []
211
- const host = {
212
- get element(): Element {
213
- return root.value as Element
214
- },
215
- state: new Proxy({} as Record<string, unknown>, {
216
- get: (_target, name) => typeof name === 'string' ? read(name) : undefined,
217
- set: (_target, name, value) => typeof name === 'string' && write(name, value),
218
- }),
219
- refs: {} as Readonly<Record<string, Element>>,
220
- elements: new Proxy({} as Record<string, Element | RadioNodeList | undefined>, {
221
- get: (_target, name) => {
222
- if (typeof name !== 'string' || root.value === null) return undefined
223
- const form = root.value instanceof HTMLFormElement
224
- ? root.value
225
- : root.value.querySelector('form')
226
- return form?.elements.namedItem(name)
227
- ?? root.value.querySelector(`[name="${CSS.escape(name)}"]`) ?? undefined
228
- },
229
- }),
230
- signal<T>(initialValue: T) {
231
- const value = shallowRef(initialValue)
232
- return {
233
- get: (): T => value.value,
234
- set: (next: T): void => {
235
- if (!Object.is(value.value, next)) value.value = next
236
- },
237
- update: (next: (current: T) => T): void => {
238
- const updated = next(value.value)
239
- if (!Object.is(value.value, updated)) value.value = updated
240
- },
241
- }
242
- },
243
- computed<T>(compute: () => T) {
244
- const value = computed(compute)
245
- return { get: (): T => value.value }
246
- },
247
- effect(run: () => void | (() => void)): () => void {
248
- const stop = watchEffect((onCleanup) => {
249
- const cleanup = run()
250
- if (typeof cleanup === 'function') onCleanup(cleanup)
251
- }, { flush: 'post' })
252
- stops.push(stop)
253
- return stop
254
- },
255
- on(event: string, listener: EventListener): () => void {
256
- const element = root.value
257
- element?.addEventListener(event, listener)
258
- const off = (): void => element?.removeEventListener(event, listener)
259
- stops.push(off)
260
- return off
136
+ && (typeof ((detail as Record<string, unknown>)['anchor'] as Record<string, unknown>)['top']
137
+ === 'number'
138
+ && Number.isFinite(
139
+ ((detail as Record<string, unknown>)['anchor'] as Record<string, unknown>)['top'],
140
+ ))
141
+ && (typeof ((detail as Record<string, unknown>)['anchor'] as Record<string, unknown>)['right']
142
+ === 'number'
143
+ && Number.isFinite(
144
+ ((detail as Record<string, unknown>)['anchor'] as Record<string, unknown>)['right'],
145
+ ))
146
+ && (typeof ((detail as Record<string, unknown>)['anchor'] as Record<string, unknown>)[
147
+ 'bottom'
148
+ ] === 'number'
149
+ && Number.isFinite(
150
+ ((detail as Record<string, unknown>)['anchor'] as Record<string, unknown>)['bottom'],
151
+ ))
152
+ && Object.keys((detail as Record<string, unknown>)['anchor'] as object).every((key) =>
153
+ ['left', 'top', 'right', 'bottom'].includes(key)
154
+ ))
155
+ && Object.keys(detail as object).every((key) =>
156
+ ['action', 'rowIndex', 'columnIndex', 'anchor'].includes(key)
157
+ ))
158
+ const dispatch = createDispatch(root, emit as (name: string, detail: unknown) => void, {
159
+ checks: {
160
+ action: isActionDetail,
261
161
  },
262
- dispatch,
263
- }
264
-
265
- let cleanup: void | (() => void)
266
- let ready: Promise<void> | undefined
267
- onMounted(() => {
268
- ready = Promise.resolve(controllerModule.default(host as never)).then((result) => {
269
- cleanup = result
270
- })
271
162
  })
272
- onBeforeUnmount(() => {
273
- for (const stop of stops.splice(0)) stop()
274
- if (typeof cleanup === 'function') cleanup()
163
+
164
+ useComponentHost(controllerModule.default, {
165
+ root,
166
+ dispatch,
167
+ props,
168
+ state: { rows, cols, hovered, active, activeKey },
275
169
  })
276
170
  </script>
277
171