diff options
Diffstat (limited to 'app/assets/javascripts/content_editor/components/toolbar_table_button.vue')
-rw-r--r-- | app/assets/javascripts/content_editor/components/toolbar_table_button.vue | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/app/assets/javascripts/content_editor/components/toolbar_table_button.vue b/app/assets/javascripts/content_editor/components/toolbar_table_button.vue new file mode 100644 index 00000000000..49d3006e9bf --- /dev/null +++ b/app/assets/javascripts/content_editor/components/toolbar_table_button.vue @@ -0,0 +1,91 @@ +<script> +import { GlDropdown, GlDropdownDivider, GlDropdownForm, GlButton } from '@gitlab/ui'; +import { Editor as TiptapEditor } from '@tiptap/vue-2'; +import { __, sprintf } from '~/locale'; +import { clamp } from '../services/utils'; + +export const tableContentType = 'table'; + +const MIN_ROWS = 3; +const MIN_COLS = 3; +const MAX_ROWS = 8; +const MAX_COLS = 8; + +export default { + components: { + GlDropdown, + GlDropdownDivider, + GlDropdownForm, + GlButton, + }, + props: { + tiptapEditor: { + type: TiptapEditor, + required: true, + }, + }, + data() { + return { + maxRows: MIN_ROWS, + maxCols: MIN_COLS, + rows: 1, + cols: 1, + }; + }, + methods: { + list(n) { + return new Array(n).fill().map((_, i) => i + 1); + }, + setRowsAndCols(rows, cols) { + this.rows = rows; + this.cols = cols; + this.maxRows = clamp(rows + 1, MIN_ROWS, MAX_ROWS); + this.maxCols = clamp(cols + 1, MIN_COLS, MAX_COLS); + }, + resetState() { + this.rows = 1; + this.cols = 1; + }, + insertTable() { + this.tiptapEditor + .chain() + .focus() + .insertTable({ + rows: this.rows, + cols: this.cols, + withHeaderRow: true, + }) + .run(); + + this.resetState(); + + this.$emit('execute', { contentType: 'table' }); + }, + getButtonLabel(rows, cols) { + return sprintf(__('Insert a %{rows}x%{cols} table.'), { rows, cols }); + }, + }, +}; +</script> +<template> + <gl-dropdown size="small" category="tertiary" icon="table"> + <gl-dropdown-form class="gl-px-3! gl-w-auto!"> + <div class="gl-w-auto!"> + <div v-for="r of list(maxRows)" :key="r" class="gl-display-flex"> + <gl-button + v-for="c of list(maxCols)" + :key="c" + :data-testid="`table-${r}-${c}`" + :class="{ 'gl-bg-blue-50!': r <= rows && c <= cols }" + :aria-label="getButtonLabel(r, c)" + class="gl-display-inline! gl-px-0! gl-w-5! gl-h-5! gl-rounded-0!" + @mouseover="setRowsAndCols(r, c)" + @click="insertTable()" + /> + </div> + <gl-dropdown-divider /> + {{ getButtonLabel(rows, cols) }} + </div> + </gl-dropdown-form> + </gl-dropdown> +</template> |