Skip to content

Commit

Permalink
feat(tables): prototype
Browse files Browse the repository at this point in the history
Adding, editing, parse from input content, resize

#20, #182, #140
  • Loading branch information
iliyaZelenko committed Jun 1, 2020
1 parent 75fa6c0 commit 6442677
Show file tree
Hide file tree
Showing 8 changed files with 303 additions and 1 deletion.
26 changes: 25 additions & 1 deletion demo/pages/Index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,41 @@ export default {
Call mom
</li>
</ul>
<table>
<tr>
<th colspan="3" data-colwidth="100,0,0">Wide header</th>
</tr>
<tr>
<td>One</td>
<td>Two</td>
<td>Three</td>
</tr>
<tr>
<td>Four</td>
<td>Five</td>
<td>Six</td>
</tr>
</table>
`
}),
async created () {
const {
Heading, Bold, Italic, Strike, Underline, Code, CodeBlock, Paragraph, BulletList, OrderedList, ListItem,
Link, Blockquote, HardBreak, HorizontalRule, History, Image, TodoList, TodoItem
Link, Blockquote, HardBreak, HorizontalRule, History, Image, TodoList, TodoItem, Table, TableCell, TableHeader,
TableRow
} = await MAIN_MODULE
this.extensions = [
MyCustomExtension,
[Table, {
options: {
resizable: true
}
}],
TableCell,
TableHeader,
TodoList,
TableRow,
[TodoItem, {
options: {
nested: true
Expand Down
47 changes: 47 additions & 0 deletions src/components/TiptapVuetify.vue
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,53 @@ export default class TiptapVuetify extends Vue {
height: 0
font-style: italic
table
border-collapse: collapse
table-layout: fixed
width: 100%
margin: 0
overflow: hidden
td, th
min-width: 1em
border: 2px solid gray
padding: 3px 5px
vertical-align: top
box-sizing: border-box
position: relative
> *
margin-bottom: 0
th
font-weight: bold
text-align: left
.selectedCell:after
z-index: 2
position: absolute
content: ''
left: 0
right: 0
top: 0
bottom: 0
background: rgba(200, 200, 255, 0.4)
pointer-events: none
.column-resize-handle
position: absolute
right: -2px; top: 0; bottom: 0
width: 4px
z-index: 20
background-color: #adf
pointer-events: none
.tableWrapper
margin: 1em 0
overflow-x: auto
.resize-cursor
cursor: col-resize
&--disabled
// same color for disabled text as default light vuetify theme: vuetify/src/styles/settings/_light.scss#L30
color rgba(0, 0, 0, 0.38)
Expand Down
4 changes: 4 additions & 0 deletions src/extensions/nativeExtensions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,7 @@ export { default as Link } from '~/extensions/nativeExtensions/link/Link'
export { default as Image } from '~/extensions/nativeExtensions/image/Image'
export { default as TodoList } from '~/extensions/nativeExtensions/TodoList/TodoList'
export { default as TodoItem } from '~/extensions/nativeExtensions/TodoList/TodoItem'
export { default as Table } from '~/extensions/nativeExtensions/table/Table'
export { default as TableCell } from '~/extensions/nativeExtensions/table/TableCell'
export { default as TableHeader } from '~/extensions/nativeExtensions/table/TableHeader'
export { default as TableRow } from '~/extensions/nativeExtensions/table/TableRow'
48 changes: 48 additions & 0 deletions src/extensions/nativeExtensions/table/Table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Table as TableOriginal } from 'tiptap-extensions'
import { VuetifyIconsGroups } from '~/configs/theme'
import VuetifyIcon from '~/extensions/nativeExtensions/icons/VuetifyIcon'
import AbstractExtension from '~/extensions/AbstractExtension'
import ExtensionActionInterface from '~/extensions/actions/ExtensionActionInterface'
import Vue from 'vue'
import ExtensionActionRenderBtn from '~/extensions/actions/renders/btn/ExtensionActionRenderBtn.ts'
import TableWindow from '~/extensions/nativeExtensions/table/TableWindow.vue'

export default class Table extends AbstractExtension {
constructor (options) {
super(options, TableOriginal)
}

get availableActions (): ExtensionActionInterface[] {
const nativeExtensionName = 'table'

return [
{
render: new ExtensionActionRenderBtn({
tooltip: 'TODO',
icons: {
[VuetifyIconsGroups.md]: new VuetifyIcon('table'),
[VuetifyIconsGroups.fa]: new VuetifyIcon('fas fa-table'),
[VuetifyIconsGroups.mdi]: new VuetifyIcon('mdi-table'),
[VuetifyIconsGroups.mdiSvg]: new VuetifyIcon('M8.5,13.5L11,16.5L14.5,12L19,18H5M21,19V5C21,3.89 20.1,3 19,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19Z')
},
nativeExtensionName,
async onClick ({ context, editor }) {
const WindowComponent = Vue.extend(TableWindow)
const instance = new WindowComponent({
vuetify: Vue.prototype.tiptapVuetifyPlugin.vuetify,
propsData: {
value: true,
nativeExtensionName,
context,
editor
}
})

instance.$mount()
document.querySelector('body')!.appendChild(instance.$el)
}
})
}
]
}
}
13 changes: 13 additions & 0 deletions src/extensions/nativeExtensions/table/TableCell.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { TableCell as TableCellOriginal } from 'tiptap-extensions'
import ExtensionActionInterface from '~/extensions/actions/ExtensionActionInterface'
import AbstractExtension from '~/extensions/AbstractExtension'

export default class TableCell extends AbstractExtension {
constructor (options) {
super(options, TableCellOriginal)
}

get availableActions (): ExtensionActionInterface[] {
return []
}
}
13 changes: 13 additions & 0 deletions src/extensions/nativeExtensions/table/TableHeader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { TableHeader as TableHeaderOriginal } from 'tiptap-extensions'
import ExtensionActionInterface from '~/extensions/actions/ExtensionActionInterface'
import AbstractExtension from '~/extensions/AbstractExtension'

export default class TableHeader extends AbstractExtension {
constructor (options) {
super(options, TableHeaderOriginal)
}

get availableActions (): ExtensionActionInterface[] {
return []
}
}
13 changes: 13 additions & 0 deletions src/extensions/nativeExtensions/table/TableRow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { TableRow as TableRowOriginal } from 'tiptap-extensions'
import ExtensionActionInterface from '~/extensions/actions/ExtensionActionInterface'
import AbstractExtension from '~/extensions/AbstractExtension'

export default class TableRow extends AbstractExtension {
constructor (options) {
super(options, TableRowOriginal)
}

get availableActions (): ExtensionActionInterface[] {
return []
}
}
140 changes: 140 additions & 0 deletions src/extensions/nativeExtensions/table/TableWindow.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
<template>
<v-dialog
:value="value"
max-width="500px"
>
<v-card>
<v-card-title>
<span class="headline">
Tables
</span>

<v-spacer />

<v-btn
icon
@click="close"
>
<v-icon>{{ COMMON_ICONS.close[$tiptapVuetify.iconsGroup] }}</v-icon>
</v-btn>
</v-card-title>
<v-card-text>
<v-text-field
v-model="form.rowsCount"
label="Rows count"
/>
<v-text-field
v-model="form.colsCount"
label="Cols count"
/>
<v-checkbox
v-model="form.withHeaderRow"
label="With header row"
/>
</v-card-text>
<v-card-actions>
<v-btn
text
@click="close"
>
Close
</v-btn>

<v-btn
text
@click="apply"
>
Apply
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>

<script lang="ts">
import { mixins } from 'vue-class-component'
import { Component, Prop } from 'vue-property-decorator'
import {
VRow,
VCol,
VDialog,
VCard,
VCardTitle,
VCardText,
VCardActions,
VBtn,
VSpacer,
VIcon,
VTextField,
VCheckbox
} from 'vuetify/lib'
import I18nMixin from '~/mixins/I18nMixin'
import { COMMON_ICONS } from '~/configs/theme'
export const PROPS = {
VALUE: 'value' as const,
CONTEXT: 'context' as const,
EDITOR: 'editor' as const,
IMAGE_SOURCES: 'imageSources' as const,
IMAGE_SOURCES_OVERRIDE: 'imageSourcesOverride' as const,
NATIVE_EXTENSION_NAME: 'nativeExtensionName' as const
}
@Component({
components: { VRow, VCol, VDialog, VCard, VCardTitle, VCardText, VCardActions, VBtn, VSpacer, VIcon, VTextField, VCheckbox }
})
export default class TableWindow extends mixins(I18nMixin) {
@Prop({
type: Boolean,
default: false
})
readonly [PROPS.VALUE]: boolean
@Prop({
type: String,
required: true
})
readonly [PROPS.NATIVE_EXTENSION_NAME]: string
@Prop({
type: Object,
required: true
})
readonly [PROPS.CONTEXT]: any
@Prop({
type: Object,
required: true
})
readonly [PROPS.EDITOR]: any
@Prop({
type: Boolean,
required: false
})
readonly [PROPS.IMAGE_SOURCES_OVERRIDE]: any
readonly COMMON_ICONS = COMMON_ICONS
form = {
rowsCount: 2,
colsCount: 3,
withHeaderRow: false
}
apply () {
this[PROPS.CONTEXT].commands.createTable({
rowsCount: this.form.rowsCount,
colsCount: this.form.colsCount,
withHeaderRow: this.form.withHeaderRow
})
this.close()
this[PROPS.EDITOR].focus()
}
close () {
this.$destroy()
this.$el.parentNode!.removeChild(this.$el)
}
}
</script>

0 comments on commit 6442677

Please sign in to comment.