Files
timi-tdesign-mobile/src/components/tiptap-editor/TiptapTableButton.vue
T
2026-08-25 17:35:42 +08:00

114 lines
2.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>