Skip to content

Commit 9c89b2e

Browse files
author
ilimei
committed
✨ feat: 添加 table 控制器
1 parent a5a95f9 commit 9c89b2e

11 files changed

Lines changed: 1465 additions & 4 deletions

File tree

src/editor-kernel/kernel.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,4 +198,8 @@ export class Kernel extends EventEmitter implements IEditorKernel {
198198
}
199199
return this.editor.dispatchCommand(type, payload);
200200
}
201+
202+
getTheme() {
203+
return this.themes;
204+
}
201205
}

src/editor-kernel/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ export interface IEditor {
6666
* 获取文档编辑器根节点
6767
*/
6868
getRootElement(): HTMLElement | null;
69+
/**
70+
* 获取编辑器主题
71+
*/
72+
getTheme(): Record<string, string | Record<string, string>>;
6973
/**
7074
* 取消编辑器事件监听
7175
* @param event
@@ -97,6 +101,7 @@ export interface IEditor {
97101
* @param serviceId
98102
*/
99103
requireService<T>(serviceId: IServiceID<T>): T | null;
104+
100105
/**
101106
* 设置编辑器内容,type 为内容类型,content 为内容数据
102107
* @param type

src/plugins/table/node/index.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { TableNode } from '@lexical/table';
2+
import { EditorConfig, LexicalEditor } from 'lexical/LexicalEditor';
3+
4+
const OriginalCreateDOM = TableNode.prototype.createDOM;
5+
6+
export function patchTableNode() {
7+
Object.defineProperty(TableNode.prototype, 'createDOM', {
8+
configurable: true,
9+
enumerable: false,
10+
value: function (config: EditorConfig, editor?: LexicalEditor) {
11+
const table = OriginalCreateDOM.call(this, config, editor);
12+
console.info('------createDOM------->', table);
13+
const controller = document.createElement('div');
14+
table.append(controller);
15+
return table;
16+
},
17+
writable: true,
18+
});
19+
}
20+
21+
export { TableNode } from '@lexical/table';

src/plugins/table/plugin/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import {
22
$isTableNode,
33
TableCellNode,
4-
TableNode,
54
TableRowNode,
65
registerTableCellUnmergeTransform,
76
registerTablePlugin,
@@ -17,6 +16,7 @@ import { IEditorKernel, IEditorPluginConstructor } from '@/editor-kernel/types';
1716
import { IMarkdownShortCutService } from '@/plugins/markdown';
1817

1918
import { registerTableCommand } from '../command';
19+
import { TableNode, patchTableNode } from '../node';
2020

2121
// eslint-disable-next-line @typescript-eslint/no-empty-interface
2222
export interface TablePluginOptions {
@@ -38,6 +38,9 @@ export const TablePlugin: IEditorPluginConstructor<TablePluginOptions> = class
3838
options?: TablePluginOptions,
3939
) {
4040
super();
41+
patchTableNode();
42+
43+
console.dir(TableNode);
4144
// Register the horizontal rule node
4245
kernel.registerNodes([TableNode, TableRowNode, TableCellNode]);
4346
kernel.registerThemes({
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
import { createStyles } from 'antd-style';
2+
3+
export const useStyles = createStyles(({ css }) => {
4+
return css`
5+
will-change: transform;
6+
7+
position: absolute;
8+
z-index: 3;
9+
inset-block-start: 0;
10+
inset-inline-start: 0;
11+
12+
&.table-cell-action-button-container--active {
13+
pointer-events: auto;
14+
opacity: 1;
15+
}
16+
17+
&.table-cell-action-button-container--inactive {
18+
pointer-events: none;
19+
opacity: 0;
20+
}
21+
22+
.table-cell-action-button {
23+
cursor: pointer;
24+
25+
position: absolute;
26+
inset-block-start: 10px;
27+
inset-inline-end: 10px;
28+
29+
display: flex;
30+
display: inline-block;
31+
align-items: center;
32+
justify-content: center;
33+
34+
border: 0;
35+
border-radius: 15px;
36+
37+
color: #222;
38+
}
39+
40+
.dropdown {
41+
position: fixed;
42+
z-index: 100;
43+
44+
display: block;
45+
46+
min-height: 40px;
47+
border-radius: 8px;
48+
49+
background-color: #fff;
50+
box-shadow:
51+
0 12px 28px 0 rgba(0, 0, 0, 20%),
52+
0 2px 4px 0 rgba(0, 0, 0, 10%),
53+
inset 0 0 0 1px rgba(255, 255, 255, 50%);
54+
}
55+
56+
.dropdown .item {
57+
cursor: pointer;
58+
59+
display: flex;
60+
flex-direction: row;
61+
flex-shrink: 0;
62+
place-content: center space-between;
63+
64+
min-width: 100px;
65+
max-width: 264px;
66+
margin-block: 0;
67+
margin-inline: 8px;
68+
padding: 8px;
69+
border: 0;
70+
border-radius: 8px;
71+
72+
font-size: 15px;
73+
line-height: 16px;
74+
color: #050505;
75+
76+
background-color: #fff;
77+
}
78+
79+
.dropdown .item.wide {
80+
align-items: center;
81+
width: 260px;
82+
}
83+
84+
.dropdown .item.wide .icon-text-container {
85+
display: flex;
86+
87+
.text {
88+
min-width: 120px;
89+
}
90+
}
91+
92+
.dropdown .item .shortcut {
93+
align-self: flex-end;
94+
color: #939393;
95+
}
96+
97+
.dropdown .item .active {
98+
display: flex;
99+
width: 20px;
100+
height: 20px;
101+
background-size: contain;
102+
}
103+
104+
.dropdown .item:first-child {
105+
margin-block-start: 8px;
106+
}
107+
108+
.dropdown .item:last-child {
109+
margin-block-end: 8px;
110+
}
111+
112+
.dropdown .item:hover {
113+
background-color: #eee;
114+
}
115+
116+
.dropdown .item .text {
117+
display: flex;
118+
flex-grow: 1;
119+
min-width: 150px;
120+
line-height: 20px;
121+
}
122+
123+
.dropdown .item .icon {
124+
user-select: none;
125+
126+
display: flex;
127+
128+
width: 20px;
129+
height: 20px;
130+
margin-inline-end: 12px;
131+
132+
line-height: 16px;
133+
134+
background-repeat: no-repeat;
135+
background-position: center;
136+
background-size: contain;
137+
}
138+
139+
.dropdown .divider {
140+
width: auto;
141+
height: 1px;
142+
margin-block: 4px;
143+
margin-inline: 8px;
144+
145+
background-color: #eee;
146+
}
147+
`;
148+
});
149+
150+
export const dropDownStyles = createStyles(({ css }) => {
151+
return css`
152+
position: fixed;
153+
z-index: 100;
154+
155+
display: block;
156+
157+
min-height: 40px;
158+
border-radius: 8px;
159+
160+
background-color: #fff;
161+
box-shadow:
162+
0 12px 28px 0 rgba(0, 0, 0, 20%),
163+
0 2px 4px 0 rgba(0, 0, 0, 10%),
164+
inset 0 0 0 1px rgba(255, 255, 255, 50%);
165+
166+
.item {
167+
cursor: pointer;
168+
169+
display: flex;
170+
flex-direction: row;
171+
flex-shrink: 0;
172+
place-content: center space-between;
173+
174+
min-width: 100px;
175+
max-width: 264px;
176+
margin-block: 0;
177+
margin-inline: 8px;
178+
padding: 8px;
179+
border: 0;
180+
border-radius: 8px;
181+
182+
font-size: 15px;
183+
line-height: 16px;
184+
color: #050505;
185+
186+
background-color: #fff;
187+
}
188+
189+
.item.wide {
190+
align-items: center;
191+
width: 260px;
192+
}
193+
194+
.item.wide .icon-text-container {
195+
display: flex;
196+
197+
.text {
198+
min-width: 120px;
199+
}
200+
}
201+
202+
.item .shortcut {
203+
align-self: flex-end;
204+
color: #939393;
205+
}
206+
207+
.item .active {
208+
display: flex;
209+
width: 20px;
210+
height: 20px;
211+
background-size: contain;
212+
}
213+
214+
.item:first-child {
215+
margin-block-start: 8px;
216+
}
217+
218+
.item:last-child {
219+
margin-block-end: 8px;
220+
}
221+
222+
.item:hover {
223+
background-color: #eee;
224+
}
225+
226+
.item .text {
227+
display: flex;
228+
flex-grow: 1;
229+
min-width: 150px;
230+
line-height: 20px;
231+
}
232+
233+
.item .icon {
234+
user-select: none;
235+
236+
display: flex;
237+
238+
width: 20px;
239+
height: 20px;
240+
margin-inline-end: 12px;
241+
242+
line-height: 16px;
243+
244+
background-repeat: no-repeat;
245+
background-position: center;
246+
background-size: contain;
247+
}
248+
249+
.divider {
250+
width: auto;
251+
height: 1px;
252+
margin-block: 4px;
253+
margin-inline: 8px;
254+
255+
background-color: #eee;
256+
}
257+
`;
258+
});

0 commit comments

Comments
 (0)