refactor editor

This commit is contained in:
Timi
2026-08-25 17:35:42 +08:00
parent bc375e1b2d
commit 13bd61326d
40 changed files with 4444 additions and 55 deletions
@@ -0,0 +1,113 @@
<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>