diff --git a/app/javascript/template_builder/dynamic_block_menu.vue b/app/javascript/template_builder/dynamic_block_menu.vue index c0da1151c..7ebb609c3 100644 --- a/app/javascript/template_builder/dynamic_block_menu.vue +++ b/app/javascript/template_builder/dynamic_block_menu.vue @@ -43,7 +43,7 @@
@@ -114,8 +114,8 @@ export default { ], [ [ - { command: 'mergeTableCells', icon: IconMergeCells, title: 'merge_cells', structural: true, enabled: 'canMerge' }, - { command: 'splitTableCell', icon: IconSplitCell, title: 'split_cell', structural: true, enabled: 'canSplit' } + { command: 'mergeTableCells', icon: IconMergeCells, title: 'merge_cells', structural: true, disabled: !this.coords.canMerge }, + { command: 'splitTableCell', icon: IconSplitCell, title: 'split_cell', structural: true, disabled: !this.coords.canSplit } ], [ { command: 'deleteTableRow', icon: IconRowRemove, title: 'delete_row', danger: true, structural: true }, @@ -138,7 +138,7 @@ export default { }, methods: { isDisabled (action) { - return (action.structural && !this.coords.isRegular) || (action.enabled && !this.coords[action.enabled]) + return (action.structural && !this.coords.isRegular) || action.disabled }, startResize (event) { this.resizeStart = { x: event.clientX, y: event.clientY, width: this.coords.width, height: this.coords.height } diff --git a/app/javascript/template_builder/dynamic_editor.js b/app/javascript/template_builder/dynamic_editor.js index 6cb28e8ac..fbf5a2685 100644 --- a/app/javascript/template_builder/dynamic_editor.js +++ b/app/javascript/template_builder/dynamic_editor.js @@ -1058,8 +1058,6 @@ function tableCellNodes (table) { function styleNewCells (tr, existingCells) { const table = findTable(tr.selection.$head) - if (!table) return - const map = TableMap.get(table.node) const cellPositions = [...new Set(map.map)] const isNew = (pos) => !existingCells.has(table.node.nodeAt(pos)) @@ -1098,15 +1096,7 @@ function styleNewCells (tr, existingCells) { }) } -function updateTableCols (tr, tablePos, update) { - 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 } = {}) { +function runTableCommand (command, { state, tr, dispatch }, colsUpdate) { const table = findEditableTable(state) if (!table) return false @@ -1122,7 +1112,13 @@ function runTableCommand (command, { state, tr, dispatch }, { colsUpdate } = {}) styleNewCells(tr, existingCells) 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 @@ -1142,9 +1138,10 @@ const TableCommands = Extension.create({ plugin.props.handlePaste = (view, event, slice) => { 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) => { styleNewCells(tr, existingCells) @@ -1181,14 +1178,10 @@ const TableCommands = Extension.create({ addCommands () { return { addTableRow: (after) => (props) => runTableCommand(after ? addRowAfter : addRowBefore, props), - addTableColumn: (after) => (props) => runTableCommand(after ? addColumnAfter : addColumnBefore, props, { - colsUpdate: (cols, rect) => { - const index = after ? rect.right : rect.left + addTableColumn: (after) => (props) => runTableCommand(after ? addColumnAfter : addColumnBefore, props, (cols, rect) => { + const index = after ? rect.right : rect.left - cols.splice(index, 0, { ...cols[after ? rect.right - 1 : rect.left] }) - - return cols - } + cols.splice(index, 0, { ...cols[after ? index - 1 : index] }) }), deleteTableRow: () => (props) => { const table = findEditableTable(props.state) @@ -1218,13 +1211,7 @@ const TableCommands = Extension.create({ return true } - return runTableCommand(deleteColumn, props, { - colsUpdate: (cols, { left, right }) => { - cols.splice(left, right - left) - - return cols - } - }) + return runTableCommand(deleteColumn, props, (cols, { left, right }) => cols.splice(left, right - left)) }, mergeTableCells: () => (props) => runTableCommand(mergeCells, props), splitTableCell: () => (props) => runTableCommand(splitCell, props), @@ -1247,7 +1234,7 @@ const TableCommands = Extension.create({ let htmlAttrs = table.node.attrs.htmlAttrs 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'] htmlAttrs = withStyle(htmlAttrs, 'float', align) @@ -1593,7 +1580,7 @@ export function buildEditor ({ dynamicAreaProps, attachmentsIndex, renderHtmlFor const MIN_SIZE_PX = 16 function findResizeTarget (view, event) { - const cellDom = event.target.closest?.('td, th') + const cellDom = event.target.closest('td, th') if (!cellDom) return null @@ -1671,7 +1658,7 @@ export function buildEditor ({ dynamicAreaProps, attachmentsIndex, renderHtmlFor guide.remove() 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 @@ -1795,7 +1782,7 @@ export function buildEditor ({ dynamicAreaProps, attachmentsIndex, renderHtmlFor onUpdate: (updatedNode) => updatedNode.attrs.htmlAttrs === node.attrs.htmlAttrs, options: { 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 } }) diff --git a/app/javascript/template_builder/dynamic_menu.vue b/app/javascript/template_builder/dynamic_menu.vue index a4b0c2335..7477affcc 100644 --- a/app/javascript/template_builder/dynamic_menu.vue +++ b/app/javascript/template_builder/dynamic_menu.vue @@ -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" > @@ -379,10 +379,7 @@ export default { IconList, IconX }, - inject: { - t: 't', - documentFonts: { default: () => [] } - }, + inject: ['t', 'documentFonts'], props: { editor: { type: Object, @@ -445,16 +442,9 @@ export default { }, listStyles () { return { - disc: this.t('dots'), - dash: this.t('dash'), - decimal: this.t('numbers') - } - }, - listMarkers () { - return { - disc: '•', - dash: '–', - decimal: '1.' + disc: { label: this.t('dots'), marker: '•' }, + dash: { label: this.t('dash'), marker: '–' }, + decimal: { label: this.t('numbers'), marker: '1.' } } }, colors () { @@ -514,12 +504,12 @@ export default { }) }, 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 () { - 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))) if (isActive) { @@ -540,7 +530,7 @@ export default { if (tr.docChanged) view.dispatch(tr) - this.editor.commands.setListMarkerStyle(property, value) + this.editor.commands.setListMarkerStyle(property, markName) } }, selectedTextSegments () {