* refactor(editor): separate canvas view state - Classify shared and view-local editor state explicitly - Let canvas surfaces render supplied view state and report their viewport - Preserve the existing one-canvas behavior by default * fix(canvas): preserve loading render state * feat(editor): model split canvas panes - Add pure recursive split-tree operations with validated sizes - Add explicit pane registry and independent view-state cloning - Cap visible panes and cover close and split behavior * refactor(editor): group state ownership modules - Move shared and view state into the editor state namespace - Model the partition with explicit interfaces and default factories - Derive runtime view keys from the default view object * feat(editor): model split canvas panes - Add pure recursive split-tree operations with validated sizes - Add explicit pane registry and independent view-state cloning - Cap visible panes and cover close and split behavior * feat(editor): add split canvas views - Render recursive pane layouts with Reka UI splitters and pane-local headers - Route canvas input, selection, viewport state, and close actions to the active pane - Repaint every canvas during shared document previews and cover split lifecycle in tests * fix(editor): clean up inactive pane interactions - Cancel drag, padding preview, and text editing state when pane focus changes - Remove duplicate changelog entries introduced while updating master
59 lines
1.4 KiB
TypeScript
59 lines
1.4 KiB
TypeScript
import { watch } from 'vue'
|
|
import type { ShallowRef } from 'vue'
|
|
|
|
import type { Editor } from '@open-pencil/core/editor'
|
|
|
|
export function createHiddenTextArea() {
|
|
const textarea = document.createElement('textarea')
|
|
textarea.setAttribute('aria-hidden', 'true')
|
|
textarea.tabIndex = -1
|
|
textarea.className = 'fixed left-0 top-0 h-px w-px opacity-0'
|
|
document.body.appendChild(textarea)
|
|
return textarea
|
|
}
|
|
|
|
export function focusTextAreaOnCanvasPointerDown(
|
|
textareaRef: ShallowRef<HTMLTextAreaElement | null>,
|
|
store: Editor
|
|
) {
|
|
if (store.state.editingTextId && textareaRef.value) {
|
|
requestAnimationFrame(() => textareaRef.value?.focus())
|
|
}
|
|
}
|
|
|
|
export function useTextEditingSession({
|
|
store,
|
|
textareaRef,
|
|
resetBlink,
|
|
stopBlink,
|
|
resetComposition,
|
|
isEnabled
|
|
}: {
|
|
store: Editor
|
|
textareaRef: ShallowRef<HTMLTextAreaElement | null>
|
|
resetBlink: () => void
|
|
stopBlink: () => void
|
|
resetComposition: () => void
|
|
isEnabled?: () => boolean
|
|
}) {
|
|
watch(
|
|
() => [store.state.editingTextId, isEnabled?.() ?? true] as const,
|
|
([id, enabled], _, onCleanup) => {
|
|
if (!enabled) return
|
|
if (id) {
|
|
const el = createHiddenTextArea()
|
|
textareaRef.value = el
|
|
el.focus()
|
|
resetBlink()
|
|
|
|
onCleanup(() => {
|
|
stopBlink()
|
|
el.remove()
|
|
textareaRef.value = null
|
|
resetComposition()
|
|
})
|
|
}
|
|
}
|
|
)
|
|
}
|