@prosekit/web 0.7.2 → 0.7.4
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.
- package/dist/get-default-state-CIEy7xrl.js +2 -1
- package/dist/get-default-state-CIEy7xrl.js.map +1 -0
- package/dist/get-safe-editor-view-DENm4avv.js +2 -1
- package/dist/get-safe-editor-view-DENm4avv.js.map +1 -0
- package/dist/{inject-style-RwRNoINh.js → inject-style-BJQNFufI.js} +12 -13
- package/dist/inject-style-BJQNFufI.js.map +1 -0
- package/dist/prosekit-web-autocomplete.d.ts +2 -1
- package/dist/prosekit-web-autocomplete.d.ts.map +1 -0
- package/dist/prosekit-web-autocomplete.js +5 -7
- package/dist/prosekit-web-autocomplete.js.map +1 -0
- package/dist/prosekit-web-block-handle.d.ts +2 -1
- package/dist/prosekit-web-block-handle.d.ts.map +1 -0
- package/dist/prosekit-web-block-handle.js +33 -20
- package/dist/prosekit-web-block-handle.js.map +1 -0
- package/dist/prosekit-web-drop-indicator.d.ts +2 -1
- package/dist/prosekit-web-drop-indicator.d.ts.map +1 -0
- package/dist/prosekit-web-drop-indicator.js +2 -1
- package/dist/prosekit-web-drop-indicator.js.map +1 -0
- package/dist/prosekit-web-inline-popover.d.ts +2 -1
- package/dist/prosekit-web-inline-popover.d.ts.map +1 -0
- package/dist/prosekit-web-inline-popover.js +4 -5
- package/dist/prosekit-web-inline-popover.js.map +1 -0
- package/dist/prosekit-web-popover.d.ts +2 -1
- package/dist/prosekit-web-popover.d.ts.map +1 -0
- package/dist/prosekit-web-popover.js +2 -1
- package/dist/prosekit-web-popover.js.map +1 -0
- package/dist/prosekit-web-resizable.d.ts +2 -1
- package/dist/prosekit-web-resizable.d.ts.map +1 -0
- package/dist/prosekit-web-resizable.js +2 -1
- package/dist/prosekit-web-resizable.js.map +1 -0
- package/dist/prosekit-web-table-handle.d.ts +2 -1
- package/dist/prosekit-web-table-handle.d.ts.map +1 -0
- package/dist/prosekit-web-table-handle.js +38 -75
- package/dist/prosekit-web-table-handle.js.map +1 -0
- package/dist/prosekit-web-tooltip.d.ts +2 -1
- package/dist/prosekit-web-tooltip.d.ts.map +1 -0
- package/dist/prosekit-web-tooltip.js +2 -1
- package/dist/prosekit-web-tooltip.js.map +1 -0
- package/dist/prosekit-web.d.ts +1 -1
- package/dist/prosekit-web.js +1 -0
- package/dist/use-editor-extension-Cc7ZG7uj.js +2 -1
- package/dist/use-editor-extension-Cc7ZG7uj.js.map +1 -0
- package/dist/use-scrolling-BNfsQs3S.js +2 -1
- package/dist/use-scrolling-BNfsQs3S.js.map +1 -0
- package/package.json +21 -20
- package/src/components/autocomplete/autocomplete-empty/element.gen.ts +18 -0
- package/src/components/autocomplete/autocomplete-empty/setup.ts +6 -0
- package/src/components/autocomplete/autocomplete-empty/types.ts +16 -0
- package/src/components/autocomplete/autocomplete-item/element.gen.ts +18 -0
- package/src/components/autocomplete/autocomplete-item/setup.ts +38 -0
- package/src/components/autocomplete/autocomplete-item/types.ts +31 -0
- package/src/components/autocomplete/autocomplete-list/element.gen.ts +18 -0
- package/src/components/autocomplete/autocomplete-list/setup.ts +140 -0
- package/src/components/autocomplete/autocomplete-list/types.ts +30 -0
- package/src/components/autocomplete/autocomplete-popover/element.gen.ts +18 -0
- package/src/components/autocomplete/autocomplete-popover/helpers.spec.ts +21 -0
- package/src/components/autocomplete/autocomplete-popover/helpers.ts +7 -0
- package/src/components/autocomplete/autocomplete-popover/setup.ts +185 -0
- package/src/components/autocomplete/autocomplete-popover/types.ts +103 -0
- package/src/components/autocomplete/context.ts +19 -0
- package/src/components/autocomplete/index.gen.ts +17 -0
- package/src/components/block-handle/block-handle-add/element.gen.ts +18 -0
- package/src/components/block-handle/block-handle-add/setup.ts +37 -0
- package/src/components/block-handle/block-handle-add/types.ts +26 -0
- package/src/components/block-handle/block-handle-draggable/element.gen.ts +18 -0
- package/src/components/block-handle/block-handle-draggable/set-drag-preview.ts +88 -0
- package/src/components/block-handle/block-handle-draggable/setup.ts +133 -0
- package/src/components/block-handle/block-handle-draggable/types.ts +26 -0
- package/src/components/block-handle/block-handle-popover/element.gen.ts +18 -0
- package/src/components/block-handle/block-handle-popover/pointer-move.ts +243 -0
- package/src/components/block-handle/block-handle-popover/setup.ts +88 -0
- package/src/components/block-handle/block-handle-popover/types.ts +84 -0
- package/src/components/block-handle/context.ts +34 -0
- package/src/components/block-handle/index.gen.ts +13 -0
- package/src/components/drop-indicator/drop-indicator/element.gen.ts +18 -0
- package/src/components/drop-indicator/drop-indicator/setup.ts +87 -0
- package/src/components/drop-indicator/drop-indicator/types.ts +34 -0
- package/src/components/drop-indicator/index.gen.ts +5 -0
- package/src/components/inline-popover/index.gen.ts +5 -0
- package/src/components/inline-popover/inline-popover/element.gen.ts +18 -0
- package/src/components/inline-popover/inline-popover/setup.ts +97 -0
- package/src/components/inline-popover/inline-popover/types.ts +115 -0
- package/src/components/inline-popover/inline-popover/virtual-selection-element.ts +75 -0
- package/src/components/popover/index.gen.ts +13 -0
- package/src/components/popover/popover-content/element.gen.ts +18 -0
- package/src/components/popover/popover-content/setup.ts +1 -0
- package/src/components/popover/popover-content/types.ts +12 -0
- package/src/components/popover/popover-root/element.gen.ts +18 -0
- package/src/components/popover/popover-root/setup.ts +1 -0
- package/src/components/popover/popover-root/types.ts +12 -0
- package/src/components/popover/popover-trigger/element.gen.ts +18 -0
- package/src/components/popover/popover-trigger/setup.ts +1 -0
- package/src/components/popover/popover-trigger/types.ts +12 -0
- package/src/components/resizable/context.ts +45 -0
- package/src/components/resizable/index.gen.ts +9 -0
- package/src/components/resizable/resizable-handle/calc-resize.spec.ts +280 -0
- package/src/components/resizable/resizable-handle/calc-resize.ts +121 -0
- package/src/components/resizable/resizable-handle/element.gen.ts +18 -0
- package/src/components/resizable/resizable-handle/setup.ts +112 -0
- package/src/components/resizable/resizable-handle/types.ts +32 -0
- package/src/components/resizable/resizable-root/element.gen.ts +18 -0
- package/src/components/resizable/resizable-root/setup.ts +93 -0
- package/src/components/resizable/resizable-root/types.ts +28 -0
- package/src/components/table-handle/context.ts +49 -0
- package/src/components/table-handle/dnd.ts +135 -0
- package/src/components/table-handle/hooks/use-drop.ts +94 -0
- package/src/components/table-handle/hooks/use-empty-image.ts +30 -0
- package/src/components/table-handle/index.gen.ts +37 -0
- package/src/components/table-handle/table-handle-column-root/element.gen.ts +18 -0
- package/src/components/table-handle/table-handle-column-root/setup.ts +71 -0
- package/src/components/table-handle/table-handle-column-root/types.ts +76 -0
- package/src/components/table-handle/table-handle-column-trigger/element.gen.ts +18 -0
- package/src/components/table-handle/table-handle-column-trigger/setup.ts +75 -0
- package/src/components/table-handle/table-handle-column-trigger/types.ts +23 -0
- package/src/components/table-handle/table-handle-drag-preview/element.gen.ts +18 -0
- package/src/components/table-handle/table-handle-drag-preview/render-preview.ts +80 -0
- package/src/components/table-handle/table-handle-drag-preview/setup.ts +67 -0
- package/src/components/table-handle/table-handle-drag-preview/types.ts +17 -0
- package/src/components/table-handle/table-handle-drag-preview/updater.ts +101 -0
- package/src/components/table-handle/table-handle-drop-indicator/calc-drag-over.ts +44 -0
- package/src/components/table-handle/table-handle-drop-indicator/element.gen.ts +18 -0
- package/src/components/table-handle/table-handle-drop-indicator/setup.ts +56 -0
- package/src/components/table-handle/table-handle-drop-indicator/types.ts +18 -0
- package/src/components/table-handle/table-handle-drop-indicator/updater.ts +110 -0
- package/src/components/table-handle/table-handle-popover-content/element.gen.ts +18 -0
- package/src/components/table-handle/table-handle-popover-content/setup.ts +90 -0
- package/src/components/table-handle/table-handle-popover-content/types.ts +40 -0
- package/src/components/table-handle/table-handle-popover-item/element.gen.ts +18 -0
- package/src/components/table-handle/table-handle-popover-item/setup.ts +23 -0
- package/src/components/table-handle/table-handle-popover-item/types.ts +24 -0
- package/src/components/table-handle/table-handle-root/element.gen.ts +18 -0
- package/src/components/table-handle/table-handle-root/setup.ts +93 -0
- package/src/components/table-handle/table-handle-root/types.ts +26 -0
- package/src/components/table-handle/table-handle-row-root/element.gen.ts +18 -0
- package/src/components/table-handle/table-handle-row-root/setup.ts +77 -0
- package/src/components/table-handle/table-handle-row-root/types.ts +75 -0
- package/src/components/table-handle/table-handle-row-trigger/element.gen.ts +18 -0
- package/src/components/table-handle/table-handle-row-trigger/setup.ts +74 -0
- package/src/components/table-handle/table-handle-row-trigger/types.ts +26 -0
- package/src/components/table-handle/utils.ts +107 -0
- package/src/components/tooltip/index.gen.ts +13 -0
- package/src/components/tooltip/tooltip-content/element.gen.ts +18 -0
- package/src/components/tooltip/tooltip-content/setup.ts +1 -0
- package/src/components/tooltip/tooltip-content/types.ts +12 -0
- package/src/components/tooltip/tooltip-root/element.gen.ts +18 -0
- package/src/components/tooltip/tooltip-root/setup.ts +1 -0
- package/src/components/tooltip/tooltip-root/types.ts +12 -0
- package/src/components/tooltip/tooltip-trigger/element.gen.ts +18 -0
- package/src/components/tooltip/tooltip-trigger/setup.ts +1 -0
- package/src/components/tooltip/tooltip-trigger/types.ts +12 -0
- package/src/hooks/use-editor-extension.ts +19 -0
- package/src/hooks/use-editor-focus-event.ts +23 -0
- package/src/hooks/use-editor-typing.ts +36 -0
- package/src/hooks/use-editor-update-event.ts +23 -0
- package/src/hooks/use-first-rendering.ts +20 -0
- package/src/hooks/use-keymap.ts +20 -0
- package/src/hooks/use-scrolling.ts +33 -0
- package/src/hooks/use-selecting.ts +63 -0
- package/src/index.ts +1 -0
- package/src/utils/assign-styles.ts +14 -0
- package/src/utils/clone-element.ts +110 -0
- package/src/utils/css-feature-detection.ts +9 -0
- package/src/utils/fade-color.ts +15 -0
- package/src/utils/get-box-element.ts +20 -0
- package/src/utils/get-client-rect.ts +35 -0
- package/src/utils/get-default-state.spec.ts +50 -0
- package/src/utils/get-default-state.ts +22 -0
- package/src/utils/get-effective-background-color.ts +21 -0
- package/src/utils/get-safe-editor-view.ts +10 -0
- package/src/utils/inject-style.ts +11 -0
- package/src/utils/is-finite-positive-number.ts +3 -0
- package/src/utils/max-z-index.ts +3 -0
- package/src/utils/throttle.ts +17 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { assignStyles } from '../../../utils/assign-styles'
|
|
2
|
+
import {
|
|
3
|
+
cloneElement,
|
|
4
|
+
deepCloneElement,
|
|
5
|
+
} from '../../../utils/clone-element'
|
|
6
|
+
import { fadeColor } from '../../../utils/fade-color'
|
|
7
|
+
import { getEffectiveBackgroundColor } from '../../../utils/get-effective-background-color'
|
|
8
|
+
import { injectStyle } from '../../../utils/inject-style'
|
|
9
|
+
|
|
10
|
+
export function clearPreviewDOM(previewRoot: HTMLElement): void {
|
|
11
|
+
while (previewRoot.firstChild) {
|
|
12
|
+
previewRoot.removeChild(previewRoot.firstChild)
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function createPreviewDOM(
|
|
17
|
+
table: HTMLTableElement,
|
|
18
|
+
previewRoot: HTMLElement,
|
|
19
|
+
index: number,
|
|
20
|
+
direction: 'row' | 'col',
|
|
21
|
+
): void {
|
|
22
|
+
clearPreviewDOM(previewRoot)
|
|
23
|
+
|
|
24
|
+
const [previewTable, previewTableStyle] = cloneElement(table)
|
|
25
|
+
injectStyle(previewRoot, previewTableStyle)
|
|
26
|
+
unsetSize(previewTable)
|
|
27
|
+
|
|
28
|
+
const tableBody = table.querySelector('tbody')
|
|
29
|
+
const [previewTableBody, previewTableBodyStyle] = tableBody
|
|
30
|
+
? cloneElement(tableBody)
|
|
31
|
+
: [table.ownerDocument.createElement('tbody'), '']
|
|
32
|
+
injectStyle(previewRoot, previewTableBodyStyle)
|
|
33
|
+
unsetSize(previewTableBody)
|
|
34
|
+
|
|
35
|
+
// Get effective background color and apply it with some opacity
|
|
36
|
+
const backgroundColor = getEffectiveBackgroundColor(table)
|
|
37
|
+
if (backgroundColor) {
|
|
38
|
+
const backgroundColorWithOpacity = fadeColor(backgroundColor, 0.8)
|
|
39
|
+
if (backgroundColorWithOpacity) {
|
|
40
|
+
assignStyles(previewTable, { backgroundColor: backgroundColorWithOpacity })
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
previewTable.appendChild(previewTableBody)
|
|
45
|
+
previewRoot.appendChild(previewTable)
|
|
46
|
+
|
|
47
|
+
const rows = table.querySelectorAll('tr')
|
|
48
|
+
|
|
49
|
+
if (direction === 'row') {
|
|
50
|
+
const row = rows[index]
|
|
51
|
+
const [previewRow, previewRowStyle] = deepCloneElement(row)
|
|
52
|
+
injectStyle(previewRoot, previewRowStyle)
|
|
53
|
+
previewTableBody.appendChild(previewRow)
|
|
54
|
+
} else {
|
|
55
|
+
rows.forEach((row) => {
|
|
56
|
+
const [previewRow, previewRowStyle] = cloneElement(row)
|
|
57
|
+
injectStyle(previewRoot, previewRowStyle)
|
|
58
|
+
unsetSize(previewRow)
|
|
59
|
+
const cells = row.querySelectorAll('td')
|
|
60
|
+
const cell = cells[index]
|
|
61
|
+
if (cell) {
|
|
62
|
+
const [previewCell, previewCellStyle] = deepCloneElement(cell)
|
|
63
|
+
injectStyle(previewRoot, previewCellStyle)
|
|
64
|
+
previewRow.appendChild(previewCell)
|
|
65
|
+
previewTableBody.appendChild(previewRow)
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function unsetSize(element: HTMLElement) {
|
|
72
|
+
assignStyles(element, {
|
|
73
|
+
width: 'unset',
|
|
74
|
+
height: 'unset',
|
|
75
|
+
minWidth: 'unset',
|
|
76
|
+
minHeight: 'unset',
|
|
77
|
+
maxWidth: 'unset',
|
|
78
|
+
maxHeight: 'unset',
|
|
79
|
+
})
|
|
80
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useEffect,
|
|
3
|
+
type ConnectableElement,
|
|
4
|
+
type SignalState,
|
|
5
|
+
} from '@aria-ui/core'
|
|
6
|
+
|
|
7
|
+
import { assignStyles } from '../../../utils/assign-styles'
|
|
8
|
+
import {
|
|
9
|
+
useInitDndPosition,
|
|
10
|
+
type OnInitParams,
|
|
11
|
+
} from '../dnd'
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
clearPreviewDOM,
|
|
15
|
+
createPreviewDOM,
|
|
16
|
+
} from './render-preview'
|
|
17
|
+
import type { TableHandleDragPreviewProps } from './types'
|
|
18
|
+
import { useUpdatePreviewPosition } from './updater'
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @internal
|
|
22
|
+
*/
|
|
23
|
+
export function useTableHandleDragPreview(host: ConnectableElement, { state }: { state: SignalState<TableHandleDragPreviewProps> }): void {
|
|
24
|
+
const { editor } = state
|
|
25
|
+
|
|
26
|
+
useEffect(host, () => {
|
|
27
|
+
assignStyles(host, {
|
|
28
|
+
position: 'absolute',
|
|
29
|
+
// Make sure drop on preview will trigger drop event on the host
|
|
30
|
+
pointerEvents: 'none',
|
|
31
|
+
})
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
useInitDndPosition(host, editor, onInitPreviewPosition)
|
|
35
|
+
|
|
36
|
+
useUpdatePreviewPosition(host, editor)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function onInitPreviewPosition({ host, direction, dragging, table, cell, draggingIndex }: OnInitParams): void {
|
|
40
|
+
assignStyles(host, {
|
|
41
|
+
display: dragging ? 'block' : 'none',
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
if (!dragging) {
|
|
45
|
+
clearPreviewDOM(host)
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
createPreviewDOM(table, host, draggingIndex, direction)
|
|
50
|
+
|
|
51
|
+
const tableRect = table.getBoundingClientRect()
|
|
52
|
+
const cellRect = cell.getBoundingClientRect()
|
|
53
|
+
|
|
54
|
+
if (direction === 'col') {
|
|
55
|
+
assignStyles(host, {
|
|
56
|
+
width: `${cellRect.width}px`,
|
|
57
|
+
height: `${tableRect.height}px`,
|
|
58
|
+
})
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (direction === 'row') {
|
|
62
|
+
assignStyles(host, {
|
|
63
|
+
width: `${tableRect.width}px`,
|
|
64
|
+
height: `${cellRect.height}px`,
|
|
65
|
+
})
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
EventDeclarations,
|
|
3
|
+
PropDeclarations,
|
|
4
|
+
} from '@aria-ui/core'
|
|
5
|
+
import type { Editor } from '@prosekit/core'
|
|
6
|
+
|
|
7
|
+
export interface TableHandleDragPreviewProps {
|
|
8
|
+
editor: Editor | null
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const tableHandleDragPreviewProps: PropDeclarations<TableHandleDragPreviewProps> = {
|
|
12
|
+
editor: { default: null },
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface TableHandleDragPreviewEvents {}
|
|
16
|
+
|
|
17
|
+
export const tableHandleDragPreviewEvents: EventDeclarations<TableHandleDragPreviewEvents> = {}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createComputed,
|
|
3
|
+
useEffect,
|
|
4
|
+
type ConnectableElement,
|
|
5
|
+
type ReadonlySignal,
|
|
6
|
+
} from '@aria-ui/core'
|
|
7
|
+
import {
|
|
8
|
+
computePosition,
|
|
9
|
+
type ReferenceElement,
|
|
10
|
+
} from '@floating-ui/dom'
|
|
11
|
+
import type { Editor } from '@prosekit/core'
|
|
12
|
+
|
|
13
|
+
import { assignStyles } from '../../../utils/assign-styles'
|
|
14
|
+
import { getSafeEditorView } from '../../../utils/get-safe-editor-view'
|
|
15
|
+
import {
|
|
16
|
+
tableHandleDndContext,
|
|
17
|
+
tableHandleRootContext,
|
|
18
|
+
} from '../context'
|
|
19
|
+
import { getDndRelatedDOMs } from '../dnd'
|
|
20
|
+
|
|
21
|
+
export function useUpdatePreviewPosition(host: ConnectableElement, editor: ReadonlySignal<Editor | null>): void {
|
|
22
|
+
const dndContext = tableHandleDndContext.consume(host)
|
|
23
|
+
const rootContext = tableHandleRootContext.consume(host)
|
|
24
|
+
|
|
25
|
+
const draggingSignal = createComputed(() => {
|
|
26
|
+
const context = dndContext.get()
|
|
27
|
+
return context.dragging
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const clientXSignal = createComputed(() => {
|
|
31
|
+
const context = dndContext.get()
|
|
32
|
+
return context.x
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const clientYSignal = createComputed(() => {
|
|
36
|
+
const context = dndContext.get()
|
|
37
|
+
return context.y
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
useEffect(host, () => {
|
|
41
|
+
const view = getSafeEditorView(editor.get())
|
|
42
|
+
if (!view) return
|
|
43
|
+
|
|
44
|
+
if (!draggingSignal.get()) return
|
|
45
|
+
|
|
46
|
+
const { draggingIndex, direction } = dndContext.peek()
|
|
47
|
+
const x = clientXSignal.get()
|
|
48
|
+
const y = clientYSignal.get()
|
|
49
|
+
|
|
50
|
+
const relatedDOMs = getDndRelatedDOMs(view, rootContext.peek()?.cellPos, draggingIndex, direction)
|
|
51
|
+
if (!relatedDOMs) return
|
|
52
|
+
const { cell } = relatedDOMs
|
|
53
|
+
|
|
54
|
+
let cancelled = false
|
|
55
|
+
|
|
56
|
+
void computePosition(
|
|
57
|
+
getVirtualElement(cell, x, y),
|
|
58
|
+
host,
|
|
59
|
+
{ placement: direction === 'row' ? 'right' : 'bottom' },
|
|
60
|
+
).then(({ x, y }) => {
|
|
61
|
+
if (cancelled) return
|
|
62
|
+
|
|
63
|
+
if (direction === 'row') {
|
|
64
|
+
assignStyles(host, {
|
|
65
|
+
top: `${y}px`,
|
|
66
|
+
})
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (direction === 'col') {
|
|
71
|
+
assignStyles(host, {
|
|
72
|
+
left: `${x}px`,
|
|
73
|
+
})
|
|
74
|
+
return
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
return () => {
|
|
79
|
+
cancelled = true
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function getVirtualElement(cell: HTMLTableCellElement, x: number, y: number): ReferenceElement {
|
|
85
|
+
return {
|
|
86
|
+
contextElement: cell,
|
|
87
|
+
getBoundingClientRect: () => {
|
|
88
|
+
const rect = cell.getBoundingClientRect()
|
|
89
|
+
return {
|
|
90
|
+
width: rect.width,
|
|
91
|
+
height: rect.height,
|
|
92
|
+
right: x + rect.width / 2,
|
|
93
|
+
bottom: y + rect.height / 2,
|
|
94
|
+
top: y - rect.height / 2,
|
|
95
|
+
left: x - rect.width / 2,
|
|
96
|
+
x: x - rect.width / 2,
|
|
97
|
+
y: y - rect.height / 2,
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
function findDragOverElement(
|
|
2
|
+
elements: Element[],
|
|
3
|
+
pointer: number,
|
|
4
|
+
axis: 'x' | 'y',
|
|
5
|
+
): [Element, number] | undefined {
|
|
6
|
+
const startProp = axis === 'x' ? 'left' : 'top'
|
|
7
|
+
const endProp = axis === 'x' ? 'right' : 'bottom'
|
|
8
|
+
const lastIndex = elements.length - 1
|
|
9
|
+
|
|
10
|
+
const index = elements.findIndex((el, index) => {
|
|
11
|
+
const rect = el.getBoundingClientRect()
|
|
12
|
+
const boundaryStart = rect[startProp]
|
|
13
|
+
const boundaryEnd = rect[endProp]
|
|
14
|
+
|
|
15
|
+
// The pointer is within the boundary of the current element.
|
|
16
|
+
if (boundaryStart <= pointer && pointer <= boundaryEnd) return true
|
|
17
|
+
// The pointer is beyond the last element.
|
|
18
|
+
if (index === lastIndex && pointer > boundaryEnd) return true
|
|
19
|
+
// The pointer is before the first element.
|
|
20
|
+
if (index === 0 && pointer < boundaryStart) return true
|
|
21
|
+
|
|
22
|
+
return false
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
return index >= 0 ? [elements[index], index] : undefined
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function getDragOverColumn(
|
|
29
|
+
table: HTMLTableElement,
|
|
30
|
+
pointerX: number,
|
|
31
|
+
): [element: Element, index: number] | undefined {
|
|
32
|
+
const firstRow = table.querySelector('tr')
|
|
33
|
+
if (!firstRow) return
|
|
34
|
+
const cells = Array.from(firstRow.children)
|
|
35
|
+
return findDragOverElement(cells, pointerX, 'x')
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function getDragOverRow(
|
|
39
|
+
table: HTMLTableElement,
|
|
40
|
+
pointerY: number,
|
|
41
|
+
): [element: Element, index: number] | undefined {
|
|
42
|
+
const rows = Array.from(table.querySelectorAll('tr'))
|
|
43
|
+
return findDragOverElement(rows, pointerY, 'y')
|
|
44
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineCustomElement, registerCustomElement, type BaseElementConstructor } from "@aria-ui/core"
|
|
2
|
+
|
|
3
|
+
import { useTableHandleDropIndicator } from "./setup"
|
|
4
|
+
import { tableHandleDropIndicatorEvents, tableHandleDropIndicatorProps, type TableHandleDropIndicatorEvents, type TableHandleDropIndicatorProps } from "./types"
|
|
5
|
+
|
|
6
|
+
const TableHandleDropIndicatorElementBase: BaseElementConstructor<TableHandleDropIndicatorProps> = defineCustomElement<
|
|
7
|
+
TableHandleDropIndicatorProps,
|
|
8
|
+
TableHandleDropIndicatorEvents
|
|
9
|
+
>({
|
|
10
|
+
props: tableHandleDropIndicatorProps,
|
|
11
|
+
events: tableHandleDropIndicatorEvents,
|
|
12
|
+
setup: useTableHandleDropIndicator,
|
|
13
|
+
})
|
|
14
|
+
class TableHandleDropIndicatorElement extends TableHandleDropIndicatorElementBase {}
|
|
15
|
+
|
|
16
|
+
registerCustomElement('prosekit-table-handle-drop-indicator', TableHandleDropIndicatorElement)
|
|
17
|
+
|
|
18
|
+
export { TableHandleDropIndicatorElement }
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useEffect,
|
|
3
|
+
type ConnectableElement,
|
|
4
|
+
type SignalState,
|
|
5
|
+
} from '@aria-ui/core'
|
|
6
|
+
|
|
7
|
+
import { assignStyles } from '../../../utils/assign-styles'
|
|
8
|
+
import {
|
|
9
|
+
useInitDndPosition,
|
|
10
|
+
type OnInitParams,
|
|
11
|
+
} from '../dnd'
|
|
12
|
+
|
|
13
|
+
import type { TableHandleDropIndicatorProps } from './types'
|
|
14
|
+
import { useUpdateIndicatorPosition } from './updater'
|
|
15
|
+
|
|
16
|
+
const HANDLE_WIDTH = 2
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
export function useTableHandleDropIndicator(host: ConnectableElement, { state }: { state: SignalState<TableHandleDropIndicatorProps> }): void {
|
|
22
|
+
const { editor } = state
|
|
23
|
+
|
|
24
|
+
useEffect(host, () => {
|
|
25
|
+
assignStyles(host, {
|
|
26
|
+
pointerEvents: 'none',
|
|
27
|
+
position: 'absolute',
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
useInitDndPosition(host, editor, onInitIndicatorPosition)
|
|
32
|
+
|
|
33
|
+
useUpdateIndicatorPosition(host, editor, HANDLE_WIDTH)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function onInitIndicatorPosition({ host, direction, dragging, table }: OnInitParams): void {
|
|
37
|
+
assignStyles(host, {
|
|
38
|
+
display: dragging ? 'block' : 'none',
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const tableRect = table.getBoundingClientRect()
|
|
42
|
+
|
|
43
|
+
if (direction === 'col') {
|
|
44
|
+
assignStyles(host, {
|
|
45
|
+
width: `${HANDLE_WIDTH}px`,
|
|
46
|
+
height: `${tableRect.height}px`,
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (direction === 'row') {
|
|
51
|
+
assignStyles(host, {
|
|
52
|
+
width: `${tableRect.width}px`,
|
|
53
|
+
height: `${HANDLE_WIDTH}px`,
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
EventDeclarations,
|
|
3
|
+
PropDeclarations,
|
|
4
|
+
} from '@aria-ui/core'
|
|
5
|
+
import type { Editor } from '@prosekit/core'
|
|
6
|
+
import type { TableCommandsExtension } from '@prosekit/extensions/table'
|
|
7
|
+
|
|
8
|
+
export interface TableHandleDropIndicatorProps {
|
|
9
|
+
editor: Editor<TableCommandsExtension> | null
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const tableHandleDropIndicatorProps: PropDeclarations<TableHandleDropIndicatorProps> = {
|
|
13
|
+
editor: { default: null },
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface TableHandleDropIndicatorEvents {}
|
|
17
|
+
|
|
18
|
+
export const tableHandleDropIndicatorEvents: EventDeclarations<TableHandleDropIndicatorEvents> = {}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createComputed,
|
|
3
|
+
useEffect,
|
|
4
|
+
type ConnectableElement,
|
|
5
|
+
type ReadonlySignal,
|
|
6
|
+
} from '@aria-ui/core'
|
|
7
|
+
import {
|
|
8
|
+
computePosition,
|
|
9
|
+
offset,
|
|
10
|
+
} from '@floating-ui/dom'
|
|
11
|
+
import type { Editor } from '@prosekit/core'
|
|
12
|
+
|
|
13
|
+
import { assignStyles } from '../../../utils/assign-styles'
|
|
14
|
+
import { getSafeEditorView } from '../../../utils/get-safe-editor-view'
|
|
15
|
+
import {
|
|
16
|
+
tableHandleDndContext,
|
|
17
|
+
tableHandleRootContext,
|
|
18
|
+
} from '../context'
|
|
19
|
+
import { getDndRelatedDOMs } from '../dnd'
|
|
20
|
+
|
|
21
|
+
import {
|
|
22
|
+
getDragOverColumn,
|
|
23
|
+
getDragOverRow,
|
|
24
|
+
} from './calc-drag-over'
|
|
25
|
+
|
|
26
|
+
export function useUpdateIndicatorPosition(host: ConnectableElement, editor: ReadonlySignal<Editor | null>, handleWidth: number): void {
|
|
27
|
+
const dndContext = tableHandleDndContext.consume(host)
|
|
28
|
+
const rootContext = tableHandleRootContext.consume(host)
|
|
29
|
+
|
|
30
|
+
const draggingSignal = createComputed(() => {
|
|
31
|
+
const context = dndContext.get()
|
|
32
|
+
return context.dragging
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const clientXSignal = createComputed(() => {
|
|
36
|
+
const context = dndContext.get()
|
|
37
|
+
return context.x
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
const clientYSignal = createComputed(() => {
|
|
41
|
+
const context = dndContext.get()
|
|
42
|
+
return context.y
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
const startXSignal = createComputed(() => {
|
|
46
|
+
return dndContext.get().startX
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
const startYSignal = createComputed(() => {
|
|
50
|
+
return dndContext.get().startY
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
useEffect(host, () => {
|
|
54
|
+
const view = getSafeEditorView(editor.get())
|
|
55
|
+
if (!view) return
|
|
56
|
+
|
|
57
|
+
if (!draggingSignal.get()) return
|
|
58
|
+
|
|
59
|
+
const { draggingIndex, direction } = dndContext.peek()
|
|
60
|
+
const x = clientXSignal.get()
|
|
61
|
+
const y = clientYSignal.get()
|
|
62
|
+
|
|
63
|
+
const relatedDOMs = getDndRelatedDOMs(view, rootContext.peek()?.cellPos, draggingIndex, direction)
|
|
64
|
+
if (!relatedDOMs) return
|
|
65
|
+
const { table } = relatedDOMs
|
|
66
|
+
|
|
67
|
+
let cancelled = false
|
|
68
|
+
let cleanup = () => {
|
|
69
|
+
cancelled = true
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (direction === 'col') {
|
|
73
|
+
const direction = startXSignal.get() > x ? 'left' : 'right'
|
|
74
|
+
const dragOverColumn = getDragOverColumn(table, x)
|
|
75
|
+
|
|
76
|
+
if (dragOverColumn) {
|
|
77
|
+
const [col, index] = dragOverColumn
|
|
78
|
+
dndContext.set({ ...dndContext.peek(), droppingIndex: index })
|
|
79
|
+
void computePosition(col, host, {
|
|
80
|
+
placement: direction === 'left' ? 'left' : 'right',
|
|
81
|
+
middleware: [offset(direction === 'left' ? -1 * handleWidth : 0)],
|
|
82
|
+
}).then(({ x }) => {
|
|
83
|
+
if (cancelled) return
|
|
84
|
+
assignStyles(host, { left: `${x}px` })
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return cleanup
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (direction === 'row') {
|
|
92
|
+
const direction = startYSignal.get() > y ? 'up' : 'down'
|
|
93
|
+
const dragOverRow = getDragOverRow(table, y)
|
|
94
|
+
|
|
95
|
+
if (dragOverRow) {
|
|
96
|
+
const [row, index] = dragOverRow
|
|
97
|
+
dndContext.set({ ...dndContext.peek(), droppingIndex: index })
|
|
98
|
+
void computePosition(row, host, {
|
|
99
|
+
placement: direction === 'up' ? 'top' : 'bottom',
|
|
100
|
+
middleware: [offset(direction === 'up' ? -1 * handleWidth : 0)],
|
|
101
|
+
}).then(({ y }) => {
|
|
102
|
+
if (cancelled) return
|
|
103
|
+
assignStyles(host, { top: `${y}px` })
|
|
104
|
+
})
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return cleanup
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineCustomElement, registerCustomElement, type BaseElementConstructor } from "@aria-ui/core"
|
|
2
|
+
|
|
3
|
+
import { useTableHandlePopoverContent } from "./setup"
|
|
4
|
+
import { tableHandlePopoverContentEvents, tableHandlePopoverContentProps, type TableHandlePopoverContentEvents, type TableHandlePopoverContentProps } from "./types"
|
|
5
|
+
|
|
6
|
+
const TableHandlePopoverContentElementBase: BaseElementConstructor<TableHandlePopoverContentProps> = defineCustomElement<
|
|
7
|
+
TableHandlePopoverContentProps,
|
|
8
|
+
TableHandlePopoverContentEvents
|
|
9
|
+
>({
|
|
10
|
+
props: tableHandlePopoverContentProps,
|
|
11
|
+
events: tableHandlePopoverContentEvents,
|
|
12
|
+
setup: useTableHandlePopoverContent,
|
|
13
|
+
})
|
|
14
|
+
class TableHandlePopoverContentElement extends TableHandlePopoverContentElementBase {}
|
|
15
|
+
|
|
16
|
+
registerCustomElement('prosekit-table-handle-popover-content', TableHandlePopoverContentElement)
|
|
17
|
+
|
|
18
|
+
export { TableHandlePopoverContentElement }
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createComputed,
|
|
3
|
+
createSignal,
|
|
4
|
+
useEffect,
|
|
5
|
+
type ConnectableElement,
|
|
6
|
+
type ReadonlySignal,
|
|
7
|
+
type SetupOptions,
|
|
8
|
+
type SignalState,
|
|
9
|
+
type TypedEventTarget,
|
|
10
|
+
} from '@aria-ui/core'
|
|
11
|
+
import {
|
|
12
|
+
menuContentProps,
|
|
13
|
+
useMenuContent,
|
|
14
|
+
type MenuContentProps,
|
|
15
|
+
} from '@aria-ui/menu/elements'
|
|
16
|
+
|
|
17
|
+
import { getStateWithDefaults } from '../../../utils/get-default-state'
|
|
18
|
+
import { tableHandleRootContext } from '../context'
|
|
19
|
+
|
|
20
|
+
import type {
|
|
21
|
+
TableHandlePopoverContentEvents,
|
|
22
|
+
TableHandlePopoverContentProps,
|
|
23
|
+
} from './types'
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
export function useTableHandlePopoverContent(
|
|
29
|
+
host: ConnectableElement,
|
|
30
|
+
{
|
|
31
|
+
state,
|
|
32
|
+
emit,
|
|
33
|
+
}: SetupOptions<
|
|
34
|
+
TableHandlePopoverContentProps,
|
|
35
|
+
TableHandlePopoverContentEvents
|
|
36
|
+
>,
|
|
37
|
+
): void {
|
|
38
|
+
const rootContext = tableHandleRootContext.consume(host)
|
|
39
|
+
const open = createComputed(() => !!rootContext.get())
|
|
40
|
+
const keyDownTarget = useKeyDownTarget(host, open)
|
|
41
|
+
|
|
42
|
+
const menuContentState: SignalState<MenuContentProps> = getStateWithDefaults(
|
|
43
|
+
{
|
|
44
|
+
placement: state.placement,
|
|
45
|
+
offset: state.offset,
|
|
46
|
+
eventTarget: createSignal(keyDownTarget),
|
|
47
|
+
},
|
|
48
|
+
menuContentProps,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
useMenuContent(host, { state: menuContentState, emit })
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function useKeyDownTarget(
|
|
55
|
+
element: ConnectableElement,
|
|
56
|
+
open: ReadonlySignal<boolean>,
|
|
57
|
+
): TypedEventTarget<'keydown'> {
|
|
58
|
+
const keydownHandlers: Array<(event: KeyboardEvent) => void> = []
|
|
59
|
+
|
|
60
|
+
useEffect(element, () => {
|
|
61
|
+
const handleKeydown = (event: KeyboardEvent) => {
|
|
62
|
+
if (event.isComposing || event.defaultPrevented || !open.get()) {
|
|
63
|
+
return false
|
|
64
|
+
}
|
|
65
|
+
keydownHandlers.forEach((handler) => handler(event))
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
document.addEventListener('keydown', handleKeydown)
|
|
69
|
+
|
|
70
|
+
return () => {
|
|
71
|
+
document.removeEventListener('keydown', handleKeydown)
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
addEventListener: (type, listener) => {
|
|
77
|
+
if (type === 'keydown') {
|
|
78
|
+
keydownHandlers.push(listener)
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
removeEventListener: (type, listener) => {
|
|
82
|
+
if (type === 'keydown') {
|
|
83
|
+
const index = keydownHandlers.indexOf(listener)
|
|
84
|
+
if (index !== -1) {
|
|
85
|
+
keydownHandlers.splice(index, 1)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
EventDeclarations,
|
|
3
|
+
PropDeclarations,
|
|
4
|
+
} from '@aria-ui/core'
|
|
5
|
+
import {
|
|
6
|
+
menuContentEvents,
|
|
7
|
+
menuContentProps,
|
|
8
|
+
type MenuContentEvents,
|
|
9
|
+
type MenuContentProps,
|
|
10
|
+
} from '@aria-ui/menu/elements'
|
|
11
|
+
import type { Editor } from '@prosekit/core'
|
|
12
|
+
|
|
13
|
+
export interface TableHandlePopoverContentProps extends Omit<MenuContentProps, 'placement' | 'offset'> {
|
|
14
|
+
/**
|
|
15
|
+
* @default 'bottom-start'
|
|
16
|
+
*/
|
|
17
|
+
placement: MenuContentProps['placement']
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @default {mainAxis: -4, crossAxis: 4}
|
|
21
|
+
*/
|
|
22
|
+
offset: MenuContentProps['offset']
|
|
23
|
+
|
|
24
|
+
editor: Editor | null
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** @internal */
|
|
28
|
+
export const tableHandlePopoverContentProps: PropDeclarations<TableHandlePopoverContentProps> = Object.freeze({
|
|
29
|
+
...menuContentProps,
|
|
30
|
+
placement: { default: 'right-start' },
|
|
31
|
+
offset: { default: { mainAxis: -4, crossAxis: 4 } },
|
|
32
|
+
editor: { default: null },
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
export interface TableHandlePopoverContentEvents extends MenuContentEvents {}
|
|
36
|
+
|
|
37
|
+
/** @internal */
|
|
38
|
+
export const tableHandlePopoverContentEvents: EventDeclarations<TableHandlePopoverContentEvents> = Object.freeze({
|
|
39
|
+
...menuContentEvents,
|
|
40
|
+
})
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineCustomElement, registerCustomElement, type BaseElementConstructor } from "@aria-ui/core"
|
|
2
|
+
|
|
3
|
+
import { useTableHandlePopoverItem } from "./setup"
|
|
4
|
+
import { tableHandlePopoverItemEvents, tableHandlePopoverItemProps, type TableHandlePopoverItemEvents, type TableHandlePopoverItemProps } from "./types"
|
|
5
|
+
|
|
6
|
+
const TableHandlePopoverItemElementBase: BaseElementConstructor<TableHandlePopoverItemProps> = defineCustomElement<
|
|
7
|
+
TableHandlePopoverItemProps,
|
|
8
|
+
TableHandlePopoverItemEvents
|
|
9
|
+
>({
|
|
10
|
+
props: tableHandlePopoverItemProps,
|
|
11
|
+
events: tableHandlePopoverItemEvents,
|
|
12
|
+
setup: useTableHandlePopoverItem,
|
|
13
|
+
})
|
|
14
|
+
class TableHandlePopoverItemElement extends TableHandlePopoverItemElementBase {}
|
|
15
|
+
|
|
16
|
+
registerCustomElement('prosekit-table-handle-popover-item', TableHandlePopoverItemElement)
|
|
17
|
+
|
|
18
|
+
export { TableHandlePopoverItemElement }
|