Skip to content

Commit

Permalink
fix: block add position (#1457)
Browse files Browse the repository at this point in the history
  • Loading branch information
Saul-Mirone authored Aug 3, 2024
1 parent db97828 commit 1723d36
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 97 deletions.
12 changes: 4 additions & 8 deletions packages/crepe/src/feature/block-edit/handle/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,10 @@ export class BlockHandleView implements PluginView {
if (!active)
return

const pos = active.$pos
const isNoneTextBlock = ['hr', 'image-block'].includes(active.node.type.name)
const nodeSize = isNoneTextBlock ? active.node.nodeSize : active.node.content.size
const side = pos.pos + nodeSize + (['blockquote'].includes(pos.parent.type.name) ? 1 : 0)
const offset
= ['blockquote'].includes(pos.parent.type.name) ? 1 : isNoneTextBlock ? 1 : 2
let tr = state.tr.insert(side, paragraphSchema.type(ctx).create())
tr = tr.setSelection(TextSelection.create(tr.doc, side + offset))
const $pos = active.$pos
const pos = $pos.pos + active.node.nodeSize
let tr = state.tr.insert(pos, paragraphSchema.type(ctx).create())
tr = tr.setSelection(TextSelection.near(tr.doc.resolve(pos)))
dispatch(tr.scrollIntoView())

this.#provider.hide()
Expand Down
91 changes: 2 additions & 89 deletions packages/crepe/src/feature/block-edit/menu/config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import type { html } from 'atomico'
import type { Ctx } from '@milkdown/kit/ctx'
import { editorViewCtx } from '@milkdown/kit/core'
import {
blockquoteSchema,
Expand All @@ -11,9 +9,6 @@ import {
orderedListSchema,
paragraphSchema,
} from '@milkdown/kit/preset/commonmark'
import type { Attrs, NodeType } from '@milkdown/kit/prose/model'
import { findWrapping } from '@milkdown/kit/prose/transform'
import type { Command, Transaction } from '@milkdown/kit/prose/state'
import { NodeSelection } from '@milkdown/kit/prose/state'
import { imageBlockSchema } from '@milkdown/kit/component/image-block'
import { createTable } from '@milkdown/kit/preset/gfm'
Expand All @@ -35,90 +30,8 @@ import {
todoListIcon,
} from '../../../icons'
import type { BlockEditFeatureConfig } from '../index'

interface MenuItem {
index: number
key: string
label: string
icon: ReturnType<typeof html>
onRun: (ctx: Ctx) => void
}

type WithRange<T, HasIndex extends true | false = true> = HasIndex extends true ? T & { range: [start: number, end: number] } : T

type MenuItemGroup<HasIndex extends true | false = true> = WithRange<{
key: string
label: string
items: HasIndex extends true ? MenuItem[] : Omit<MenuItem, 'index'>[]
}, HasIndex>

function clearRange(tr: Transaction) {
const { $from, $to } = tr.selection
const { pos: from } = $from
const { pos: to } = $to
tr = tr.deleteRange(from - $from.node().content.size, to)
return tr
}

function setBlockType(tr: Transaction, nodeType: NodeType, attrs: Attrs | null = null) {
const { from, to } = tr.selection
return tr.setBlockType(from, to, nodeType, attrs)
}

function wrapInBlockType(tr: Transaction, nodeType: NodeType, attrs: Attrs | null = null) {
const { $from, $to } = tr.selection

const range = $from.blockRange($to)
const wrapping = range && findWrapping(range, nodeType, attrs)
if (!wrapping)
return null

return tr.wrap(range, wrapping)
}

function addBlockType(tr: Transaction, nodeType: NodeType, attrs: Attrs | null = null) {
const node = nodeType.createAndFill(attrs)
if (!node)
return null

return tr.replaceSelectionWith(node)
}

function clearContentAndSetBlockType(nodeType: NodeType, attrs: Attrs | null = null): Command {
return (state, dispatch) => {
if (dispatch) {
const tr = setBlockType(clearRange(state.tr), nodeType, attrs)
dispatch(tr.scrollIntoView())
}
return true
}
}

function clearContentAndWrapInBlockType(nodeType: NodeType, attrs: Attrs | null = null): Command {
return (state, dispatch) => {
const tr = wrapInBlockType(clearRange(state.tr), nodeType, attrs)
if (!tr)
return false

if (dispatch)
dispatch(tr.scrollIntoView())

return true
}
}

function clearContentAndAddBlockType(nodeType: NodeType, attrs: Attrs | null = null): Command {
return (state, dispatch) => {
const tr = addBlockType(clearRange(state.tr), nodeType, attrs)
if (!tr)
return false

if (dispatch)
dispatch(tr.scrollIntoView())

return true
}
}
import type { MenuItemGroup } from './utils'
import { clearContentAndAddBlockType, clearContentAndSetBlockType, clearContentAndWrapInBlockType, clearRange } from './utils'

export function getGroups(filter?: string, config?: BlockEditFeatureConfig) {
let groups: MenuItemGroup<false>[] = [
Expand Down
89 changes: 89 additions & 0 deletions packages/crepe/src/feature/block-edit/menu/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import type { html } from 'atomico'
import type { Ctx } from '@milkdown/kit/ctx'
import type { Command, Transaction } from '@milkdown/kit/prose/state'
import type { Attrs, NodeType } from '@milkdown/kit/prose/model'
import { findWrapping } from '@milkdown/kit/prose/transform'

export interface MenuItem {
index: number
key: string
label: string
icon: ReturnType<typeof html>
onRun: (ctx: Ctx) => void
}

type WithRange<T, HasIndex extends true | false = true> = HasIndex extends true ? T & { range: [start: number, end: number] } : T

export type MenuItemGroup<HasIndex extends true | false = true> = WithRange<{
key: string
label: string
items: HasIndex extends true ? MenuItem[] : Omit<MenuItem, 'index'>[]
}, HasIndex>

export function clearRange(tr: Transaction) {
const { $from, $to } = tr.selection
const { pos: from } = $from
const { pos: to } = $to
tr = tr.deleteRange(from - $from.node().content.size, to)
return tr
}

export function setBlockType(tr: Transaction, nodeType: NodeType, attrs: Attrs | null = null) {
const { from, to } = tr.selection
return tr.setBlockType(from, to, nodeType, attrs)
}

export function wrapInBlockType(tr: Transaction, nodeType: NodeType, attrs: Attrs | null = null) {
const { $from, $to } = tr.selection

const range = $from.blockRange($to)
const wrapping = range && findWrapping(range, nodeType, attrs)
if (!wrapping)
return null

return tr.wrap(range, wrapping)
}

export function addBlockType(tr: Transaction, nodeType: NodeType, attrs: Attrs | null = null) {
const node = nodeType.createAndFill(attrs)
if (!node)
return null

return tr.replaceSelectionWith(node)
}

export function clearContentAndSetBlockType(nodeType: NodeType, attrs: Attrs | null = null): Command {
return (state, dispatch) => {
if (dispatch) {
const tr = setBlockType(clearRange(state.tr), nodeType, attrs)
dispatch(tr.scrollIntoView())
}
return true
}
}

export function clearContentAndWrapInBlockType(nodeType: NodeType, attrs: Attrs | null = null): Command {
return (state, dispatch) => {
const tr = wrapInBlockType(clearRange(state.tr), nodeType, attrs)
if (!tr)
return false

if (dispatch)
dispatch(tr.scrollIntoView())

return true
}
}

export function clearContentAndAddBlockType(nodeType: NodeType, attrs: Attrs | null = null): Command {
return (state, dispatch) => {
const tr = addBlockType(clearRange(state.tr), nodeType, attrs)
if (!tr)
return false

if (dispatch)
dispatch(tr.scrollIntoView())

return true
}
}

0 comments on commit 1723d36

Please sign in to comment.