@prosekit/web 0.8.0-beta.0 → 0.8.0-beta.2

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 (207) hide show
  1. package/dist/prosekit-web-autocomplete.d.ts +112 -90
  2. package/dist/prosekit-web-autocomplete.d.ts.map +1 -1
  3. package/dist/prosekit-web-autocomplete.js +292 -217
  4. package/dist/prosekit-web-autocomplete.js.map +1 -1
  5. package/dist/prosekit-web-block-handle.d.ts +95 -62
  6. package/dist/prosekit-web-block-handle.d.ts.map +1 -1
  7. package/dist/prosekit-web-block-handle.js +219 -114
  8. package/dist/prosekit-web-block-handle.js.map +1 -1
  9. package/dist/prosekit-web-drop-indicator.d.ts +13 -15
  10. package/dist/prosekit-web-drop-indicator.d.ts.map +1 -1
  11. package/dist/prosekit-web-drop-indicator.js +34 -30
  12. package/dist/prosekit-web-drop-indicator.js.map +1 -1
  13. package/dist/prosekit-web-inline-popover.d.ts +94 -53
  14. package/dist/prosekit-web-inline-popover.d.ts.map +1 -1
  15. package/dist/prosekit-web-inline-popover.js +134 -79
  16. package/dist/prosekit-web-inline-popover.js.map +1 -1
  17. package/dist/prosekit-web-menu.d.ts +13 -0
  18. package/dist/prosekit-web-menu.d.ts.map +1 -0
  19. package/dist/prosekit-web-menu.js +53 -0
  20. package/dist/prosekit-web-menu.js.map +1 -0
  21. package/dist/prosekit-web-popover.d.ts +7 -26
  22. package/dist/prosekit-web-popover.d.ts.map +1 -1
  23. package/dist/prosekit-web-popover.js +31 -29
  24. package/dist/prosekit-web-popover.js.map +1 -1
  25. package/dist/prosekit-web-resizable.d.ts +92 -51
  26. package/dist/prosekit-web-resizable.d.ts.map +1 -1
  27. package/dist/prosekit-web-resizable.js +139 -131
  28. package/dist/prosekit-web-resizable.js.map +1 -1
  29. package/dist/prosekit-web-table-handle.d.ts +166 -199
  30. package/dist/prosekit-web-table-handle.d.ts.map +1 -1
  31. package/dist/prosekit-web-table-handle.js +495 -496
  32. package/dist/prosekit-web-table-handle.js.map +1 -1
  33. package/dist/prosekit-web-tooltip.d.ts +7 -26
  34. package/dist/prosekit-web-tooltip.d.ts.map +1 -1
  35. package/dist/prosekit-web-tooltip.js +31 -29
  36. package/dist/prosekit-web-tooltip.js.map +1 -1
  37. package/dist/use-editor-extension.js +2 -2
  38. package/dist/use-editor-extension.js.map +1 -1
  39. package/dist/use-scrolling.js +17 -8
  40. package/dist/use-scrolling.js.map +1 -1
  41. package/package.json +26 -21
  42. package/src/components/autocomplete/autocomplete-empty.ts +45 -0
  43. package/src/components/autocomplete/autocomplete-item.ts +65 -0
  44. package/src/components/autocomplete/autocomplete-popup.ts +95 -0
  45. package/src/components/autocomplete/autocomplete-positioner.ts +98 -0
  46. package/src/components/autocomplete/autocomplete-root.ts +280 -0
  47. package/src/components/autocomplete/context.ts +16 -14
  48. package/src/components/autocomplete/index.ts +65 -0
  49. package/src/components/block-handle/block-handle-add.ts +71 -0
  50. package/src/components/block-handle/block-handle-draggable.ts +158 -0
  51. package/src/components/block-handle/block-handle-popup.ts +43 -0
  52. package/src/components/block-handle/block-handle-positioner.ts +89 -0
  53. package/src/components/block-handle/block-handle-root.ts +116 -0
  54. package/src/components/block-handle/context.ts +9 -18
  55. package/src/components/block-handle/hover-state.ts +16 -0
  56. package/src/components/block-handle/index.ts +59 -0
  57. package/src/components/block-handle/{block-handle-popover/pointer-move.ts → pointer-move.ts} +8 -7
  58. package/src/components/block-handle/{block-handle-draggable/set-drag-preview.ts → set-drag-preview.ts} +4 -4
  59. package/src/components/block-handle/use-hover-extension.ts +65 -0
  60. package/src/components/drop-indicator/drop-indicator.ts +128 -0
  61. package/src/components/drop-indicator/index.ts +18 -0
  62. package/src/components/inline-popover/index.ts +41 -0
  63. package/src/components/inline-popover/inline-popover-popup.ts +52 -0
  64. package/src/components/inline-popover/inline-popover-positioner.ts +118 -0
  65. package/src/components/inline-popover/inline-popover-root.ts +122 -0
  66. package/src/components/inline-popover/store.ts +6 -0
  67. package/src/components/menu/index.ts +92 -0
  68. package/src/components/popover/index.ts +53 -0
  69. package/src/components/resizable/{resizable-handle/calc-resize.ts → calc-resize.ts} +1 -1
  70. package/src/components/resizable/context.ts +3 -6
  71. package/src/components/resizable/index.ts +32 -0
  72. package/src/components/resizable/resizable-handle.ts +134 -0
  73. package/src/components/resizable/resizable-root.ts +184 -0
  74. package/src/components/table-handle/dnd.ts +16 -27
  75. package/src/components/table-handle/index.ts +125 -0
  76. package/src/components/table-handle/{table-handle-drag-preview/render-preview.ts → render-preview.ts} +5 -5
  77. package/src/components/table-handle/shared.ts +61 -0
  78. package/src/components/table-handle/store.ts +117 -0
  79. package/src/components/table-handle/table-handle-column-menu-root.ts +51 -0
  80. package/src/components/table-handle/table-handle-column-menu-trigger.ts +107 -0
  81. package/src/components/table-handle/table-handle-column-popup.ts +44 -0
  82. package/src/components/table-handle/table-handle-column-positioner.ts +67 -0
  83. package/src/components/table-handle/table-handle-drag-preview.ts +169 -0
  84. package/src/components/table-handle/table-handle-drop-indicator.ts +166 -0
  85. package/src/components/table-handle/table-handle-root.ts +103 -0
  86. package/src/components/table-handle/table-handle-row-menu-root.ts +51 -0
  87. package/src/components/table-handle/table-handle-row-menu-trigger.ts +107 -0
  88. package/src/components/table-handle/table-handle-row-popup.ts +42 -0
  89. package/src/components/table-handle/table-handle-row-positioner.ts +67 -0
  90. package/src/components/table-handle/use-drop.ts +74 -0
  91. package/src/components/table-handle/{hooks/use-empty-image.ts → use-empty-image.ts} +2 -3
  92. package/src/components/table-handle/utils.ts +0 -11
  93. package/src/components/tooltip/index.ts +52 -0
  94. package/src/hooks/use-editor-extension.ts +4 -4
  95. package/src/hooks/use-editor-focus-event.ts +4 -4
  96. package/src/hooks/use-editor-typing.ts +12 -16
  97. package/src/hooks/use-editor-update-event.ts +4 -4
  98. package/src/hooks/use-keymap.ts +4 -4
  99. package/src/hooks/use-scrolling.ts +11 -10
  100. package/src/hooks/use-selecting.ts +8 -15
  101. package/src/utils/event.ts +28 -0
  102. package/src/utils/lazy-signal.spec.ts +68 -0
  103. package/src/utils/lazy-signal.ts +17 -0
  104. package/src/utils/prefers-reduced-motion.ts +6 -0
  105. package/src/utils/prevent-default.ts +3 -0
  106. package/src/utils/use-html-element-at.ts +17 -0
  107. package/src/utils/use-no-focus.ts +7 -0
  108. package/dist/get-default-state.js +0 -11
  109. package/dist/get-default-state.js.map +0 -1
  110. package/src/components/autocomplete/autocomplete-empty/element.gen.ts +0 -18
  111. package/src/components/autocomplete/autocomplete-empty/setup.ts +0 -6
  112. package/src/components/autocomplete/autocomplete-empty/types.ts +0 -13
  113. package/src/components/autocomplete/autocomplete-item/element.gen.ts +0 -18
  114. package/src/components/autocomplete/autocomplete-item/setup.ts +0 -30
  115. package/src/components/autocomplete/autocomplete-item/types.ts +0 -25
  116. package/src/components/autocomplete/autocomplete-list/element.gen.ts +0 -18
  117. package/src/components/autocomplete/autocomplete-list/setup.ts +0 -125
  118. package/src/components/autocomplete/autocomplete-list/types.ts +0 -22
  119. package/src/components/autocomplete/autocomplete-popover/element.gen.ts +0 -18
  120. package/src/components/autocomplete/autocomplete-popover/setup.ts +0 -169
  121. package/src/components/autocomplete/autocomplete-popover/types.ts +0 -100
  122. package/src/components/autocomplete/index.gen.ts +0 -17
  123. package/src/components/block-handle/block-handle-add/element.gen.ts +0 -18
  124. package/src/components/block-handle/block-handle-add/setup.ts +0 -33
  125. package/src/components/block-handle/block-handle-add/types.ts +0 -23
  126. package/src/components/block-handle/block-handle-draggable/element.gen.ts +0 -18
  127. package/src/components/block-handle/block-handle-draggable/setup.ts +0 -113
  128. package/src/components/block-handle/block-handle-draggable/types.ts +0 -23
  129. package/src/components/block-handle/block-handle-popover/element.gen.ts +0 -18
  130. package/src/components/block-handle/block-handle-popover/setup.ts +0 -68
  131. package/src/components/block-handle/block-handle-popover/types.ts +0 -81
  132. package/src/components/block-handle/index.gen.ts +0 -13
  133. package/src/components/drop-indicator/drop-indicator/element.gen.ts +0 -18
  134. package/src/components/drop-indicator/drop-indicator/setup.ts +0 -75
  135. package/src/components/drop-indicator/drop-indicator/types.ts +0 -31
  136. package/src/components/drop-indicator/index.gen.ts +0 -5
  137. package/src/components/inline-popover/index.gen.ts +0 -5
  138. package/src/components/inline-popover/inline-popover/element.gen.ts +0 -18
  139. package/src/components/inline-popover/inline-popover/setup.ts +0 -111
  140. package/src/components/inline-popover/inline-popover/types.ts +0 -112
  141. package/src/components/popover/index.gen.ts +0 -13
  142. package/src/components/popover/popover-content/element.gen.ts +0 -18
  143. package/src/components/popover/popover-content/setup.ts +0 -1
  144. package/src/components/popover/popover-content/types.ts +0 -6
  145. package/src/components/popover/popover-root/element.gen.ts +0 -18
  146. package/src/components/popover/popover-root/setup.ts +0 -1
  147. package/src/components/popover/popover-root/types.ts +0 -6
  148. package/src/components/popover/popover-trigger/element.gen.ts +0 -18
  149. package/src/components/popover/popover-trigger/setup.ts +0 -1
  150. package/src/components/popover/popover-trigger/types.ts +0 -6
  151. package/src/components/resizable/index.gen.ts +0 -9
  152. package/src/components/resizable/resizable-handle/element.gen.ts +0 -18
  153. package/src/components/resizable/resizable-handle/setup.ts +0 -106
  154. package/src/components/resizable/resizable-handle/types.ts +0 -29
  155. package/src/components/resizable/resizable-root/element.gen.ts +0 -18
  156. package/src/components/resizable/resizable-root/setup.ts +0 -84
  157. package/src/components/resizable/resizable-root/types.ts +0 -59
  158. package/src/components/table-handle/context.ts +0 -43
  159. package/src/components/table-handle/hooks/use-drop.ts +0 -85
  160. package/src/components/table-handle/index.gen.ts +0 -37
  161. package/src/components/table-handle/table-handle-column-root/element.gen.ts +0 -18
  162. package/src/components/table-handle/table-handle-column-root/setup.ts +0 -60
  163. package/src/components/table-handle/table-handle-column-root/types.ts +0 -73
  164. package/src/components/table-handle/table-handle-column-trigger/element.gen.ts +0 -18
  165. package/src/components/table-handle/table-handle-column-trigger/setup.ts +0 -64
  166. package/src/components/table-handle/table-handle-column-trigger/types.ts +0 -20
  167. package/src/components/table-handle/table-handle-drag-preview/element.gen.ts +0 -18
  168. package/src/components/table-handle/table-handle-drag-preview/setup.ts +0 -57
  169. package/src/components/table-handle/table-handle-drag-preview/types.ts +0 -14
  170. package/src/components/table-handle/table-handle-drag-preview/updater.ts +0 -90
  171. package/src/components/table-handle/table-handle-drop-indicator/element.gen.ts +0 -18
  172. package/src/components/table-handle/table-handle-drop-indicator/setup.ts +0 -52
  173. package/src/components/table-handle/table-handle-drop-indicator/types.ts +0 -15
  174. package/src/components/table-handle/table-handle-drop-indicator/updater.ts +0 -96
  175. package/src/components/table-handle/table-handle-popover-content/element.gen.ts +0 -18
  176. package/src/components/table-handle/table-handle-popover-content/setup.ts +0 -83
  177. package/src/components/table-handle/table-handle-popover-content/types.ts +0 -32
  178. package/src/components/table-handle/table-handle-popover-item/element.gen.ts +0 -18
  179. package/src/components/table-handle/table-handle-popover-item/setup.ts +0 -17
  180. package/src/components/table-handle/table-handle-popover-item/types.ts +0 -16
  181. package/src/components/table-handle/table-handle-root/element.gen.ts +0 -18
  182. package/src/components/table-handle/table-handle-root/setup.ts +0 -86
  183. package/src/components/table-handle/table-handle-root/types.ts +0 -23
  184. package/src/components/table-handle/table-handle-row-root/element.gen.ts +0 -18
  185. package/src/components/table-handle/table-handle-row-root/setup.ts +0 -70
  186. package/src/components/table-handle/table-handle-row-root/types.ts +0 -68
  187. package/src/components/table-handle/table-handle-row-trigger/element.gen.ts +0 -18
  188. package/src/components/table-handle/table-handle-row-trigger/setup.ts +0 -63
  189. package/src/components/table-handle/table-handle-row-trigger/types.ts +0 -23
  190. package/src/components/tooltip/index.gen.ts +0 -13
  191. package/src/components/tooltip/tooltip-content/element.gen.ts +0 -18
  192. package/src/components/tooltip/tooltip-content/setup.ts +0 -1
  193. package/src/components/tooltip/tooltip-content/types.ts +0 -6
  194. package/src/components/tooltip/tooltip-root/element.gen.ts +0 -18
  195. package/src/components/tooltip/tooltip-root/setup.ts +0 -1
  196. package/src/components/tooltip/tooltip-root/types.ts +0 -6
  197. package/src/components/tooltip/tooltip-trigger/element.gen.ts +0 -18
  198. package/src/components/tooltip/tooltip-trigger/setup.ts +0 -1
  199. package/src/components/tooltip/tooltip-trigger/types.ts +0 -6
  200. package/src/hooks/use-first-rendering.ts +0 -15
  201. package/src/utils/get-default-state.spec.ts +0 -42
  202. package/src/utils/get-default-state.ts +0 -18
  203. /package/src/components/autocomplete/{autocomplete-popover/helpers.spec.ts → helpers.spec.ts} +0 -0
  204. /package/src/components/autocomplete/{autocomplete-popover/helpers.ts → helpers.ts} +0 -0
  205. /package/src/components/inline-popover/{inline-popover/virtual-selection-element.ts → virtual-selection-element.ts} +0 -0
  206. /package/src/components/resizable/{resizable-handle/calc-resize.spec.ts → calc-resize.spec.ts} +0 -0
  207. /package/src/components/table-handle/{table-handle-drop-indicator/calc-drag-over.ts → calc-drag-over.ts} +0 -0
