diff --git a/app/javascript/template_builder/dynamic_block_menu.vue b/app/javascript/template_builder/dynamic_block_menu.vue
index d2e9e8ffc..73d7aa67a 100644
--- a/app/javascript/template_builder/dynamic_block_menu.vue
+++ b/app/javascript/template_builder/dynamic_block_menu.vue
@@ -4,56 +4,43 @@
:style="{ top: coords.top + 'px', left: coords.left + 'px', width: coords.width + 'px', height: coords.height + 'px' }"
>
-
-
-
-
-
-
+
+
+
@@ -89,9 +76,6 @@ const IconSplitCell = (props) => h('svg', { xmlns: 'http://www.w3.org/2000/svg',
export default {
name: 'DynamicBlockMenu',
- components: {
- IconTrash
- },
inject: ['t'],
props: {
coords: {
@@ -102,34 +86,55 @@ export default {
emits: ['command', 'resize'],
data () {
return {
- size: null
+ size: null,
+ toolbarHeight: 38
}
},
computed: {
- alignIcons () {
- return {
- left: IconAlignLeft,
- center: IconAlignCenter,
- right: IconAlignRight
+ actionRows () {
+ const alignActions = [
+ { command: 'setBlockAlign', arg: 'left', icon: IconAlignLeft, title: 'align_left', active: this.coords.align === 'left' },
+ { command: 'setBlockAlign', arg: 'center', icon: IconAlignCenter, title: 'align_center', active: this.coords.align === 'center' },
+ { command: 'setBlockAlign', arg: 'right', icon: IconAlignRight, title: 'align_right', active: this.coords.align === 'right' }
+ ]
+
+ if (this.coords.type !== 'table') {
+ return [[alignActions, [{ command: 'deleteSelection', icon: IconTrash, title: 'delete_image', danger: true }]]]
}
- },
- tableActions () {
+
return [
- { command: 'addTableRow', arg: false, icon: IconRowInsertTop, title: 'insert_row_above', structural: true },
- { command: 'addTableRow', arg: true, icon: IconRowInsertBottom, title: 'insert_row_below', structural: true },
- { command: 'addTableColumn', arg: false, icon: IconColumnInsertLeft, title: 'insert_column_left', structural: true },
- { command: 'addTableColumn', arg: true, icon: IconColumnInsertRight, title: 'insert_column_right', structural: true },
- { command: 'mergeTableCells', icon: IconMergeCells, title: 'merge_cells', structural: true, enabled: 'canMerge' },
- { command: 'splitTableCell', icon: IconSplitCell, title: 'split_cell', structural: true, enabled: 'canSplit' },
- { command: 'deleteTableRow', icon: IconRowRemove, title: 'delete_row', danger: true, structural: true },
- { command: 'deleteTableColumn', icon: IconColumnRemove, title: 'delete_column', danger: true, structural: true },
- { command: 'deleteTable', icon: IconTrash, title: 'delete_table', danger: true }
+ [
+ alignActions,
+ [
+ { command: 'addTableRow', arg: false, icon: IconRowInsertTop, title: 'insert_row_above', structural: true },
+ { command: 'addTableRow', arg: true, icon: IconRowInsertBottom, title: 'insert_row_below', structural: true },
+ { command: 'addTableColumn', arg: false, icon: IconColumnInsertLeft, title: 'insert_column_left', structural: true },
+ { command: 'addTableColumn', arg: true, icon: IconColumnInsertRight, title: 'insert_column_right', structural: true }
+ ]
+ ],
+ [
+ [
+ { command: 'mergeTableCells', icon: IconMergeCells, title: 'merge_cells', structural: true, enabled: 'canMerge' },
+ { command: 'splitTableCell', icon: IconSplitCell, title: 'split_cell', structural: true, enabled: 'canSplit' }
+ ],
+ [
+ { command: 'deleteTableRow', icon: IconRowRemove, title: 'delete_row', danger: true, structural: true },
+ { command: 'deleteTableColumn', icon: IconColumnRemove, title: 'delete_column', danger: true, structural: true },
+ { command: 'deleteTable', icon: IconTrash, title: 'delete_table', danger: true }
+ ]
+ ]
]
}
},
+ mounted () {
+ this.toolbarHeight = this.$refs.toolbar.offsetHeight
+ },
+ updated () {
+ this.toolbarHeight = this.$refs.toolbar.offsetHeight
+ },
beforeUnmount () {
- window.removeEventListener('mousemove', this.onResizeMove)
- window.removeEventListener('mouseup', this.onResizeEnd)
+ window.removeEventListener('pointermove', this.onResizeMove)
+ window.removeEventListener('pointerup', this.onResizeEnd)
},
methods: {
isDisabled (action) {
@@ -139,8 +144,8 @@ export default {
this.resizeStart = { x: event.clientX, y: event.clientY, width: this.coords.width, height: this.coords.height }
this.size = { width: this.coords.width, height: this.coords.height }
- window.addEventListener('mousemove', this.onResizeMove)
- window.addEventListener('mouseup', this.onResizeEnd)
+ window.addEventListener('pointermove', this.onResizeMove)
+ window.addEventListener('pointerup', this.onResizeEnd)
},
onResizeMove (event) {
const { x, y, width, height } = this.resizeStart
@@ -150,8 +155,8 @@ export default {
}
},
onResizeEnd () {
- window.removeEventListener('mousemove', this.onResizeMove)
- window.removeEventListener('mouseup', this.onResizeEnd)
+ window.removeEventListener('pointermove', this.onResizeMove)
+ window.removeEventListener('pointerup', this.onResizeEnd)
if (this.size.width !== this.coords.width || this.size.height !== this.coords.height) {
this.$emit('resize', this.size)
diff --git a/app/javascript/template_builder/dynamic_editor.js b/app/javascript/template_builder/dynamic_editor.js
index c1475fd64..ef25279c6 100644
--- a/app/javascript/template_builder/dynamic_editor.js
+++ b/app/javascript/template_builder/dynamic_editor.js
@@ -104,15 +104,24 @@ img.ProseMirror-separator {
}
[data-resize-handle] {
+ --handle-size: calc(10px / var(--zoom, 1));
display: none;
- width: 10px;
- height: 10px;
+ width: var(--handle-size);
+ height: var(--handle-size);
background: #ffffff;
- border: 2px solid #3b82f6;
+ border: calc(2px / var(--zoom, 1)) solid #3b82f6;
border-radius: 2px;
z-index: 1;
}
+@media (pointer: coarse) {
+ [data-resize-handle]::after {
+ content: "";
+ position: absolute;
+ inset: calc(-8px / var(--zoom, 1));
+ }
+}
+
.ProseMirror-selectednode [data-resize-wrapper] {
outline: 2px solid #3b82f6;
}
@@ -121,10 +130,10 @@ img.ProseMirror-separator {
display: block;
}
-[data-resize-handle="top-left"] { margin: -5px 0 0 -5px; cursor: nwse-resize; }
-[data-resize-handle="top-right"] { margin: -5px -5px 0 0; cursor: nesw-resize; }
-[data-resize-handle="bottom-left"] { margin: 0 0 -5px -5px; cursor: nesw-resize; }
-[data-resize-handle="bottom-right"] { margin: 0 -5px -5px 0; cursor: nwse-resize; }
+[data-resize-handle="top-left"] { margin: calc(var(--handle-size) / -2) 0 0 calc(var(--handle-size) / -2); cursor: nwse-resize; }
+[data-resize-handle="top-right"] { margin: calc(var(--handle-size) / -2) calc(var(--handle-size) / -2) 0 0; cursor: nesw-resize; }
+[data-resize-handle="bottom-left"] { margin: 0 0 calc(var(--handle-size) / -2) calc(var(--handle-size) / -2); cursor: nesw-resize; }
+[data-resize-handle="bottom-right"] { margin: 0 calc(var(--handle-size) / -2) calc(var(--handle-size) / -2) 0; cursor: nwse-resize; }
.ProseMirror .selectedCell {
position: relative;
diff --git a/app/javascript/template_builder/dynamic_menu.vue b/app/javascript/template_builder/dynamic_menu.vue
index 059243512..a4b0c2335 100644
--- a/app/javascript/template_builder/dynamic_menu.vue
+++ b/app/javascript/template_builder/dynamic_menu.vue
@@ -9,7 +9,7 @@
-
+
diff --git a/app/javascript/template_builder/dynamic_section.vue b/app/javascript/template_builder/dynamic_section.vue
index 73e7b3c84..b8187db05 100644
--- a/app/javascript/template_builder/dynamic_section.vue
+++ b/app/javascript/template_builder/dynamic_section.vue
@@ -8,7 +8,7 @@
class="absolute pointer-events-none z-10 bg-black"
:style="{ width: '1px', height: cursorHighlightCoords.height + 'px', left: cursorHighlightCoords.x + 'px', top: cursorHighlightCoords.y + 'px' }"
/>
-