114 lines
2.5 KiB
Vue
114 lines
2.5 KiB
Vue
<template>
|
||
<t-button v-popup="'插入表格'" variant="outline" :theme="active ? 'primary' : 'default'" @click="openPopup">
|
||
<t-icon name="table" />
|
||
</t-button>
|
||
<t-popup v-model="visible" placement="bottom" destroy-on-close>
|
||
<div class="table-picker" @mouseleave="onReset">
|
||
<div class="tip" v-text="`${hoverRow} × ${hoverCol}`" />
|
||
<div class="grid">
|
||
<button
|
||
v-for="item in tablePickerItems"
|
||
:key="item.key"
|
||
class="cell"
|
||
:class="{ active: item.active }"
|
||
type="button"
|
||
@mousemove="onHover(item.row, item.col)"
|
||
@click="onSelect(item.row, item.col)"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</t-popup>
|
||
</template>
|
||
|
||
<script lang="ts" setup>
|
||
import { TABLE_PICKER_SIZE } from "timi-web/editor";
|
||
import type { TiptapEditorInstance } from "timi-web/editor";
|
||
|
||
defineOptions({
|
||
name: "TiptapTableButton"
|
||
});
|
||
|
||
const props = defineProps<{
|
||
editor?: TiptapEditorInstance;
|
||
active: boolean;
|
||
}>();
|
||
|
||
const visible = ref(false);
|
||
const hoverRow = ref(1);
|
||
const hoverCol = ref(1);
|
||
|
||
const tablePickerItems = computed(() => {
|
||
const items: { key: string; row: number; col: number; active: boolean }[] = [];
|
||
for (let row = 1; row < TABLE_PICKER_SIZE + 1; row += 1) {
|
||
for (let col = 1; col < TABLE_PICKER_SIZE + 1; col += 1) {
|
||
items.push({
|
||
key: `${row}-${col}`,
|
||
row,
|
||
col,
|
||
active: row < hoverRow.value + 1 && col < hoverCol.value + 1
|
||
});
|
||
}
|
||
}
|
||
return items;
|
||
});
|
||
|
||
function openPopup() {
|
||
hoverRow.value = 1;
|
||
hoverCol.value = 1;
|
||
visible.value = true;
|
||
}
|
||
|
||
function onReset() {
|
||
hoverRow.value = 1;
|
||
hoverCol.value = 1;
|
||
}
|
||
|
||
function onHover(row: number, col: number) {
|
||
hoverRow.value = row;
|
||
hoverCol.value = col;
|
||
}
|
||
|
||
function onSelect(row: number, col: number) {
|
||
if (!props.editor) {
|
||
return;
|
||
}
|
||
props.editor.chain().focus().insertTable({ rows: row, cols: col, withHeaderRow: true }).run();
|
||
visible.value = false;
|
||
}
|
||
</script>
|
||
|
||
<style lang="less" scoped>
|
||
.table-picker {
|
||
width: min(20rem, calc(100vw - 2rem));
|
||
padding: 1rem 1rem calc(1rem + env(safe-area-inset-bottom));
|
||
box-sizing: border-box;
|
||
background: var(--td-bg-color-container, #fff);
|
||
|
||
.tip {
|
||
height: 1.5rem;
|
||
color: var(--td-text-color-secondary, #666);
|
||
font-size: .75rem;
|
||
line-height: 1.5rem;
|
||
}
|
||
|
||
.grid {
|
||
gap: .125rem;
|
||
display: grid;
|
||
grid-template-columns: repeat(7, 1fr);
|
||
}
|
||
|
||
.cell {
|
||
width: 1.75rem;
|
||
height: 1.75rem;
|
||
padding: 0;
|
||
border: 1px solid var(--td-component-border, #dcdcdc);
|
||
background: var(--td-bg-color-container, #fff);
|
||
|
||
&.active {
|
||
border-color: var(--td-brand-color, #0052d9);
|
||
background: var(--td-brand-color-light, #e0edff);
|
||
}
|
||
}
|
||
}
|
||
</style>
|