@@ -0,0 +1,74 @@
1
+ import { computed, useEffect, type HostElement } from '@aria-ui/core'
2
+ import type { Editor } from '@prosekit/core'
3
+ import { moveTableColumn, moveTableRow } from '@prosekit/extensions/table'
4
+
5
+ import { getSafeEditorView } from '../../utils/get-safe-editor-view.ts'
6
+
7
+ import type { TableHandleStore } from './store.ts'
8
+
9
+ export function useDrop(
10
+ host: HostElement,
11
+ getEditor: () => Editor | null,
12
+ store: TableHandleStore,
13
+ ): void {
14
+ const getDndStore = () => store.dndStore
15
+ const getDragging = computed(() => getDndStore().dragging.get())
16
+
17
+ useEffect(host, () => {
18
+ const view = getSafeEditorView(getEditor())
19
+ if (!view || !view.editable) return
20
+
21
+ const ownerDocument = view.dom?.ownerDocument
22
+ if (!ownerDocument) return
23
+
24
+ const handleDrop = () => {
25
+ if (!getDragging()) return
26
+ const editor = getEditor()
27
+ if (!editor) return
28
+
29
+ const dndStore = getDndStore()
30
+
31
+ const droppingIndex = dndStore.droppingIndex.get()
32
+ const draggingIndex = dndStore.draggingIndex.get()
33
+ const direction = dndStore.direction.get()
34
+
35
+ if (draggingIndex < 0 || droppingIndex < 0) {
36
+ console.warn('[prosekit] Invalid drag indices:', { draggingIndex, droppingIndex })
37
+ return
38
+ }
39
+
40
+ if (direction === 'row') {
41
+ editor.exec(moveTableRow({ from: draggingIndex, to: droppingIndex }))
42
+ return
43
+ }
44
+ if (direction === 'col') {
45
+ editor.exec(moveTableColumn({ from: draggingIndex, to: droppingIndex }))
46
+ return
47
+ }
48
+ }
49
+
50
+ const handleDragOver = (event: DragEvent) => {
51
+ if (!getDragging()) return
52
+ event.preventDefault()
53
+ const dndStore = getDndStore()
54
+ dndStore.dragging.set(true)
55
+ dndStore.x.set(event.clientX)
56
+ dndStore.y.set(event.clientY)
57
+ }
58
+
59
+ const handleDragEnd = () => {
60
+ if (!getDragging()) return
61
+ const dndStore = getDndStore()
62
+ dndStore.dragging.set(false)
63
+ }
64
+
65
+ ownerDocument.addEventListener('dragover', handleDragOver)
66
+ ownerDocument.addEventListener('drop', handleDrop)
67
+ ownerDocument.addEventListener('dragend', handleDragEnd)
68
+ return () => {
69
+ ownerDocument.removeEventListener('dragover', handleDragOver)
70
+ ownerDocument.removeEventListener('drop', handleDrop)
71
+ ownerDocument.removeEventListener('dragend', handleDragEnd)
72
+ }
73
+ })
74
+ }
@@ -1,5 +1,4 @@
1
- import type { ConnectableElement } from '@aria-ui/core'
2
- import { useEffect } from '@aria-ui/core'
1
+ import { useEffect, type HostElement } from '@aria-ui/core'
3
2
 
