Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/content_editor/components/wrappers/table_cell_base.vue')
-rw-r--r--app/assets/javascripts/content_editor/components/wrappers/table_cell_base.vue156
1 files changed, 84 insertions, 72 deletions
diff --git a/app/assets/javascripts/content_editor/components/wrappers/table_cell_base.vue b/app/assets/javascripts/content_editor/components/wrappers/table_cell_base.vue
index 5624bae34c2..44f5a2895fd 100644
--- a/app/assets/javascripts/content_editor/components/wrappers/table_cell_base.vue
+++ b/app/assets/javascripts/content_editor/components/wrappers/table_cell_base.vue
@@ -1,22 +1,71 @@
<script>
-import { GlDropdown, GlDropdownItem, GlDropdownDivider } from '@gitlab/ui';
+import { GlDisclosureDropdown } from '@gitlab/ui';
import { NodeViewWrapper, NodeViewContent } from '@tiptap/vue-2';
import { selectedRect as getSelectedRect } from '@tiptap/pm/tables';
-import { __ } from '~/locale';
+import { __, n__ } from '~/locale';
const TABLE_CELL_HEADER = 'th';
const TABLE_CELL_BODY = 'td';
+function getDropdownItems({ selectedRect, cellType, rowspan = 1, colspan = 1 }) {
+ const totalRows = selectedRect?.map.height;
+ const totalCols = selectedRect?.map.width;
+ const isTableBodyCell = cellType === TABLE_CELL_BODY;
+ const selectedRows = selectedRect ? selectedRect.bottom - selectedRect.top : 0;
+ const selectedCols = selectedRect ? selectedRect.right - selectedRect.left : 0;
+ const showSplitCellOption =
+ selectedRows === rowspan && selectedCols === colspan && (rowspan > 1 || colspan > 1);
+ const showMergeCellsOption = selectedRows !== rowspan || selectedCols !== colspan;
+ const numCellsToMerge = (selectedRows - rowspan + 1) * (selectedCols - colspan + 1);
+ const showDeleteRowOption = totalRows > selectedRows + 1 && isTableBodyCell;
+ const showDeleteColumnOption = totalCols > selectedCols;
+
+ return [
+ {
+ items: [
+ { text: __('Insert column before'), value: 'addColumnBefore' },
+ { text: __('Insert column after'), value: 'addColumnAfter' },
+ isTableBodyCell && { text: __('Insert row before'), value: 'addRowBefore' },
+ { text: __('Insert row after'), value: 'addRowAfter' },
+ ].filter(Boolean),
+ },
+ {
+ items: [
+ showSplitCellOption && { text: __('Split cell'), value: 'splitCell' },
+ showMergeCellsOption && {
+ text: n__('Merge %d cell', 'Merge %d cells', numCellsToMerge),
+ value: 'mergeCells',
+ },
+ ].filter(Boolean),
+ },
+ {
+ items: [
+ showDeleteRowOption && {
+ text: n__('Delete row', 'Delete %d rows', selectedRows),
+ value: 'deleteRow',
+ },
+ showDeleteColumnOption && {
+ text: n__('Delete column', 'Delete %d columns', selectedCols),
+ value: 'deleteColumn',
+ },
+ { text: __('Delete table'), value: 'deleteTable' },
+ ].filter(Boolean),
+ },
+ ].filter(({ items }) => items.length);
+}
+
export default {
name: 'TableCellBaseWrapper',
components: {
NodeViewWrapper,
NodeViewContent,
- GlDropdown,
- GlDropdownItem,
- GlDropdownDivider,
+ GlDisclosureDropdown,
},
props: {
+ getPos: {
+ type: Function,
+ required: true,
+ },
cellType: {
type: String,
validator: (type) => [TABLE_CELL_HEADER, TABLE_CELL_BODY].includes(type),
@@ -34,19 +83,17 @@ export default {
data() {
return {
displayActionsDropdown: false,
- preventHide: true,
selectedRect: null,
};
},
computed: {
- totalRows() {
- return this.selectedRect?.map.height;
- },
- totalCols() {
- return this.selectedRect?.map.width;
- },
- isTableBodyCell() {
- return this.cellType === TABLE_CELL_BODY;
+ dropdownItems() {
+ return getDropdownItems({
+ selectedRect: this.selectedRect,
+ cellType: this.cellType,
+ rowspan: this.node.attrs.rowspan,
+ colspan: this.node.attrs.colspan,
+ });
},
},
mounted() {
@@ -61,6 +108,13 @@ export default {
const { state } = this.editor;
const { $cursor } = state.selection;
+ try {
+ this.selectedRect = getSelectedRect(state);
+ } catch (e) {
+ // ignore error if the selection is not in a table
+ return;
+ }
+
if (!$cursor) return;
this.displayActionsDropdown = false;
@@ -71,54 +125,34 @@ export default {
break;
}
}
-
- if (this.displayActionsDropdown) {
- this.selectedRect = getSelectedRect(state);
- }
},
- runCommand(command) {
- this.editor.chain()[command]().run();
+
+ runCommand({ value: command }) {
this.hideDropdown();
+ this.editor.chain()[command]().run();
},
- handleHide($event) {
- if (this.preventHide) {
- $event.preventDefault();
- }
- this.preventHide = true;
- },
+
hideDropdown() {
- this.preventHide = false;
- this.$refs.dropdown?.hide();
+ this.$refs.dropdown?.close();
},
},
- i18n: {
- insertColumnBefore: __('Insert column before'),
- insertColumnAfter: __('Insert column after'),
- insertRowBefore: __('Insert row before'),
- insertRowAfter: __('Insert row after'),
- deleteRow: __('Delete row'),
- deleteColumn: __('Delete column'),
- deleteTable: __('Delete table'),
- editTableActions: __('Edit table'),
- },
- dropdownPopperOpts: {
- positionFixed: true,
- },
};
</script>
<template>
<node-view-wrapper
- class="gl-relative gl-padding-5 gl-min-w-10"
:as="cellType"
+ :rowspan="node.attrs.rowspan || 1"
+ :colspan="node.attrs.colspan || 1"
dir="auto"
+ class="gl-m-0! gl-p-0! gl-relative"
@click="hideDropdown"
>
<span
v-if="displayActionsDropdown"
contenteditable="false"
- class="gl-absolute gl-right-0 gl-top-0"
+ class="gl-absolute gl-right-0 gl-top-0 gl-pr-1 gl-pt-1"
>
- <gl-dropdown
+ <gl-disclosure-dropdown
ref="dropdown"
dropup
icon="chevron-down"
@@ -127,34 +161,12 @@ export default {
boundary="viewport"
no-caret
text-sr-only
- :text="$options.i18n.editTableActions"
- :popper-opts="$options.dropdownPopperOpts"
- @hide="handleHide($event)"
- >
- <gl-dropdown-item @click="runCommand('addColumnBefore')">
- {{ $options.i18n.insertColumnBefore }}
- </gl-dropdown-item>
- <gl-dropdown-item @click="runCommand('addColumnAfter')">
- {{ $options.i18n.insertColumnAfter }}
- </gl-dropdown-item>
- <gl-dropdown-item v-if="isTableBodyCell" @click="runCommand('addRowBefore')">
- {{ $options.i18n.insertRowBefore }}
- </gl-dropdown-item>
- <gl-dropdown-item @click="runCommand('addRowAfter')">
- {{ $options.i18n.insertRowAfter }}
- </gl-dropdown-item>
- <gl-dropdown-divider />
- <gl-dropdown-item v-if="totalRows > 2 && isTableBodyCell" @click="runCommand('deleteRow')">
- {{ $options.i18n.deleteRow }}
- </gl-dropdown-item>
- <gl-dropdown-item v-if="totalCols > 1" @click="runCommand('deleteColumn')">
- {{ $options.i18n.deleteColumn }}
- </gl-dropdown-item>
- <gl-dropdown-item @click="runCommand('deleteTable')">
- {{ $options.i18n.deleteTable }}
- </gl-dropdown-item>
- </gl-dropdown>
+ :items="dropdownItems"
+ :toggle-text="__('Edit table')"
+ positioning-strategy="fixed"
+ @action="runCommand"
+ />
</span>
- <node-view-content />
+ <node-view-content as="div" class="gl-p-5 gl-min-w-10" />
</node-view-wrapper>
</template>