PluginProbe
The Innovative Form Builder – IvyForms / 0.8
The Innovative Form Builder – IvyForms v0.8
1.5.1 1.5 1.4.1 1.4 trunk 0.1.2 0.2 0.2.1 0.3 0.3.1 0.4 0.5 0.6 0.6.1 0.6.1-backup 0.6.1.1 0.7 0.8 0.8.1 0.8.2 0.9 0.9.1 1.0 1.1 1.1.1 All 27 releases
ivyforms / frontend / src / views / _components / html-editor / utils / indentUtil.ts

indentUtil.ts in The Innovative Form Builder – IvyForms 0.8, at frontend/src/views/_components/html-editor/utils/indentUtil.ts

89 lines 1.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import type { Command, Editor } from '@tiptap/core'
2 import { isList } from '@tiptap/core'
3 import { TextSelection, AllSelection, Transaction } from 'prosemirror-state'
4
5 export const enum IndentProps {
6 max = 21,
7 min = 0,
8
9 more = 1,
10 less = -1,
11 }
12
13 function updateIndentLevel(
14 tr: Transaction,
15 delta: number,
16 types: string[],
17 editor: Editor,
18 ): Transaction {
19 const { doc, selection } = tr
20
21 if (!doc || !selection) return tr
22
23 if (!(selection instanceof TextSelection || selection instanceof AllSelection)) {
24 return tr
25 }
26
27 const { from, to } = selection
28
29 doc.nodesBetween(from, to, (node, pos) => {
30 const nodeType = node.type
31
32 if (types.includes(nodeType.name)) {
33 tr = setNodeIndentMarkup(tr, pos, delta)
34 return false
35 } else if (isList(node.type.name, editor.extensionManager.extensions)) {
36 return false
37 }
38 return true
39 })
40
41 return tr
42 }
43
44 function setNodeIndentMarkup(tr: Transaction, pos: number, delta: number): Transaction {
45 if (!tr.doc) return tr
46
47 const node = tr.doc.nodeAt(pos)
48 if (!node) return tr
49
50 const minIndent = IndentProps.min
51 const maxIndent = IndentProps.max
52
53 const indent = clamp((node.attrs.indent || 0) + delta, minIndent, maxIndent)
54
55 if (indent === node.attrs.indent) return tr
56
57 const nodeAttrs = {
58 ...node.attrs,
59 indent,
60 }
61
62 return tr.setNodeMarkup(pos, node.type, nodeAttrs, node.marks)
63 }
64
65 export function createIndentCommand({ delta, types }: { delta: number; types: string[] }): Command {
66 return ({ state, dispatch, editor }) => {
67 const { selection } = state
68 let { tr } = state
69 tr = tr.setSelection(selection)
70 tr = updateIndentLevel(tr, delta, types, editor)
71 if (tr.docChanged) {
72 dispatch?.(tr)
73 return true
74 }
75
76 return false
77 }
78 }
79
80 const clamp = function (val: number, min: number, max: number): number {
81 if (val < min) {
82 return min
83 }
84 if (val > max) {
85 return max
86 }
87 return val
88 }
89