4
3
  /**
5
4
  * Returns a function that returns a 1x1 transparent image. This is used to
@@ -12,7 +11,7 @@ import { useEffect } from '@aria-ui/core'
12
11
  * @internal
13
12
  */
14
13
  export function useEmptyImage(
15
- host: ConnectableElement,
14
+ host: HostElement,
16
15
  ): () => HTMLImageElement | undefined {
17
16
  let image: HTMLImageElement | undefined
18
17
 
@@ -9,17 +9,6 @@ export interface HoveringCellInfo {
9
9
  colFirstCellPos: number
10
10
  }
11
11
 
12
- export interface DndInfo {
13
- dragging: boolean
14
- direction: 'row' | 'col'
15
- draggingIndex: number
16
- droppingIndex: number
17
- x: number
18
- y: number
19
- startX: number
20
- startY: number
21
- }
22
-
23
12
  export function isHoveringCellInfoEqual(
24
13
  a?: HoveringCellInfo | null,
25
14
  b?: HoveringCellInfo | null,
@@ -0,0 +1,52 @@
1
+ /**
2
+
3
+ @module
4
+
5
+ ## Anatomy
6
+
7
+ ```html
8
+ <prosekit-tooltip-root>
9
+ <prosekit-tooltip-trigger>...</prosekit-tooltip-trigger>
10
+ <prosekit-tooltip-positioner>
11
+ <prosekit-tooltip-popup>...</prosekit-tooltip-popup>
12
+ </prosekit-tooltip-positioner>
13
+ </prosekit-tooltip-root>
14
+ ```
15
+ */
16
+
17
+ import { registerCustomElement } from '@aria-ui/core'
18
+ import { TooltipPopupElement, TooltipPositionerElement, TooltipRootElement, TooltipTriggerElement } from '@aria-ui/elements/tooltip'
19
+
20
+ export {
21
+ OpenChangeEvent,
22
+ setupTooltipPopup,
23
+ setupTooltipPositioner,
24
+ setupTooltipRoot,
25
+ setupTooltipTrigger,
26
+ TooltipPopupElement,
27
+ TooltipPopupPropsDeclaration,
28
+ TooltipPositionerElement,
29
+ TooltipPositionerPropsDeclaration,
30
+ TooltipRootElement,
31
+ TooltipRootPropsDeclaration,
32
+ TooltipTriggerElement,
33
+ TooltipTriggerPropsDeclaration,
34
+ type TooltipPopupProps,
35
+ type TooltipPositionerProps,
36
+ type TooltipRootEvents,
37
+ type TooltipRootProps,
38
+ type TooltipTriggerProps,
39
+ } from '@aria-ui/elements/tooltip'
40
+
41
+ export function registerTooltipRootElement(): void {
42
+ registerCustomElement('prosekit-tooltip-root', TooltipRootElement)
43
+ }
44
+ export function registerTooltipTriggerElement(): void {
45
+ registerCustomElement('prosekit-tooltip-trigger', TooltipTriggerElement)
46
+ }
47
+ export function registerTooltipPopupElement(): void {
48
+ registerCustomElement('prosekit-tooltip-popup', TooltipPopupElement)
49
+ }
50
+ export function registerTooltipPositionerElement(): void {
51
+ registerCustomElement('prosekit-tooltip-positioner', TooltipPositionerElement)
52
+ }
@@ -1,12 +1,12 @@
1
- import { useEffect, type ConnectableElement, type ReadonlySignal } from '@aria-ui/core'
1
+ import { useEffect, type HostElement } from '@aria-ui/core'
2
2
  import type { Editor, Extension } from '@prosekit/core'
3
3
 
4
4
  export function useEditorExtension(
5
- host: ConnectableElement,
6
- editor: ReadonlySignal<Editor | null>,
5
+ host: HostElement,
6
+ getEditor: () => Editor | null,
7
7
  extension: Extension,
8
8
  ): void {
9
9
  useEffect(host, () => {
10
- return editor.get()?.use(extension)
10
+ return getEditor()?.use(extension)
11
11
  })
12
12
  }
@@ -1,4 +1,4 @@
1
- import type { ConnectableElement, ReadonlySignal } from '@aria-ui/core'
1
+ import type { HostElement } from '@aria-ui/core'
2
2
  import { defineFocusChangeHandler, type Editor, type FocusChangeHandler } from '@prosekit/core'
3
3
 
4
4
  import { useEditorExtension } from './use-editor-extension.ts'
@@ -7,10 +7,10 @@ import { useEditorExtension } from './use-editor-extension.ts'
7
7
  * @internal
8
8
  */
9
9
  export function useEditorFocusChangeEvent(
10
- host: ConnectableElement,
11
- editor: ReadonlySignal<Editor | null>,
10
+ host: HostElement,
11
+ getEditor: () => Editor | null,
12
12
  handler: FocusChangeHandler,
13
13
  ): void {
14
14
  const extension = defineFocusChangeHandler(handler)
15
- useEditorExtension(host, editor, extension)
15
+ useEditorExtension(host, getEditor, extension)
16
16
  }
@@ -1,28 +1,24 @@
1
- import { createSignal, type ConnectableElement, type ReadonlySignal } from '@aria-ui/core'
1
+ import { createSignal, type HostElement } from '@aria-ui/core'
2
2
  import { defineDOMEventHandler, union, type Editor } from '@prosekit/core'
3
3
 
4
4
  import { useEditorExtension } from './use-editor-extension.ts'
5
5
 
6
6
  export function useEditorTyping(
7
- host: ConnectableElement,
8
- editor: ReadonlySignal<Editor | null>,
9
- ): ReadonlySignal<boolean> {
7
+ host: HostElement,
8
+ getEditor: () => Editor | null,
9
+ ): () => boolean {
10
10
  const typing = createSignal(false)
11
11
 
12
- const handleKeypress = () => {
13
- typing.set(true)
14
- }
15
-
16
- const handlePointerMove = () => {
17
- typing.set(false)
18
- }
19
-
20
12
  const extension = union(
21
- defineDOMEventHandler('keypress', handleKeypress),
22
- defineDOMEventHandler('pointermove', handlePointerMove),
13
+ defineDOMEventHandler('keypress', () => {
14
+ typing.set(true)
15
+ }),
16
+ defineDOMEventHandler('pointermove', () => {
17
+ typing.set(false)
18
+ }),
23
19
  )
24
20
 
25
- useEditorExtension(host, editor, extension)
21
+ useEditorExtension(host, getEditor, extension)
26
22
 
27
- return typing
23
+ return typing.get
28
24
  }
@@ -1,4 +1,4 @@
1
- import type { ConnectableElement, ReadonlySignal } from '@aria-ui/core'
1
+ import type { HostElement } from '@aria-ui/core'
2
2
  import { defineUpdateHandler, type Editor, type UpdateHandler } from '@prosekit/core'
3
3
 
4
4
  import { useEditorExtension } from './use-editor-extension.ts'
@@ -7,10 +7,10 @@ import { useEditorExtension } from './use-editor-extension.ts'
7
7
  * @internal
8
8
  */
9
9
  export function useEditorUpdateEvent(
10
- host: ConnectableElement,
11
- editor: ReadonlySignal<Editor | null>,
10
+ host: HostElement,
11
+ getEditor: () => Editor | null,
12
12
  handler: UpdateHandler,
13
13
  ): void {
14
14
  const extension = defineUpdateHandler(handler)
15
- useEditorExtension(host, editor, extension)
15
+ useEditorExtension(host, getEditor, extension)
16
16
  }
@@ -1,13 +1,13 @@
1
- import type { ConnectableElement, ReadonlySignal } from '@aria-ui/core'
1
+ import type { HostElement } from '@aria-ui/core'
2
2
  import { defineKeymap, type Editor, type Keymap } from '@prosekit/core'
3
3
 
4
4
  import { useEditorExtension } from './use-editor-extension.ts'
5
5
 
6
6
  export function useKeymap(
7
- host: ConnectableElement,
8
- editor: ReadonlySignal<Editor | null>,
7
+ host: HostElement,
8
+ getEditor: () => Editor | null,
9
9
  keymap: Keymap,
10
10
  ): void {
11
11
  const extension = defineKeymap(keymap)
12
- useEditorExtension(host, editor, extension)
12
+ useEditorExtension(host, getEditor, extension)
13
13
  }
@@ -1,7 +1,7 @@
1
- import { createSignal, useEffect, type ConnectableElement, type ReadonlySignal } from '@aria-ui/core'
2
- import { getNearestOverflowAncestor } from '@zag-js/dom-query'
1
+ import { createSignal, useEffect, type HostElement } from '@aria-ui/core'
2
+ import { getNearestOverflowAncestor } from '@aria-ui/utils'
3
3
 
4
- export function useScrolling(host: ConnectableElement): ReadonlySignal<boolean> {
4
+ export function useScrolling(host: HostElement): () => boolean {
5
5
  const scrolling = createSignal(false)
6
6
 
7
7
  useEffect(host, () => {
@@ -15,16 +15,17 @@ export function useScrolling(host: ConnectableElement): ReadonlySignal<boolean>
15
15
  scrolling.set(false)
16
16
  }
17
17
 
18
- scrollableParent.addEventListener('scroll', handleScroll, { passive: true })
19
- window.addEventListener('mousemove', handleMouseMove, { passive: true })
20
- window.addEventListener('pointermove', handleMouseMove, { passive: true })
18
+ const abortController = new AbortController()
19
+ const abortSignal = abortController.signal
20
+
21
+ scrollableParent.addEventListener('scroll', handleScroll, { passive: true, signal: abortSignal })
22
+ window.addEventListener('mousemove', handleMouseMove, { passive: true, signal: abortSignal })
23
+ window.addEventListener('pointermove', handleMouseMove, { passive: true, signal: abortSignal })
21
24
 
22
25
  return () => {
23
- scrollableParent.removeEventListener('scroll', handleScroll)
24
- window.removeEventListener('mousemove', handleMouseMove)
25
- window.removeEventListener('pointermove', handleMouseMove)
26
+ abortController.abort()
26
27
  }
27
28
  })
28
29
 
29
- return scrolling
30
+ return scrolling.get
30
31
  }
@@ -1,5 +1,4 @@
1
- import type { ReadonlySignal } from '@aria-ui/core'
2
- import { createSignal, useEffect, type ConnectableElement } from '@aria-ui/core'
1
+ import { createSignal, useEffect, type HostElement } from '@aria-ui/core'
3
2
  import type { Editor } from '@prosekit/core'
4
3
 
5
4
  import { getSafeEditorView } from '../utils/get-safe-editor-view.ts'
@@ -9,25 +8,22 @@ import { getSafeEditorView } from '../utils/get-safe-editor-view.ts'
9
8
  * components should be disabled or hidden.
10
9
  */
11
10
  export function useSelecting(
12
- host: ConnectableElement,
13
- editor: ReadonlySignal<Editor | null>,
14
- enabled: ReadonlySignal<boolean>,
15
- ): ReadonlySignal<boolean> {
11
+ host: HostElement,
12
+ getEditor: () => Editor | null,
13
+ getEnabled: () => boolean,
14
+ ): () => boolean {
16
15
  const selecting = createSignal(false)
17
16
  const isPointerDown = createSignal(false)
18
17
 
19
18
  useEffect(host, () => {
20
- if (!enabled.get()) {
21
- return
22
- }
19
+ if (!getEnabled()) return
23
20
 
24
- const view = getSafeEditorView(editor.peek())
21
+ const view = getSafeEditorView(getEditor())
25
22
  if (!view) return
26
23
 
27
24
  const { dom, root } = view
28
25
  if (!root) return
29
26
 
30
- // When the user starts selecting text, we set the selecting signal to true.
31
27
  const handlePointerDown = () => {
32
28
  selecting.set(true)
33
29
  isPointerDown.set(true)
@@ -35,15 +31,12 @@ export function useSelecting(
35
31
  const handlePointerUp = () => {
36
32
  isPointerDown.set(false)
37
33
  }
38
- // When the user moves the pointer and the pointer is not down, we set the
39
- // selecting signal to false again.
40
34
  const handleMouseMove = () => {
41
35
  if (!isPointerDown.get()) {
42
36
  selecting.set(false)
43
37
  }
44
38
  }
45
39
 
46
- // Only listen to pointer down events on the editor
47
40
  dom.addEventListener('pointerdown', handlePointerDown)
48
41
  root.addEventListener('pointerup', handlePointerUp)
49
42
  root.addEventListener('pointermove', handleMouseMove)
@@ -55,5 +48,5 @@ export function useSelecting(
55
48
  }
56
49
  })
57
50
 
58
- return selecting
51
+ return selecting.get
59
52
  }
@@ -0,0 +1,28 @@
1
+ function cloneKeyboardEvent(source: KeyboardEvent): KeyboardEvent {
2
+ return new KeyboardEvent(source.type, {
3
+ code: source.code,
4
+ key: source.key,
5
+ location: source.location,
6
+ repeat: source.repeat,
7
+ altKey: source.altKey,
8
+ ctrlKey: source.ctrlKey,
9
+ metaKey: source.metaKey,
10
+ shiftKey: source.shiftKey,
11
+
12
+ view: source.view,
13
+ // internal bridge target; events don't need to bubble"
14
+ bubbles: false,
15
+ cancelable: true,
16
+ })
17
+ }
18
+
19
+ export class KeyboardEventTarget extends EventTarget {
20
+ override dispatchEvent(event: KeyboardEvent): boolean {
21
+ const newEvent = cloneKeyboardEvent(event)
22
+ const result: boolean = super.dispatchEvent(newEvent)
23
+ if (newEvent.defaultPrevented) {
24
+ event.preventDefault()
25
+ }
26
+ return result
27
+ }
28
+ }
@@ -0,0 +1,68 @@
1
+ import { computed, createSignal, type Signal } from '@aria-ui/core'
2
+ import { describe, expect, it } from 'vitest'
3
+
4
+ import { createLazySignal } from './lazy-signal.ts'
5
+
6
+ describe('createLazySignal', () => {
7
+ it('returns fallback when remote is undefined', () => {
8
+ const lazy = createLazySignal<number>(() => undefined, 42)
9
+ expect(lazy.get()).toBe(42)
10
+ })
11
+
12
+ it('delegates get to remote when resolved', () => {
13
+ const real = createSignal(10)
14
+ const lazy = createLazySignal<number>(() => real, 0)
15
+ expect(lazy.get()).toBe(10)
16
+ })
17
+
18
+ it('delegates set to remote when resolved', () => {
19
+ const real = createSignal(10)
20
+ const lazy = createLazySignal<number>(() => real, 0)
21
+ lazy.set(20)
22
+ expect(real.get()).toBe(20)
23
+ })
24
+
25
+ it('set is a no-op when remote is undefined', () => {
26
+ const lazy = createLazySignal<number>(() => undefined, 42)
27
+ expect(() => lazy.set(99)).not.toThrow()
28
+ expect(lazy.get()).toBe(42)
29
+ })
30
+
31
+ it('propagates reactivity when remote is bound late', () => {
32
+ const source = createSignal<Signal<number> | undefined>(undefined)
33
+ const lazy = createLazySignal<number>(() => source.get(), 0)
34
+ const derived = computed(() => lazy.get())
35
+
36
+ expect(derived()).toBe(0)
37
+
38
+ const real = createSignal(42)
39
+ source.set(real)
40
+ expect(derived()).toBe(42)
41
+
42
+ real.set(100)
43
+ expect(derived()).toBe(100)
44
+
45
+ real.set(200)
46
+ expect(derived()).toBe(200)
47
+ })
48
+
49
+ it('releases old dependency when remote is reparented', () => {
50
+ const source = createSignal<Signal<number> | undefined>(undefined)
51
+ const lazy = createLazySignal<number>(() => source.get(), 0)
52
+ const derived = computed(() => lazy.get())
53
+
54
+ const a = createSignal(1)
55
+ source.set(a)
56
+ expect(derived()).toBe(1)
57
+
58
+ const b = createSignal(100)
59
+ source.set(b)
60
+ expect(derived()).toBe(100)
61
+
62
+ a.set(999)
63
+ expect(derived()).toBe(100)
64
+
65
+ b.set(200)
66
+ expect(derived()).toBe(200)
67
+ })
68
+ })
@@ -0,0 +1,17 @@
1
+ import type { Signal } from '@aria-ui/core'
2
+
3
+ export function createLazySignal<T>(
4
+ getRemote: () => Signal<T> | undefined,
5
+ fallback: T,
6
+ ): Signal<T> {
7
+ return {
8
+ get: (): T => {
9
+ const remote = getRemote()
10
+ return remote ? remote.get() : fallback
11
+ },
12
+ set: (value: T): void => {
13
+ const remote = getRemote()
14
+ if (remote) remote.set(value)
15
+ },
16
+ }
17
+ }
@@ -0,0 +1,6 @@
1
+ export function prefersReducedMotion(): boolean {
2
+ if (typeof window === 'undefined') {
3
+ return false
4
+ }
5
+ return window.matchMedia('(prefers-reduced-motion: reduce)').matches
6
+ }
@@ -0,0 +1,3 @@
1
+ export function preventDefault(event: Event): void {
2
+ event.preventDefault()
3
+ }
@@ -0,0 +1,17 @@
1
+ import { computed } from '@aria-ui/core'
2
+ import { isHTMLElement } from '@ocavue/utils'
3
+ import type { Editor } from '@prosekit/core'
4
+
5
+ export function useHTMLElementAt(
6
+ getEditor: () => Editor | null | undefined,
7
+ getPos: () => number | null | undefined,
8
+ ): () => HTMLElement | undefined {
9
+ return computed(() => {
10
+ const editor = getEditor()
11
+ const pos = getPos()
12
+ if (!editor || !pos) return
13
+ const view = editor.view
14
+ const element = view.nodeDOM(pos)
15
+ if (element && isHTMLElement(element)) return element
16
+ })
17
+ }
@@ -0,0 +1,7 @@
1
+ import { onMount, type HostElement } from '@aria-ui/core'
2
+
3
+ export function useNoFocus(host: HostElement): void {
4
+ onMount(host, () => {
5
+ host.tabIndex = -1
6
+ })
7
+ }
@@ -1,11 +0,0 @@
1
- import { createSignal } from "@aria-ui/core";
2
- //#region src/utils/get-default-state.ts
3
- function getStateWithDefaults(state, props) {
4
- const merged = { ...state };
5
- for (const key of Object.keys(props)) if (!merged[key]) merged[key] = createSignal(props[key].default);
6
- return merged;
7
- }
8
- //#endregion
9
- export { getStateWithDefaults as t };
10
-
11
- //# sourceMappingURL=get-default-state.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"get-default-state.js","names":[],"sources":["../src/utils/get-default-state.ts"],"sourcesContent":["import { createSignal, type PropDeclarations, type SignalState } from '@aria-ui/core'\n\nexport function getStateWithDefaults<\n Props extends Record<string, any> = Record<string, any>,\n>(\n state: Partial<SignalState<Props>>,\n props: PropDeclarations<Props>,\n): SignalState<Props> {\n const merged = { ...state } as SignalState<Props>\n\n for (const key of Object.keys(props) as (keyof Props)[]) {\n if (!merged[key]) {\n merged[key] = createSignal(props[key].default)\n }\n }\n\n return merged\n}\n"],"mappings":";;AAEA,SAAgB,qBAGd,OACA,OACoB;CACpB,MAAM,SAAS,EAAE,GAAG,OAAO;AAE3B,MAAK,MAAM,OAAO,OAAO,KAAK,MAAM,CAClC,KAAI,CAAC,OAAO,KACV,QAAO,OAAO,aAAa,MAAM,KAAK,QAAQ;AAIlD,QAAO"}
@@ -1,18 +0,0 @@
1
- import { defineCustomElement, registerCustomElement, type BaseElementConstructor } from "@aria-ui/core"
2
-
3
- import { useAutocompleteEmpty } from "./setup.ts"
4
- import { autocompleteEmptyEvents, autocompleteEmptyProps, type AutocompleteEmptyEvents, type AutocompleteEmptyProps } from "./types.ts"
5
-
6
- const AutocompleteEmptyElementBase: BaseElementConstructor<AutocompleteEmptyProps> = defineCustomElement<
7
- AutocompleteEmptyProps,
8
- AutocompleteEmptyEvents
9
- >({
10
- props: autocompleteEmptyProps,
11
- events: autocompleteEmptyEvents,
12
- setup: useAutocompleteEmpty,
13
- })
14
- class AutocompleteEmptyElement extends AutocompleteEmptyElementBase {}
15
-
16
- registerCustomElement('prosekit-autocomplete-empty', AutocompleteEmptyElement)
17
-
18
- export { AutocompleteEmptyElement }
@@ -1,6 +0,0 @@
1
- import { useListboxEmpty } from '@aria-ui/listbox/elements'
2
-
3
- /**
4
- * @internal
5
- */
6
- export const useAutocompleteEmpty: typeof useListboxEmpty = useListboxEmpty
@@ -1,13 +0,0 @@
1
- import type { EventDeclarations, PropDeclarations } from '@aria-ui/core'
2
-
3
- /** @internal */
4
- export interface AutocompleteEmptyProps {}
5
-
6
- /** @internal */
7
- export const autocompleteEmptyProps: PropDeclarations<AutocompleteEmptyProps> = {}
8
-
9
- /** @internal */
10
- export interface AutocompleteEmptyEvents {}
11
-
12
- /** @internal */
13
- export const autocompleteEmptyEvents: EventDeclarations<AutocompleteEmptyEvents> = {}
@@ -1,18 +0,0 @@
1
- import { defineCustomElement, registerCustomElement, type BaseElementConstructor } from "@aria-ui/core"
2
-
3
- import { useAutocompleteItem } from "./setup.ts"
4
- import { autocompleteItemEvents, autocompleteItemProps, type AutocompleteItemEvents, type AutocompleteItemProps } from "./types.ts"
5
-
6
- const AutocompleteItemElementBase: BaseElementConstructor<AutocompleteItemProps> = defineCustomElement<
7
- AutocompleteItemProps,
8
- AutocompleteItemEvents
9
- >({
10
- props: autocompleteItemProps,
11
- events: autocompleteItemEvents,
12
- setup: useAutocompleteItem,
13
- })
14
- class AutocompleteItemElement extends AutocompleteItemElementBase {}
15
-
16
- registerCustomElement('prosekit-autocomplete-item', AutocompleteItemElement)
17
-
18
- export { AutocompleteItemElement }
@@ -1,30 +0,0 @@
1
- import { useEffect, useEventListener, type ConnectableElement, type SetupOptions } from '@aria-ui/core'
2
- import { useListboxItem } from '@aria-ui/listbox/elements'
3
-
4
- import { openContext } from '../context.ts'
5
-
6
- import type { AutocompleteItemEvents, AutocompleteItemProps } from './types.ts'
7
-
8
- /**
9
- * @internal
10
- */
11
- export function useAutocompleteItem(
12
- element: ConnectableElement,
13
- { state, emit }: SetupOptions<AutocompleteItemProps, AutocompleteItemEvents>,
14
- ): void {
15
- useListboxItem(element, { state, emit })
16
-
17
- const open = openContext.consume(element)
18
-
19
- useEffect(element, () => {
20
- // Check the text content again when the open state changes
21
- if (!state.value.peek() && open.get()) {
22
- state.value.set(element.textContent ?? '')
23
- }
24
- })
25
-
26
- useEventListener(element, 'pointerdown', (event) => {
27
- // Prevent the editor from losing focus
28
- event.preventDefault()
29
- })
30
- }