mirror of
https://github.com/docusealco/docuseal
synced 2026-11-04 14:42:32 -05:00
simplify dynamic editor code
This commit is contained in:
1 parent
4f5e72f983
commit
a70ac571e3
3 files changed
+34
-57
No files matched your search
@@ -43,7 +43,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="size && coords.type === 'table'"
|
v-if="size"
|
||||||
class="absolute top-0 left-0 border border-dashed border-blue-500"
|
class="absolute top-0 left-0 border border-dashed border-blue-500"
|
||||||
:style="{ width: size.width + 'px', height: size.height + 'px' }"
|
:style="{ width: size.width + 'px', height: size.height + 'px' }"
|
||||||
/>
|
/>
|
||||||
@@ -114,8 +114,8 @@ export default {
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
{ command: 'mergeTableCells', icon: IconMergeCells, title: 'merge_cells', structural: true, enabled: 'canMerge' },
|
{ command: 'mergeTableCells', icon: IconMergeCells, title: 'merge_cells', structural: true, disabled: !this.coords.canMerge },
|
||||||
{ command: 'splitTableCell', icon: IconSplitCell, title: 'split_cell', structural: true, enabled: 'canSplit' }
|
{ command: 'splitTableCell', icon: IconSplitCell, title: 'split_cell', structural: true, disabled: !this.coords.canSplit }
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{ command: 'deleteTableRow', icon: IconRowRemove, title: 'delete_row', danger: true, structural: true },
|
{ command: 'deleteTableRow', icon: IconRowRemove, title: 'delete_row', danger: true, structural: true },
|
||||||
@@ -138,7 +138,7 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
isDisabled (action) {
|
isDisabled (action) {
|
||||||
return (action.structural && !this.coords.isRegular) || (action.enabled && !this.coords[action.enabled])
|
return (action.structural && !this.coords.isRegular) || action.disabled
|
||||||
},
|
},
|
||||||
startResize (event) {
|
startResize (event) {
|
||||||
this.resizeStart = { x: event.clientX, y: event.clientY, width: this.coords.width, height: this.coords.height }
|
this.resizeStart = { x: event.clientX, y: event.clientY, width: this.coords.width, height: this.coords.height }
|
||||||
|
|||||||
@@ -1058,8 +1058,6 @@ function tableCellNodes (table) {
|
|||||||
function styleNewCells (tr, existingCells) {
|
function styleNewCells (tr, existingCells) {
|
||||||
const table = findTable(tr.selection.$head)
|
const table = findTable(tr.selection.$head)
|
||||||
|
|
||||||
if (!table) return
|
|
||||||
|
|
||||||
const map = TableMap.get(table.node)
|
const map = TableMap.get(table.node)
|
||||||
const cellPositions = [...new Set(map.map)]
|
const cellPositions = [...new Set(map.map)]
|
||||||
const isNew = (pos) => !existingCells.has(table.node.nodeAt(pos))
|
const isNew = (pos) => !existingCells.has(table.node.nodeAt(pos))
|
||||||
@@ -1098,15 +1096,7 @@ function styleNewCells (tr, existingCells) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateTableCols (tr, tablePos, update) {
|
function runTableCommand (command, { state, tr, dispatch }, colsUpdate) {
|
||||||
const table = tr.doc.nodeAt(tablePos)
|
|
||||||
|
|
||||||
if (!table.attrs.cols.length) return
|
|
||||||
|
|
||||||
tr.setNodeMarkup(tablePos, null, { ...table.attrs, cols: update([...table.attrs.cols]) })
|
|
||||||
}
|
|
||||||
|
|
||||||
function runTableCommand (command, { state, tr, dispatch }, { colsUpdate } = {}) {
|
|
||||||
const table = findEditableTable(state)
|
const table = findEditableTable(state)
|
||||||
|
|
||||||
if (!table) return false
|
if (!table) return false
|
||||||
@@ -1122,7 +1112,13 @@ function runTableCommand (command, { state, tr, dispatch }, { colsUpdate } = {})
|
|||||||
styleNewCells(tr, existingCells)
|
styleNewCells(tr, existingCells)
|
||||||
|
|
||||||
if (colsUpdate && colsMatch) {
|
if (colsUpdate && colsMatch) {
|
||||||
updateTableCols(tr, tr.mapping.map(table.pos), (cols) => colsUpdate(cols, rect))
|
const tablePos = tr.mapping.map(table.pos)
|
||||||
|
const { attrs } = tr.doc.nodeAt(tablePos)
|
||||||
|
const cols = [...attrs.cols]
|
||||||
|
|
||||||
|
colsUpdate(cols, rect)
|
||||||
|
|
||||||
|
tr.setNodeMarkup(tablePos, null, { ...attrs, cols })
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
@@ -1142,9 +1138,10 @@ const TableCommands = Extension.create({
|
|||||||
plugin.props.handlePaste = (view, event, slice) => {
|
plugin.props.handlePaste = (view, event, slice) => {
|
||||||
const table = findTable(view.state.selection.$head)
|
const table = findTable(view.state.selection.$head)
|
||||||
|
|
||||||
if (table && !isRegularTable(table.node)) return view.state.selection instanceof CellSelection
|
if (!table) return false
|
||||||
|
if (!isRegularTable(table.node)) return view.state.selection instanceof CellSelection
|
||||||
|
|
||||||
const existingCells = table ? tableCellNodes(table.node) : new Set()
|
const existingCells = tableCellNodes(table.node)
|
||||||
|
|
||||||
const dispatch = (tr) => {
|
const dispatch = (tr) => {
|
||||||
styleNewCells(tr, existingCells)
|
styleNewCells(tr, existingCells)
|
||||||
@@ -1181,14 +1178,10 @@ const TableCommands = Extension.create({
|
|||||||
addCommands () {
|
addCommands () {
|
||||||
return {
|
return {
|
||||||
addTableRow: (after) => (props) => runTableCommand(after ? addRowAfter : addRowBefore, props),
|
addTableRow: (after) => (props) => runTableCommand(after ? addRowAfter : addRowBefore, props),
|
||||||
addTableColumn: (after) => (props) => runTableCommand(after ? addColumnAfter : addColumnBefore, props, {
|
addTableColumn: (after) => (props) => runTableCommand(after ? addColumnAfter : addColumnBefore, props, (cols, rect) => {
|
||||||
colsUpdate: (cols, rect) => {
|
const index = after ? rect.right : rect.left
|
||||||
const index = after ? rect.right : rect.left
|
|
||||||
|
|
||||||
cols.splice(index, 0, { ...cols[after ? rect.right - 1 : rect.left] })
|
cols.splice(index, 0, { ...cols[after ? index - 1 : index] })
|
||||||
|
|
||||||
return cols
|
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
deleteTableRow: () => (props) => {
|
deleteTableRow: () => (props) => {
|
||||||
const table = findEditableTable(props.state)
|
const table = findEditableTable(props.state)
|
||||||
@@ -1218,13 +1211,7 @@ const TableCommands = Extension.create({
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return runTableCommand(deleteColumn, props, {
|
return runTableCommand(deleteColumn, props, (cols, { left, right }) => cols.splice(left, right - left))
|
||||||
colsUpdate: (cols, { left, right }) => {
|
|
||||||
cols.splice(left, right - left)
|
|
||||||
|
|
||||||
return cols
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
mergeTableCells: () => (props) => runTableCommand(mergeCells, props),
|
mergeTableCells: () => (props) => runTableCommand(mergeCells, props),
|
||||||
splitTableCell: () => (props) => runTableCommand(splitCell, props),
|
splitTableCell: () => (props) => runTableCommand(splitCell, props),
|
||||||
@@ -1247,7 +1234,7 @@ const TableCommands = Extension.create({
|
|||||||
let htmlAttrs = table.node.attrs.htmlAttrs
|
let htmlAttrs = table.node.attrs.htmlAttrs
|
||||||
|
|
||||||
if (isFloating && align !== 'center') {
|
if (isFloating && align !== 'center') {
|
||||||
const gap = [el.style.marginLeft, el.style.marginRight].find((value) => value && value !== 'auto' && parseFloat(value)) || '0'
|
const gap = [el.style.marginLeft, el.style.marginRight].find((value) => parseFloat(value)) || '0'
|
||||||
|
|
||||||
margins = align === 'left' ? ['0', gap] : [gap, '0']
|
margins = align === 'left' ? ['0', gap] : [gap, '0']
|
||||||
htmlAttrs = withStyle(htmlAttrs, 'float', align)
|
htmlAttrs = withStyle(htmlAttrs, 'float', align)
|
||||||
@@ -1593,7 +1580,7 @@ export function buildEditor ({ dynamicAreaProps, attachmentsIndex, renderHtmlFor
|
|||||||
const MIN_SIZE_PX = 16
|
const MIN_SIZE_PX = 16
|
||||||
|
|
||||||
function findResizeTarget (view, event) {
|
function findResizeTarget (view, event) {
|
||||||
const cellDom = event.target.closest?.('td, th')
|
const cellDom = event.target.closest('td, th')
|
||||||
|
|
||||||
if (!cellDom) return null
|
if (!cellDom) return null
|
||||||
|
|
||||||
@@ -1671,7 +1658,7 @@ export function buildEditor ({ dynamicAreaProps, attachmentsIndex, renderHtmlFor
|
|||||||
guide.remove()
|
guide.remove()
|
||||||
document.body.style.cursor = ''
|
document.body.style.cursor = ''
|
||||||
|
|
||||||
const delta = ((isColumn ? e.clientX - event.clientX : e.clientY - event.clientY)) / dynamicAreaProps.getZoom()
|
const delta = (isColumn ? e.clientX - event.clientX : e.clientY - event.clientY) / dynamicAreaProps.getZoom()
|
||||||
|
|
||||||
if (!delta) return
|
if (!delta) return
|
||||||
|
|
||||||
@@ -1795,7 +1782,7 @@ export function buildEditor ({ dynamicAreaProps, attachmentsIndex, renderHtmlFor
|
|||||||
onUpdate: (updatedNode) => updatedNode.attrs.htmlAttrs === node.attrs.htmlAttrs,
|
onUpdate: (updatedNode) => updatedNode.attrs.htmlAttrs === node.attrs.htmlAttrs,
|
||||||
options: {
|
options: {
|
||||||
directions: ['top-left', 'top-right', 'bottom-left', 'bottom-right'],
|
directions: ['top-left', 'top-right', 'bottom-left', 'bottom-right'],
|
||||||
min: { width: 16, height: 16 },
|
min: { width: MIN_SIZE_PX, height: MIN_SIZE_PX },
|
||||||
preserveAspectRatio: true
|
preserveAspectRatio: true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -192,13 +192,13 @@
|
|||||||
class="absolute z-10 top-full mt-1 w-28 p-1 bg-white border border-neutral-200 rounded-lg shadow-lg"
|
class="absolute z-10 top-full mt-1 w-28 p-1 bg-white border border-neutral-200 rounded-lg shadow-lg"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
v-for="(label, style) in listStyles"
|
v-for="({ label, marker }, style) in listStyles"
|
||||||
:key="style"
|
:key="style"
|
||||||
class="flex items-center gap-2 w-full text-left px-2 py-1 rounded-md hover:bg-neutral-100"
|
class="flex items-center gap-2 w-full px-2 py-1 rounded-md hover:bg-neutral-100"
|
||||||
:class="{ 'bg-neutral-200': style === listStyle }"
|
:class="{ 'bg-neutral-200': style === listStyle }"
|
||||||
@click="toggleList(style)"
|
@click="toggleList(style)"
|
||||||
>
|
>
|
||||||
<span class="w-4 text-center">{{ listMarkers[style] }}</span>
|
<span class="w-4 text-center">{{ marker }}</span>
|
||||||
{{ label }}
|
{{ label }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -379,10 +379,7 @@ export default {
|
|||||||
IconList,
|
IconList,
|
||||||
IconX
|
IconX
|
||||||
},
|
},
|
||||||
inject: {
|
inject: ['t', 'documentFonts'],
|
||||||
t: 't',
|
|
||||||
documentFonts: { default: () => [] }
|
|
||||||
},
|
|
||||||
props: {
|
props: {
|
||||||
editor: {
|
editor: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@@ -445,16 +442,9 @@ export default {
|
|||||||
},
|
},
|
||||||
listStyles () {
|
listStyles () {
|
||||||
return {
|
return {
|
||||||
disc: this.t('dots'),
|
disc: { label: this.t('dots'), marker: '•' },
|
||||||
dash: this.t('dash'),
|
dash: { label: this.t('dash'), marker: '–' },
|
||||||
decimal: this.t('numbers')
|
decimal: { label: this.t('numbers'), marker: '1.' }
|
||||||
}
|
|
||||||
},
|
|
||||||
listMarkers () {
|
|
||||||
return {
|
|
||||||
disc: '•',
|
|
||||||
dash: '–',
|
|
||||||
decimal: '1.'
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
colors () {
|
colors () {
|
||||||
@@ -514,12 +504,12 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
toggleBold () {
|
toggleBold () {
|
||||||
this.toggleStyledMark('bold', 'font-weight', 'bold', this.isBold, (style) => parseInt(style.fontWeight) >= 600)
|
this.toggleStyledMark('bold', 'font-weight', this.isBold, (style) => parseInt(style.fontWeight) >= 600)
|
||||||
},
|
},
|
||||||
toggleItalic () {
|
toggleItalic () {
|
||||||
this.toggleStyledMark('italic', 'font-style', 'italic', this.isItalic, (style) => style.fontStyle === 'italic')
|
this.toggleStyledMark('italic', 'font-style', this.isItalic, (style) => style.fontStyle === 'italic')
|
||||||
},
|
},
|
||||||
toggleStyledMark (markName, property, value, isActive, isStyled) {
|
toggleStyledMark (markName, property, isActive, isStyled) {
|
||||||
const isSegmentStyled = ({ from }) => isStyled(getComputedStyle(this.textElementAt(from)))
|
const isSegmentStyled = ({ from }) => isStyled(getComputedStyle(this.textElementAt(from)))
|
||||||
|
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
@@ -540,7 +530,7 @@ export default {
|
|||||||
|
|
||||||
if (tr.docChanged) view.dispatch(tr)
|
if (tr.docChanged) view.dispatch(tr)
|
||||||
|
|
||||||
this.editor.commands.setListMarkerStyle(property, value)
|
this.editor.commands.setListMarkerStyle(property, markName)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
selectedTextSegments () {
|
selectedTextSegments () {
|
||||||
|
|||||||
Reference in new issue
Block a user