@haklex/rich-plugin-floating-toolbar 0.0.80 → 0.0.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +542 -582
- package/dist/rich-plugin-floating-toolbar.css +2 -1
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -1,612 +1,572 @@
|
|
|
1
|
-
import { jsxs, Fragment, jsx } from "react/jsx-runtime";
|
|
2
1
|
import { $createRubyNode, $isRubyNode } from "@haklex/rich-editor/nodes";
|
|
3
2
|
import { ColorPicker } from "@haklex/rich-editor-ui";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { usePortalContainer, usePortalTheme, vars } from "@haklex/rich-style-token";
|
|
4
|
+
import { $isAutoLinkNode, $isLinkNode, TOGGLE_LINK_COMMAND } from "@lexical/link";
|
|
6
5
|
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
|
|
7
|
-
import { $
|
|
8
|
-
import { $getSelection, $isRangeSelection,
|
|
9
|
-
import { Bold,
|
|
10
|
-
import {
|
|
6
|
+
import { $getSelectionStyleValueForProperty, $patchStyleText } from "@lexical/selection";
|
|
7
|
+
import { $createTextNode, $getNodeByKey, $getSelection, $isRangeSelection, COMMAND_PRIORITY_LOW, FORMAT_TEXT_COMMAND, SELECTION_CHANGE_COMMAND } from "lexical";
|
|
8
|
+
import { Bold, Check, Code, Highlighter, Italic, Languages, Link, Strikethrough, Subscript, Superscript, Trash2, Underline, X } from "lucide-react";
|
|
9
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
11
10
|
import { createPortal } from "react-dom";
|
|
11
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
//#region src/styles.css.ts
|
|
12
13
|
var toolbar = "_1m6axz71";
|
|
13
14
|
var btn = "_1m6axz72";
|
|
14
15
|
var btnActive = "_1m6axz73";
|
|
15
|
-
var btnIndicator = "_1m6axz74";
|
|
16
16
|
var rubyEditor = "_1m6axz75";
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
var rubyPreviewBase = "_1m6axz78";
|
|
20
|
-
var rubyInputRow = "_1m6axz79";
|
|
21
|
-
var rubyInput = "_1m6axz7a";
|
|
22
|
-
var rubyActionBtn = "_1m6axz7b";
|
|
23
|
-
var rubyHint = "_1m6axz7c";
|
|
24
|
-
var separator = "_1m6axz7d";
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region src/FloatingToolbarPlugin.tsx
|
|
25
19
|
function isEffectiveLinkNode(node) {
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
if (!$isLinkNode(node)) return false;
|
|
21
|
+
return !$isAutoLinkNode(node) || !node.getIsUnlinked();
|
|
28
22
|
}
|
|
29
23
|
function isRegularLinkNode(node) {
|
|
30
|
-
|
|
24
|
+
return $isLinkNode(node) && !$isAutoLinkNode(node);
|
|
31
25
|
}
|
|
32
26
|
function collectSelectedActiveAutoLinkNodes(selection) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
autoLinkNodes.set(parent.getKey(), parent);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
return Array.from(autoLinkNodes.values());
|
|
27
|
+
const autoLinkNodes = /* @__PURE__ */ new Map();
|
|
28
|
+
for (const node of selection.getNodes()) {
|
|
29
|
+
if ($isAutoLinkNode(node) && !node.getIsUnlinked()) autoLinkNodes.set(node.getKey(), node);
|
|
30
|
+
const parent = node.getParent();
|
|
31
|
+
if ($isAutoLinkNode(parent) && !parent.getIsUnlinked()) autoLinkNodes.set(parent.getKey(), parent);
|
|
32
|
+
}
|
|
33
|
+
return Array.from(autoLinkNodes.values());
|
|
44
34
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
35
|
+
var INITIAL_STATE = {
|
|
36
|
+
isBold: false,
|
|
37
|
+
isItalic: false,
|
|
38
|
+
isUnderline: false,
|
|
39
|
+
isStrikethrough: false,
|
|
40
|
+
isSuperscript: false,
|
|
41
|
+
isSubscript: false,
|
|
42
|
+
isCode: false,
|
|
43
|
+
isHighlight: false,
|
|
44
|
+
isLink: false,
|
|
45
|
+
isRuby: false,
|
|
46
|
+
fontColor: ""
|
|
57
47
|
};
|
|
58
48
|
function findRubyAncestor(node) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
return null;
|
|
49
|
+
let current = node;
|
|
50
|
+
while (current) {
|
|
51
|
+
if ($isRubyNode(current)) return current;
|
|
52
|
+
current = current.getParent();
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
67
55
|
}
|
|
68
56
|
function getSelectedRubyNodes(nodes) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
return Array.from(rubyNodes.values());
|
|
57
|
+
const rubyNodes = /* @__PURE__ */ new Map();
|
|
58
|
+
for (const node of nodes) {
|
|
59
|
+
const rubyNode = findRubyAncestor(node);
|
|
60
|
+
if (rubyNode) rubyNodes.set(rubyNode.getKey(), rubyNode);
|
|
61
|
+
}
|
|
62
|
+
return Array.from(rubyNodes.values());
|
|
77
63
|
}
|
|
78
64
|
function getSelectionState(selection) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
};
|
|
65
|
+
const nodes = selection.getNodes();
|
|
66
|
+
const hasLink = nodes.some((node) => {
|
|
67
|
+
return isEffectiveLinkNode(node.getParent()) || isEffectiveLinkNode(node);
|
|
68
|
+
});
|
|
69
|
+
const hasRuby = getSelectedRubyNodes(nodes).length > 0;
|
|
70
|
+
return {
|
|
71
|
+
isBold: selection.hasFormat("bold"),
|
|
72
|
+
isItalic: selection.hasFormat("italic"),
|
|
73
|
+
isUnderline: selection.hasFormat("underline"),
|
|
74
|
+
isStrikethrough: selection.hasFormat("strikethrough"),
|
|
75
|
+
isSuperscript: selection.hasFormat("superscript"),
|
|
76
|
+
isSubscript: selection.hasFormat("subscript"),
|
|
77
|
+
isCode: selection.hasFormat("code"),
|
|
78
|
+
isHighlight: selection.hasFormat("highlight"),
|
|
79
|
+
isLink: hasLink,
|
|
80
|
+
isRuby: hasRuby,
|
|
81
|
+
fontColor: $getSelectionStyleValueForProperty(selection, "color", "")
|
|
82
|
+
};
|
|
98
83
|
}
|
|
99
|
-
function computePosition(nativeSelection,
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
left: clampedLeft
|
|
115
|
-
};
|
|
84
|
+
function computePosition(nativeSelection, toolbar, container) {
|
|
85
|
+
const rect = nativeSelection.getRangeAt(0).getBoundingClientRect();
|
|
86
|
+
if (rect.width === 0 && rect.height === 0) return null;
|
|
87
|
+
const toolbarWidth = toolbar.offsetWidth;
|
|
88
|
+
const toolbarHeight = toolbar.offsetHeight;
|
|
89
|
+
const containerRect = container === document.body ? void 0 : container.getBoundingClientRect();
|
|
90
|
+
const offsetX = containerRect?.left ?? 0;
|
|
91
|
+
const offsetY = containerRect?.top ?? 0;
|
|
92
|
+
const availableWidth = containerRect?.width ?? window.innerWidth;
|
|
93
|
+
const rawLeft = rect.left - offsetX + rect.width / 2 - toolbarWidth / 2;
|
|
94
|
+
const clampedLeft = Math.max(8, Math.min(rawLeft, availableWidth - toolbarWidth - 8));
|
|
95
|
+
return {
|
|
96
|
+
top: rect.top - offsetY - toolbarHeight - 10,
|
|
97
|
+
left: clampedLeft
|
|
98
|
+
};
|
|
116
99
|
}
|
|
117
100
|
function ToolbarButton({ active, onClick, ariaLabel, children }) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
children: [
|
|
130
|
-
children,
|
|
131
|
-
active && /* @__PURE__ */ jsx("span", { className: btnIndicator })
|
|
132
|
-
]
|
|
133
|
-
}
|
|
134
|
-
);
|
|
101
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
102
|
+
"aria-label": ariaLabel,
|
|
103
|
+
"aria-pressed": active,
|
|
104
|
+
className: `${btn}${active ? ` ${btnActive}` : ""}`,
|
|
105
|
+
type: "button",
|
|
106
|
+
onMouseDown: (e) => {
|
|
107
|
+
e.preventDefault();
|
|
108
|
+
onClick();
|
|
109
|
+
},
|
|
110
|
+
children: [children, active && /* @__PURE__ */ jsx("span", { className: "_1m6axz74" })]
|
|
111
|
+
});
|
|
135
112
|
}
|
|
136
|
-
|
|
137
|
-
|
|
113
|
+
var ICON_SIZE = 15;
|
|
114
|
+
var ICON_STROKE = 2;
|
|
138
115
|
function extractCssVarName(value) {
|
|
139
|
-
|
|
140
|
-
return match?.[1] ?? null;
|
|
116
|
+
return value.match(/^var\((--[^\s),]+)(?:,[^)]+)?\)$/)?.[1] ?? null;
|
|
141
117
|
}
|
|
142
118
|
function collectThemeVarNames(contract, output) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
collectThemeVarNames(value, output);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
return output;
|
|
119
|
+
if (typeof contract === "string") {
|
|
120
|
+
const cssVarName = extractCssVarName(contract);
|
|
121
|
+
if (cssVarName) output.add(cssVarName);
|
|
122
|
+
return output;
|
|
123
|
+
}
|
|
124
|
+
if (contract && typeof contract === "object") for (const value of Object.values(contract)) collectThemeVarNames(value, output);
|
|
125
|
+
return output;
|
|
154
126
|
}
|
|
155
|
-
|
|
127
|
+
var THEME_VAR_NAMES = Array.from(collectThemeVarNames(vars, /* @__PURE__ */ new Set()));
|
|
156
128
|
function FloatingToolbarPlugin() {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
children: /* @__PURE__ */ jsx(Trash2, { size: 14, strokeWidth: ICON_STROKE })
|
|
599
|
-
}
|
|
600
|
-
)
|
|
601
|
-
] }),
|
|
602
|
-
/* @__PURE__ */ jsx("span", { className: rubyHint, children: "Enter 保存 / Esc 取消" })
|
|
603
|
-
]
|
|
604
|
-
}
|
|
605
|
-
),
|
|
606
|
-
portalContainer
|
|
607
|
-
)
|
|
608
|
-
] });
|
|
129
|
+
const [editor] = useLexicalComposerContext();
|
|
130
|
+
const { className: portalClassName } = usePortalTheme();
|
|
131
|
+
const portalContainer = usePortalContainer();
|
|
132
|
+
const toolbarRef = useRef(null);
|
|
133
|
+
const [visible, setVisible] = useState(false);
|
|
134
|
+
const [state, setState] = useState(INITIAL_STATE);
|
|
135
|
+
const [rubyEdit, setRubyEdit] = useState(null);
|
|
136
|
+
const rubyEditorRef = useRef(null);
|
|
137
|
+
const rubyInputRef = useRef(null);
|
|
138
|
+
const rubyEditRef = useRef(rubyEdit);
|
|
139
|
+
rubyEditRef.current = rubyEdit;
|
|
140
|
+
const updateToolbar = useCallback(() => {
|
|
141
|
+
const selection = $getSelection();
|
|
142
|
+
if (!$isRangeSelection(selection) || selection.isCollapsed()) {
|
|
143
|
+
setVisible(false);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
setState(getSelectionState(selection));
|
|
147
|
+
setVisible(true);
|
|
148
|
+
}, []);
|
|
149
|
+
const applyThemeVars = useCallback((toolbar) => {
|
|
150
|
+
const rootElement = editor.getRootElement();
|
|
151
|
+
if (!rootElement) return;
|
|
152
|
+
const computed = window.getComputedStyle(rootElement);
|
|
153
|
+
for (const name of THEME_VAR_NAMES) {
|
|
154
|
+
const value = computed.getPropertyValue(name).trim();
|
|
155
|
+
if (value) toolbar.style.setProperty(name, value);
|
|
156
|
+
}
|
|
157
|
+
}, [editor]);
|
|
158
|
+
useEffect(() => {
|
|
159
|
+
const unregisterCommand = editor.registerCommand(SELECTION_CHANGE_COMMAND, () => {
|
|
160
|
+
updateToolbar();
|
|
161
|
+
return false;
|
|
162
|
+
}, COMMAND_PRIORITY_LOW);
|
|
163
|
+
const unregisterUpdate = editor.registerUpdateListener(({ editorState }) => {
|
|
164
|
+
editorState.read(() => {
|
|
165
|
+
updateToolbar();
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
return () => {
|
|
169
|
+
unregisterCommand();
|
|
170
|
+
unregisterUpdate();
|
|
171
|
+
};
|
|
172
|
+
}, [editor, updateToolbar]);
|
|
173
|
+
useEffect(() => {
|
|
174
|
+
if (!visible || !toolbarRef.current) return;
|
|
175
|
+
const positionToolbar = () => {
|
|
176
|
+
const toolbar = toolbarRef.current;
|
|
177
|
+
if (!toolbar) return;
|
|
178
|
+
applyThemeVars(toolbar);
|
|
179
|
+
const nativeSelection = window.getSelection();
|
|
180
|
+
if (!nativeSelection || nativeSelection.rangeCount === 0) {
|
|
181
|
+
setVisible(false);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const pos = computePosition(nativeSelection, toolbar, portalContainer);
|
|
185
|
+
if (!pos) {
|
|
186
|
+
setVisible(false);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
toolbar.style.top = `${pos.top}px`;
|
|
190
|
+
toolbar.style.left = `${pos.left}px`;
|
|
191
|
+
};
|
|
192
|
+
requestAnimationFrame(positionToolbar);
|
|
193
|
+
const rootElement = editor.getRootElement();
|
|
194
|
+
if (!rootElement) return;
|
|
195
|
+
let scrollParent = window;
|
|
196
|
+
let el = rootElement.parentElement;
|
|
197
|
+
while (el) {
|
|
198
|
+
const { overflowY } = window.getComputedStyle(el);
|
|
199
|
+
if (overflowY === "auto" || overflowY === "scroll") {
|
|
200
|
+
scrollParent = el;
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
el = el.parentElement;
|
|
204
|
+
}
|
|
205
|
+
const onScroll = () => requestAnimationFrame(positionToolbar);
|
|
206
|
+
scrollParent.addEventListener("scroll", onScroll, { passive: true });
|
|
207
|
+
return () => scrollParent.removeEventListener("scroll", onScroll);
|
|
208
|
+
}, [
|
|
209
|
+
applyThemeVars,
|
|
210
|
+
editor,
|
|
211
|
+
visible,
|
|
212
|
+
state
|
|
213
|
+
]);
|
|
214
|
+
const handleFormat = useCallback((format) => {
|
|
215
|
+
editor.dispatchCommand(FORMAT_TEXT_COMMAND, format);
|
|
216
|
+
}, [editor]);
|
|
217
|
+
const handleLink = useCallback(() => {
|
|
218
|
+
editor.update(() => {
|
|
219
|
+
const selection = $getSelection();
|
|
220
|
+
if (!$isRangeSelection(selection)) return;
|
|
221
|
+
const nodes = selection.getNodes();
|
|
222
|
+
if (nodes.some((node) => {
|
|
223
|
+
return isEffectiveLinkNode(node.getParent()) || isEffectiveLinkNode(node);
|
|
224
|
+
})) {
|
|
225
|
+
for (const autoLinkNode of collectSelectedActiveAutoLinkNodes(selection)) {
|
|
226
|
+
autoLinkNode.setIsUnlinked(true);
|
|
227
|
+
autoLinkNode.markDirty();
|
|
228
|
+
}
|
|
229
|
+
if (nodes.some((node) => {
|
|
230
|
+
return isRegularLinkNode(node.getParent()) || isRegularLinkNode(node);
|
|
231
|
+
})) editor.dispatchCommand(TOGGLE_LINK_COMMAND, null);
|
|
232
|
+
} else {
|
|
233
|
+
const text = selection.getTextContent();
|
|
234
|
+
const url = /^https?:\/\//.test(text) ? text : "";
|
|
235
|
+
editor.dispatchCommand(TOGGLE_LINK_COMMAND, url || "https://");
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
}, [editor]);
|
|
239
|
+
const handleColor = useCallback((value) => {
|
|
240
|
+
editor.update(() => {
|
|
241
|
+
const sel = $getSelection();
|
|
242
|
+
if ($isRangeSelection(sel)) $patchStyleText(sel, { color: value === "inherit" ? null : value });
|
|
243
|
+
});
|
|
244
|
+
}, [editor]);
|
|
245
|
+
const handleRuby = useCallback(() => {
|
|
246
|
+
editor.update(() => {
|
|
247
|
+
const selection = $getSelection();
|
|
248
|
+
if (!$isRangeSelection(selection)) return;
|
|
249
|
+
const rubyNodes = getSelectedRubyNodes(selection.getNodes());
|
|
250
|
+
if (rubyNodes.length > 0) {
|
|
251
|
+
const rubyNode = rubyNodes[0];
|
|
252
|
+
if (!rubyNode) return;
|
|
253
|
+
setRubyEdit({
|
|
254
|
+
nodeKey: rubyNode.getKey(),
|
|
255
|
+
reading: rubyNode.getReading(),
|
|
256
|
+
baseText: rubyNode.getTextContent(),
|
|
257
|
+
isNew: false
|
|
258
|
+
});
|
|
259
|
+
} else {
|
|
260
|
+
const text = selection.getTextContent();
|
|
261
|
+
if (!text.trim()) return;
|
|
262
|
+
selection.removeText();
|
|
263
|
+
const rubyNode = $createRubyNode("");
|
|
264
|
+
rubyNode.append($createTextNode(text));
|
|
265
|
+
const freshSelection = $getSelection();
|
|
266
|
+
if ($isRangeSelection(freshSelection)) freshSelection.insertNodes([rubyNode]);
|
|
267
|
+
setRubyEdit({
|
|
268
|
+
nodeKey: rubyNode.getKey(),
|
|
269
|
+
reading: "",
|
|
270
|
+
baseText: text,
|
|
271
|
+
isNew: true
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
}, [editor]);
|
|
276
|
+
const handleRubyConfirm = useCallback(() => {
|
|
277
|
+
const edit = rubyEditRef.current;
|
|
278
|
+
if (!edit) return;
|
|
279
|
+
editor.update(() => {
|
|
280
|
+
const node = $getNodeByKey(edit.nodeKey);
|
|
281
|
+
if ($isRubyNode(node)) node.setReading(edit.reading);
|
|
282
|
+
});
|
|
283
|
+
setRubyEdit(null);
|
|
284
|
+
}, [editor]);
|
|
285
|
+
const handleRubyCancel = useCallback(() => {
|
|
286
|
+
const edit = rubyEditRef.current;
|
|
287
|
+
if (!edit) return;
|
|
288
|
+
if (edit.isNew) editor.update(() => {
|
|
289
|
+
const node = $getNodeByKey(edit.nodeKey);
|
|
290
|
+
if ($isRubyNode(node)) {
|
|
291
|
+
const children = node.getChildren();
|
|
292
|
+
for (const child of children) node.insertBefore(child);
|
|
293
|
+
node.remove();
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
setRubyEdit(null);
|
|
297
|
+
}, [editor]);
|
|
298
|
+
const handleRubyDelete = useCallback(() => {
|
|
299
|
+
const edit = rubyEditRef.current;
|
|
300
|
+
if (!edit) return;
|
|
301
|
+
editor.update(() => {
|
|
302
|
+
const node = $getNodeByKey(edit.nodeKey);
|
|
303
|
+
if ($isRubyNode(node)) {
|
|
304
|
+
const children = node.getChildren();
|
|
305
|
+
for (const child of children) node.insertBefore(child);
|
|
306
|
+
node.remove();
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
setRubyEdit(null);
|
|
310
|
+
}, [editor]);
|
|
311
|
+
const isRubyEditing = rubyEdit !== null;
|
|
312
|
+
useEffect(() => {
|
|
313
|
+
if (!isRubyEditing) return;
|
|
314
|
+
const handleClickOutside = (e) => {
|
|
315
|
+
const currentEdit = rubyEditRef.current;
|
|
316
|
+
if (!currentEdit) return;
|
|
317
|
+
if (rubyEditorRef.current && !rubyEditorRef.current.contains(e.target)) {
|
|
318
|
+
if (currentEdit.reading.trim()) editor.update(() => {
|
|
319
|
+
const node = $getNodeByKey(currentEdit.nodeKey);
|
|
320
|
+
if ($isRubyNode(node)) node.setReading(currentEdit.reading);
|
|
321
|
+
});
|
|
322
|
+
else if (currentEdit.isNew) editor.update(() => {
|
|
323
|
+
const node = $getNodeByKey(currentEdit.nodeKey);
|
|
324
|
+
if ($isRubyNode(node)) {
|
|
325
|
+
const children = node.getChildren();
|
|
326
|
+
for (const child of children) node.insertBefore(child);
|
|
327
|
+
node.remove();
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
setRubyEdit(null);
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
const timer = setTimeout(() => {
|
|
334
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
335
|
+
}, 0);
|
|
336
|
+
return () => {
|
|
337
|
+
clearTimeout(timer);
|
|
338
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
339
|
+
};
|
|
340
|
+
}, [editor, isRubyEditing]);
|
|
341
|
+
useEffect(() => {
|
|
342
|
+
if (!rubyEdit || !rubyEditorRef.current) return;
|
|
343
|
+
const positionEditor = () => {
|
|
344
|
+
const editorEl = rubyEditorRef.current;
|
|
345
|
+
if (!editorEl) return;
|
|
346
|
+
applyThemeVars(editorEl);
|
|
347
|
+
const rubyDom = editor.getElementByKey(rubyEdit.nodeKey);
|
|
348
|
+
if (!rubyDom) return;
|
|
349
|
+
const rect = rubyDom.getBoundingClientRect();
|
|
350
|
+
const containerRect = portalContainer === document.body ? void 0 : portalContainer.getBoundingClientRect();
|
|
351
|
+
const oX = containerRect?.left ?? 0;
|
|
352
|
+
const oY = containerRect?.top ?? 0;
|
|
353
|
+
const availW = containerRect?.width ?? window.innerWidth;
|
|
354
|
+
const editorWidth = editorEl.offsetWidth;
|
|
355
|
+
const rawLeft = rect.left - oX + rect.width / 2 - editorWidth / 2;
|
|
356
|
+
const clampedLeft = Math.max(8, Math.min(rawLeft, availW - editorWidth - 8));
|
|
357
|
+
editorEl.style.top = `${rect.bottom - oY + 8}px`;
|
|
358
|
+
editorEl.style.left = `${clampedLeft}px`;
|
|
359
|
+
};
|
|
360
|
+
requestAnimationFrame(positionEditor);
|
|
361
|
+
requestAnimationFrame(() => {
|
|
362
|
+
rubyInputRef.current?.focus();
|
|
363
|
+
});
|
|
364
|
+
}, [
|
|
365
|
+
applyThemeVars,
|
|
366
|
+
editor,
|
|
367
|
+
rubyEdit
|
|
368
|
+
]);
|
|
369
|
+
if (!visible && !rubyEdit) return null;
|
|
370
|
+
const toolbarClassName = portalClassName ? `${toolbar} ${portalClassName}` : toolbar;
|
|
371
|
+
const rubyEditorClassName = portalClassName ? `${rubyEditor} ${portalClassName}` : rubyEditor;
|
|
372
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [visible && !rubyEdit && createPortal(/* @__PURE__ */ jsxs("div", {
|
|
373
|
+
"aria-label": "Text formatting",
|
|
374
|
+
className: toolbarClassName,
|
|
375
|
+
ref: toolbarRef,
|
|
376
|
+
role: "toolbar",
|
|
377
|
+
style: {
|
|
378
|
+
position: "fixed",
|
|
379
|
+
zIndex: 50
|
|
380
|
+
},
|
|
381
|
+
children: [
|
|
382
|
+
/* @__PURE__ */ jsx(ToolbarButton, {
|
|
383
|
+
active: state.isBold,
|
|
384
|
+
ariaLabel: "Bold",
|
|
385
|
+
onClick: () => handleFormat("bold"),
|
|
386
|
+
children: /* @__PURE__ */ jsx(Bold, {
|
|
387
|
+
size: ICON_SIZE,
|
|
388
|
+
strokeWidth: ICON_STROKE
|
|
389
|
+
})
|
|
390
|
+
}),
|
|
391
|
+
/* @__PURE__ */ jsx(ToolbarButton, {
|
|
392
|
+
active: state.isItalic,
|
|
393
|
+
ariaLabel: "Italic",
|
|
394
|
+
onClick: () => handleFormat("italic"),
|
|
395
|
+
children: /* @__PURE__ */ jsx(Italic, {
|
|
396
|
+
size: ICON_SIZE,
|
|
397
|
+
strokeWidth: ICON_STROKE
|
|
398
|
+
})
|
|
399
|
+
}),
|
|
400
|
+
/* @__PURE__ */ jsx(ToolbarButton, {
|
|
401
|
+
active: state.isUnderline,
|
|
402
|
+
ariaLabel: "Underline",
|
|
403
|
+
onClick: () => handleFormat("underline"),
|
|
404
|
+
children: /* @__PURE__ */ jsx(Underline, {
|
|
405
|
+
size: ICON_SIZE,
|
|
406
|
+
strokeWidth: ICON_STROKE
|
|
407
|
+
})
|
|
408
|
+
}),
|
|
409
|
+
/* @__PURE__ */ jsx(ToolbarButton, {
|
|
410
|
+
active: state.isStrikethrough,
|
|
411
|
+
ariaLabel: "Strikethrough",
|
|
412
|
+
onClick: () => handleFormat("strikethrough"),
|
|
413
|
+
children: /* @__PURE__ */ jsx(Strikethrough, {
|
|
414
|
+
size: ICON_SIZE,
|
|
415
|
+
strokeWidth: ICON_STROKE
|
|
416
|
+
})
|
|
417
|
+
}),
|
|
418
|
+
/* @__PURE__ */ jsx(ToolbarButton, {
|
|
419
|
+
active: state.isSuperscript,
|
|
420
|
+
ariaLabel: "Superscript",
|
|
421
|
+
onClick: () => handleFormat("superscript"),
|
|
422
|
+
children: /* @__PURE__ */ jsx(Superscript, {
|
|
423
|
+
size: ICON_SIZE,
|
|
424
|
+
strokeWidth: ICON_STROKE
|
|
425
|
+
})
|
|
426
|
+
}),
|
|
427
|
+
/* @__PURE__ */ jsx(ToolbarButton, {
|
|
428
|
+
active: state.isSubscript,
|
|
429
|
+
ariaLabel: "Subscript",
|
|
430
|
+
onClick: () => handleFormat("subscript"),
|
|
431
|
+
children: /* @__PURE__ */ jsx(Subscript, {
|
|
432
|
+
size: ICON_SIZE,
|
|
433
|
+
strokeWidth: ICON_STROKE
|
|
434
|
+
})
|
|
435
|
+
}),
|
|
436
|
+
/* @__PURE__ */ jsx("span", { className: "_1m6axz7d" }),
|
|
437
|
+
/* @__PURE__ */ jsx(ToolbarButton, {
|
|
438
|
+
active: state.isCode,
|
|
439
|
+
ariaLabel: "Code",
|
|
440
|
+
onClick: () => handleFormat("code"),
|
|
441
|
+
children: /* @__PURE__ */ jsx(Code, {
|
|
442
|
+
size: ICON_SIZE,
|
|
443
|
+
strokeWidth: ICON_STROKE
|
|
444
|
+
})
|
|
445
|
+
}),
|
|
446
|
+
/* @__PURE__ */ jsx(ToolbarButton, {
|
|
447
|
+
active: state.isHighlight,
|
|
448
|
+
ariaLabel: "Highlight",
|
|
449
|
+
onClick: () => handleFormat("highlight"),
|
|
450
|
+
children: /* @__PURE__ */ jsx(Highlighter, {
|
|
451
|
+
size: ICON_SIZE,
|
|
452
|
+
strokeWidth: ICON_STROKE
|
|
453
|
+
})
|
|
454
|
+
}),
|
|
455
|
+
/* @__PURE__ */ jsx(ToolbarButton, {
|
|
456
|
+
active: state.isLink,
|
|
457
|
+
ariaLabel: "Link",
|
|
458
|
+
onClick: handleLink,
|
|
459
|
+
children: /* @__PURE__ */ jsx(Link, {
|
|
460
|
+
size: ICON_SIZE,
|
|
461
|
+
strokeWidth: ICON_STROKE
|
|
462
|
+
})
|
|
463
|
+
}),
|
|
464
|
+
/* @__PURE__ */ jsx(ToolbarButton, {
|
|
465
|
+
active: state.isRuby,
|
|
466
|
+
ariaLabel: "Ruby annotation",
|
|
467
|
+
onClick: handleRuby,
|
|
468
|
+
children: /* @__PURE__ */ jsx(Languages, {
|
|
469
|
+
size: ICON_SIZE,
|
|
470
|
+
strokeWidth: ICON_STROKE
|
|
471
|
+
})
|
|
472
|
+
}),
|
|
473
|
+
/* @__PURE__ */ jsx("span", { className: "_1m6axz7d" }),
|
|
474
|
+
/* @__PURE__ */ jsx(ColorPicker, {
|
|
475
|
+
currentColor: state.fontColor || "inherit",
|
|
476
|
+
onSelect: handleColor
|
|
477
|
+
})
|
|
478
|
+
]
|
|
479
|
+
}), portalContainer), rubyEdit && createPortal(/* @__PURE__ */ jsxs("div", {
|
|
480
|
+
className: rubyEditorClassName,
|
|
481
|
+
ref: rubyEditorRef,
|
|
482
|
+
style: {
|
|
483
|
+
position: "fixed",
|
|
484
|
+
zIndex: 51
|
|
485
|
+
},
|
|
486
|
+
children: [
|
|
487
|
+
/* @__PURE__ */ jsxs("div", {
|
|
488
|
+
className: "_1m6axz76",
|
|
489
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
490
|
+
className: "_1m6axz77",
|
|
491
|
+
children: rubyEdit.reading || "\xA0"
|
|
492
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
493
|
+
className: "_1m6axz78",
|
|
494
|
+
children: rubyEdit.baseText
|
|
495
|
+
})]
|
|
496
|
+
}),
|
|
497
|
+
/* @__PURE__ */ jsxs("div", {
|
|
498
|
+
className: "_1m6axz79",
|
|
499
|
+
children: [
|
|
500
|
+
/* @__PURE__ */ jsx("input", {
|
|
501
|
+
className: "_1m6axz7a",
|
|
502
|
+
placeholder: "读音",
|
|
503
|
+
ref: rubyInputRef,
|
|
504
|
+
value: rubyEdit.reading,
|
|
505
|
+
onChange: (e) => setRubyEdit((prev) => prev ? {
|
|
506
|
+
...prev,
|
|
507
|
+
reading: e.target.value
|
|
508
|
+
} : null),
|
|
509
|
+
onKeyDown: (e) => {
|
|
510
|
+
if (e.key === "Enter") {
|
|
511
|
+
e.preventDefault();
|
|
512
|
+
handleRubyConfirm();
|
|
513
|
+
}
|
|
514
|
+
if (e.key === "Escape") {
|
|
515
|
+
e.preventDefault();
|
|
516
|
+
handleRubyCancel();
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}),
|
|
520
|
+
/* @__PURE__ */ jsx("button", {
|
|
521
|
+
"aria-label": "Confirm",
|
|
522
|
+
className: "_1m6axz7b",
|
|
523
|
+
style: { color: "#22c55e" },
|
|
524
|
+
type: "button",
|
|
525
|
+
onMouseDown: (e) => {
|
|
526
|
+
e.preventDefault();
|
|
527
|
+
handleRubyConfirm();
|
|
528
|
+
},
|
|
529
|
+
children: /* @__PURE__ */ jsx(Check, {
|
|
530
|
+
size: 14,
|
|
531
|
+
strokeWidth: ICON_STROKE
|
|
532
|
+
})
|
|
533
|
+
}),
|
|
534
|
+
/* @__PURE__ */ jsx("button", {
|
|
535
|
+
"aria-label": "Cancel",
|
|
536
|
+
className: "_1m6axz7b",
|
|
537
|
+
type: "button",
|
|
538
|
+
onMouseDown: (e) => {
|
|
539
|
+
e.preventDefault();
|
|
540
|
+
handleRubyCancel();
|
|
541
|
+
},
|
|
542
|
+
children: /* @__PURE__ */ jsx(X, {
|
|
543
|
+
size: 14,
|
|
544
|
+
strokeWidth: ICON_STROKE
|
|
545
|
+
})
|
|
546
|
+
}),
|
|
547
|
+
/* @__PURE__ */ jsx("span", { className: "_1m6axz7d" }),
|
|
548
|
+
/* @__PURE__ */ jsx("button", {
|
|
549
|
+
"aria-label": "Delete ruby",
|
|
550
|
+
className: "_1m6axz7b",
|
|
551
|
+
style: { color: "#ef4444" },
|
|
552
|
+
type: "button",
|
|
553
|
+
onMouseDown: (e) => {
|
|
554
|
+
e.preventDefault();
|
|
555
|
+
handleRubyDelete();
|
|
556
|
+
},
|
|
557
|
+
children: /* @__PURE__ */ jsx(Trash2, {
|
|
558
|
+
size: 14,
|
|
559
|
+
strokeWidth: ICON_STROKE
|
|
560
|
+
})
|
|
561
|
+
})
|
|
562
|
+
]
|
|
563
|
+
}),
|
|
564
|
+
/* @__PURE__ */ jsx("span", {
|
|
565
|
+
className: "_1m6axz7c",
|
|
566
|
+
children: "Enter 保存 / Esc 取消"
|
|
567
|
+
})
|
|
568
|
+
]
|
|
569
|
+
}), portalContainer)] });
|
|
609
570
|
}
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
};
|
|
571
|
+
//#endregion
|
|
572
|
+
export { FloatingToolbarPlugin };
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
:root{--rc-text: #000;--rc-text-secondary: #27272a;--rc-text-tertiary: #71717a;--rc-text-quaternary: #a1a1aa;--rc-bg: #ffffff;--rc-bg-secondary: #fafafa;--rc-bg-tertiary: #f4f4f5;--rc-fill: #e8e8ec;--rc-fill-secondary: #eeeeef;--rc-fill-tertiary: #f4f4f6;--rc-fill-quaternary: #f9f9fa;--rc-border: #f4f4f5;--rc-accent: #2563eb;--rc-accent-light: #2563eb20;--rc-link: #2563eb;--rc-code-text: #3f3f46;--rc-code-bg: #f4f4f5;--rc-hr-border: #e4e4e7;--rc-quote-border: #2563eb;--rc-quote-bg: #eff6ff;--rc-alert-info: #006bb7;--rc-alert-warning: #cc5500;--rc-alert-tip: #11cc00;--rc-alert-caution: #cc0011;--rc-alert-important: #5500cc;--rc-max-width: 700px;--rc-shadow-top-bar: 0 8px 30px rgba(0, 0, 0, .12), 0 2px 8px rgba(0, 0, 0, .06);--rc-shadow-modal: 0 10px 15px -3px rgba(0,0,0,.1), 0 4px 6px -4px rgba(0,0,0,.1);--rc-shadow-menu: 0 1px 4px rgba(0,0,0,.04), 0 4px 16px rgba(0,0,0,.08);--rc-space-xs: 4px;--rc-space-sm: 8px;--rc-space-md: 16px;--rc-space-lg: 24px;--rc-space-xl: 32px;--rc-font-family-sans: "PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif: "Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-mono: "SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs: .625em;--rc-font-size-xs: .75em;--rc-font-size-sm: .8125em;--rc-font-size-md: .875em;--rc-font-size-lg: 1.25em;--rc-font-size-base: 16px;--rc-font-size-small: 14px;--rc-line-height: 1.7;--rc-line-height-tight: 1.4;--rc-font-family: "PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm: 4px;--rc-radius-md: 8px;--rc-radius-lg: 12px}:root.dark{--rc-text: #fafafa;--rc-text-secondary: #a1a1aa;--rc-text-tertiary: #71717a;--rc-text-quaternary: #52525b;--rc-bg: #09090b;--rc-bg-secondary: #18181b;--rc-bg-tertiary: #27272a;--rc-fill: #2a2a2f;--rc-fill-secondary: #222226;--rc-fill-tertiary: #1b1b1f;--rc-fill-quaternary: #131316;--rc-border: #27272a;--rc-accent: #60a5fa;--rc-accent-light: #60a5fa20;--rc-link: #60a5fa;--rc-code-text: #e4e4e7;--rc-code-bg: #27272a;--rc-hr-border: #27272a;--rc-quote-border: #60a5fa;--rc-quote-bg: #1e3a5f;--rc-alert-info: #7db9e5;--rc-alert-warning: #da864a;--rc-alert-tip: #54da48;--rc-alert-caution: #e16973;--rc-alert-important: #9966e0;--rc-max-width: 700px;--rc-shadow-top-bar: 0 8px 30px rgba(0, 0, 0, .45), 0 2px 8px rgba(0, 0, 0, .3);--rc-shadow-modal: 0 10px 15px -3px rgba(0,0,0,.4), 0 4px 6px -4px rgba(0,0,0,.35);--rc-shadow-menu: 0 1px 4px rgba(0,0,0,.25), 0 4px 16px rgba(0,0,0,.4);--rc-space-xs: 4px;--rc-space-sm: 8px;--rc-space-md: 16px;--rc-space-lg: 24px;--rc-space-xl: 32px;--rc-font-family-sans: "PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif: "Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-mono: "SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs: .625em;--rc-font-size-xs: .75em;--rc-font-size-sm: .8125em;--rc-font-size-md: .875em;--rc-font-size-lg: 1.25em;--rc-font-size-base: 16px;--rc-font-size-small: 14px;--rc-line-height: 1.7;--rc-line-height-tight: 1.4;--rc-font-family: "PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm: 4px;--rc-radius-md: 8px;--rc-radius-lg: 12px}._11h7prk0{--rc-text: #000;--rc-text-secondary: #27272a;--rc-text-tertiary: #71717a;--rc-text-quaternary: #a1a1aa;--rc-bg: #ffffff;--rc-bg-secondary: #fafafa;--rc-bg-tertiary: #f4f4f5;--rc-fill: #e8e8ec;--rc-fill-secondary: #eeeeef;--rc-fill-tertiary: #f4f4f6;--rc-fill-quaternary: #f9f9fa;--rc-border: #f4f4f5;--rc-accent: #2563eb;--rc-accent-light: #2563eb20;--rc-link: #2563eb;--rc-code-text: #3f3f46;--rc-code-bg: #f4f4f5;--rc-hr-border: #e4e4e7;--rc-quote-border: #2563eb;--rc-quote-bg: #eff6ff;--rc-alert-info: #006bb7;--rc-alert-warning: #cc5500;--rc-alert-tip: #11cc00;--rc-alert-caution: #cc0011;--rc-alert-important: #5500cc;--rc-max-width: 700px;--rc-shadow-top-bar: 0 8px 30px rgba(0, 0, 0, .12), 0 2px 8px rgba(0, 0, 0, .06);--rc-shadow-modal: 0 10px 15px -3px rgba(0,0,0,.1), 0 4px 6px -4px rgba(0,0,0,.1);--rc-shadow-menu: 0 1px 4px rgba(0,0,0,.04), 0 4px 16px rgba(0,0,0,.08);--rc-space-xs: 4px;--rc-space-sm: 8px;--rc-space-md: 16px;--rc-space-lg: 24px;--rc-space-xl: 32px;--rc-font-family-sans: "PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif: "Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-mono: "SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs: .625em;--rc-font-size-xs: .75em;--rc-font-size-sm: .8125em;--rc-font-size-md: .875em;--rc-font-size-lg: 1.25em;--rc-font-size-base: 16px;--rc-font-size-small: 14px;--rc-line-height: 1.7;--rc-line-height-tight: 1.4;--rc-font-family: "PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm: 4px;--rc-radius-md: 8px;--rc-radius-lg: 12px}._11h7prk1{--rc-text: #000;--rc-text-secondary: #27272a;--rc-text-tertiary: #71717a;--rc-text-quaternary: #a1a1aa;--rc-bg: #ffffff;--rc-bg-secondary: #fafafa;--rc-bg-tertiary: #f4f4f5;--rc-fill: #e8e8ec;--rc-fill-secondary: #eeeeef;--rc-fill-tertiary: #f4f4f6;--rc-fill-quaternary: #f9f9fa;--rc-border: #f4f4f5;--rc-accent: #2563eb;--rc-accent-light: #2563eb20;--rc-link: #2563eb;--rc-code-text: #3f3f46;--rc-code-bg: #f4f4f5;--rc-hr-border: #e4e4e7;--rc-quote-border: #2563eb;--rc-quote-bg: #eff6ff;--rc-alert-info: #006bb7;--rc-alert-warning: #cc5500;--rc-alert-tip: #11cc00;--rc-alert-caution: #cc0011;--rc-alert-important: #5500cc;--rc-max-width: 700px;--rc-shadow-top-bar: 0 8px 30px rgba(0, 0, 0, .12), 0 2px 8px rgba(0, 0, 0, .06);--rc-shadow-modal: 0 10px 15px -3px rgba(0,0,0,.1), 0 4px 6px -4px rgba(0,0,0,.1);--rc-shadow-menu: 0 1px 4px rgba(0,0,0,.04), 0 4px 16px rgba(0,0,0,.08);--rc-space-xs: 4px;--rc-space-sm: 8px;--rc-space-md: 16px;--rc-space-lg: 24px;--rc-space-xl: 32px;--rc-font-family-sans: "PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif: "Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-mono: "SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs: .625em;--rc-font-size-xs: .75em;--rc-font-size-sm: .8125em;--rc-font-size-md: .875em;--rc-font-size-lg: 1.25em;--rc-font-size-base: 16px;--rc-font-size-small: 14px;--rc-line-height: 1.8;--rc-line-height-tight: 1.4;--rc-font-family: "Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-radius-sm: 4px;--rc-radius-md: 8px;--rc-radius-lg: 12px}._11h7prk2{--rc-text: #000;--rc-text-secondary: #27272a;--rc-text-tertiary: #71717a;--rc-text-quaternary: #a1a1aa;--rc-bg: #ffffff;--rc-bg-secondary: #fafafa;--rc-bg-tertiary: #f4f4f5;--rc-fill: #e8e8ec;--rc-fill-secondary: #eeeeef;--rc-fill-tertiary: #f4f4f6;--rc-fill-quaternary: #f9f9fa;--rc-border: #f4f4f5;--rc-accent: #2563eb;--rc-accent-light: #2563eb20;--rc-link: #2563eb;--rc-code-text: #3f3f46;--rc-code-bg: #f4f4f5;--rc-hr-border: #e4e4e7;--rc-quote-border: #a1a1aa;--rc-quote-bg: #fafafa;--rc-alert-info: #006bb7;--rc-alert-warning: #cc5500;--rc-alert-tip: #11cc00;--rc-alert-caution: #cc0011;--rc-alert-important: #5500cc;--rc-max-width: none;--rc-shadow-top-bar: 0 8px 30px rgba(0, 0, 0, .12), 0 2px 8px rgba(0, 0, 0, .06);--rc-shadow-modal: 0 10px 15px -3px rgba(0,0,0,.1), 0 4px 6px -4px rgba(0,0,0,.1);--rc-shadow-menu: 0 1px 4px rgba(0,0,0,.04), 0 4px 16px rgba(0,0,0,.08);--rc-space-xs: 2px;--rc-space-sm: 4px;--rc-space-md: 10px;--rc-space-lg: 16px;--rc-space-xl: 20px;--rc-font-family-sans: "PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif: "Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-mono: "SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs: .625em;--rc-font-size-xs: .75em;--rc-font-size-sm: .8125em;--rc-font-size-md: .875em;--rc-font-size-lg: 1.25em;--rc-font-size-base: 14px;--rc-font-size-small: 12px;--rc-line-height: 1.5;--rc-line-height-tight: 1.3;--rc-font-family: "PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm: 3px;--rc-radius-md: 6px;--rc-radius-lg: 12px}.dark ._11h7prk0,[data-theme=dark] ._11h7prk0,.dark._11h7prk0,[data-theme=dark]._11h7prk0,.dark ._11h7prk1,[data-theme=dark] ._11h7prk1,.dark._11h7prk1,[data-theme=dark]._11h7prk1,.dark ._11h7prk2,[data-theme=dark] ._11h7prk2,.dark._11h7prk2,[data-theme=dark]._11h7prk2{--rc-text: #fafafa;--rc-text-secondary: #a1a1aa;--rc-text-tertiary: #71717a;--rc-text-quaternary: #52525b;--rc-bg: #09090b;--rc-bg-secondary: #18181b;--rc-bg-tertiary: #27272a;--rc-fill: #2a2a2f;--rc-fill-secondary: #222226;--rc-fill-tertiary: #1b1b1f;--rc-fill-quaternary: #131316;--rc-border: #27272a;--rc-accent: #60a5fa;--rc-accent-light: #60a5fa20;--rc-link: #60a5fa;--rc-code-text: #e4e4e7;--rc-code-bg: #27272a;--rc-hr-border: #27272a;--rc-quote-border: #60a5fa;--rc-quote-bg: #1e3a5f;--rc-alert-info: #7db9e5;--rc-alert-warning: #da864a;--rc-alert-tip: #54da48;--rc-alert-caution: #e16973;--rc-alert-important: #9966e0;--rc-shadow-top-bar: 0 8px 30px rgba(0, 0, 0, .45), 0 2px 8px rgba(0, 0, 0, .3);--rc-shadow-modal: 0 10px 15px -3px rgba(0,0,0,.4), 0 4px 6px -4px rgba(0,0,0,.35);--rc-shadow-menu: 0 1px 4px rgba(0,0,0,.25), 0 4px 16px rgba(0,0,0,.4)}@keyframes _1m6axz70{0%{opacity:0;transform:translateY(4px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}._1m6axz71{display:flex;align-items:center;gap:2px;padding:4px 6px;border-radius:12px;border:1px solid var(--rc-border);background-color:color-mix(in srgb,var(--rc-bg) 95%,transparent);backdrop-filter:blur(8px);box-shadow:var(--rc-shadow-top-bar);animation:_1m6axz70 .15s ease-out}._1m6axz72{position:relative;display:flex;align-items:center;justify-content:center;width:32px;height:32px;border:none;background:none;border-radius:8px;color:var(--rc-text-secondary);cursor:pointer;padding:0;transition:color .1s,background-color .1s}._1m6axz72:hover{color:var(--rc-text);background-color:color-mix(in srgb,var(--rc-text) 4%,transparent)}._1m6axz73{color:var(--rc-text);background-color:color-mix(in srgb,var(--rc-text) 6%,transparent)}._1m6axz74{position:absolute;bottom:2px;left:50%;transform:translate(-50%);height:2px;width:14px;border-radius:1px;background-color:var(--rc-text)}._1m6axz75{display:flex;flex-direction:column;align-items:center;gap:8px;padding:12px 16px;border-radius:12px;border:1px solid var(--rc-border);background-color:color-mix(in srgb,var(--rc-bg) 95%,transparent);backdrop-filter:blur(8px);box-shadow:var(--rc-shadow-top-bar);animation:_1m6axz70 .15s ease-out;min-width:240px}._1m6axz76{display:flex;flex-direction:column;align-items:center;gap:2px;padding:4px 16px 8px}._1m6axz77{font-size:12px;color:var(--rc-text-secondary);line-height:1.2}._1m6axz78{font-size:20px;font-weight:600;line-height:1.3}._1m6axz79{display:flex;align-items:center;gap:6px;width:100%}._1m6axz7a{flex:1;padding:6px 10px;border-radius:8px;border:1.5px solid var(--rc-border);background-color:transparent;color:var(--rc-text);font-size:14px;outline:none;line-height:1.4}._1m6axz7a:focus{border-color:var(--rc-text)}._1m6axz7b{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border:none;background:none;border-radius:6px;color:var(--rc-text-secondary);cursor:pointer;padding:0;transition:color .1s,background-color .1s}._1m6axz7b:hover{background-color:color-mix(in srgb,var(--rc-text) 6%,transparent)}._1m6axz7c{font-size:11px;color:var(--rc-text-secondary);opacity:.7}._1m6axz7d{width:1px;height:20px;background-color:var(--rc-border);margin-inline:2px;flex-shrink:0}
|
|
1
|
+
:root{--rc-text:#000;--rc-text-secondary:#27272a;--rc-text-tertiary:#71717a;--rc-text-quaternary:#a1a1aa;--rc-bg:#fff;--rc-bg-secondary:#fafafa;--rc-bg-tertiary:#f4f4f5;--rc-fill:#e8e8ec;--rc-fill-secondary:#eeeeef;--rc-fill-tertiary:#f4f4f6;--rc-fill-quaternary:#f9f9fa;--rc-border:#f4f4f5;--rc-accent:#2563eb;--rc-accent-light:#2563eb20;--rc-link:#2563eb;--rc-code-text:#3f3f46;--rc-code-bg:#f4f4f5;--rc-hr-border:#e4e4e7;--rc-quote-border:#2563eb;--rc-quote-bg:#eff6ff;--rc-alert-info:#006bb7;--rc-alert-warning:#c50;--rc-alert-tip:#1c0;--rc-alert-caution:#c01;--rc-alert-important:#50c;--rc-max-width:700px;--rc-shadow-top-bar:0 8px 30px #0000001f, 0 2px 8px #0000000f;--rc-shadow-modal:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--rc-shadow-menu:0 1px 4px #0000000a, 0 4px 16px #00000014;--rc-space-xs:4px;--rc-space-sm:8px;--rc-space-md:16px;--rc-space-lg:24px;--rc-space-xl:32px;--rc-font-family-sans:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-mono:"SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs:.625em;--rc-font-size-xs:.75em;--rc-font-size-sm:.8125em;--rc-font-size-md:.875em;--rc-font-size-lg:1.25em;--rc-font-size-base:16px;--rc-font-size-small:14px;--rc-line-height:1.7;--rc-line-height-tight:1.4;--rc-font-family:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm:4px;--rc-radius-md:8px;--rc-radius-lg:12px}:root.dark{--rc-text:#fafafa;--rc-text-secondary:#a1a1aa;--rc-text-tertiary:#71717a;--rc-text-quaternary:#52525b;--rc-bg:#09090b;--rc-bg-secondary:#18181b;--rc-bg-tertiary:#27272a;--rc-fill:#2a2a2f;--rc-fill-secondary:#222226;--rc-fill-tertiary:#1b1b1f;--rc-fill-quaternary:#131316;--rc-border:#27272a;--rc-accent:#60a5fa;--rc-accent-light:#60a5fa20;--rc-link:#60a5fa;--rc-code-text:#e4e4e7;--rc-code-bg:#27272a;--rc-hr-border:#27272a;--rc-quote-border:#60a5fa;--rc-quote-bg:#1e3a5f;--rc-alert-info:#7db9e5;--rc-alert-warning:#da864a;--rc-alert-tip:#54da48;--rc-alert-caution:#e16973;--rc-alert-important:#9966e0;--rc-max-width:700px;--rc-shadow-top-bar:0 8px 30px #00000073, 0 2px 8px #0000004d;--rc-shadow-modal:0 10px 15px -3px #0006, 0 4px 6px -4px #00000059;--rc-shadow-menu:0 1px 4px #00000040, 0 4px 16px #0006;--rc-space-xs:4px;--rc-space-sm:8px;--rc-space-md:16px;--rc-space-lg:24px;--rc-space-xl:32px;--rc-font-family-sans:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-mono:"SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs:.625em;--rc-font-size-xs:.75em;--rc-font-size-sm:.8125em;--rc-font-size-md:.875em;--rc-font-size-lg:1.25em;--rc-font-size-base:16px;--rc-font-size-small:14px;--rc-line-height:1.7;--rc-line-height-tight:1.4;--rc-font-family:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm:4px;--rc-radius-md:8px;--rc-radius-lg:12px}._11h7prk0{--rc-text:#000;--rc-text-secondary:#27272a;--rc-text-tertiary:#71717a;--rc-text-quaternary:#a1a1aa;--rc-bg:#fff;--rc-bg-secondary:#fafafa;--rc-bg-tertiary:#f4f4f5;--rc-fill:#e8e8ec;--rc-fill-secondary:#eeeeef;--rc-fill-tertiary:#f4f4f6;--rc-fill-quaternary:#f9f9fa;--rc-border:#f4f4f5;--rc-accent:#2563eb;--rc-accent-light:#2563eb20;--rc-link:#2563eb;--rc-code-text:#3f3f46;--rc-code-bg:#f4f4f5;--rc-hr-border:#e4e4e7;--rc-quote-border:#2563eb;--rc-quote-bg:#eff6ff;--rc-alert-info:#006bb7;--rc-alert-warning:#c50;--rc-alert-tip:#1c0;--rc-alert-caution:#c01;--rc-alert-important:#50c;--rc-max-width:700px;--rc-shadow-top-bar:0 8px 30px #0000001f, 0 2px 8px #0000000f;--rc-shadow-modal:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--rc-shadow-menu:0 1px 4px #0000000a, 0 4px 16px #00000014;--rc-space-xs:4px;--rc-space-sm:8px;--rc-space-md:16px;--rc-space-lg:24px;--rc-space-xl:32px;--rc-font-family-sans:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-mono:"SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs:.625em;--rc-font-size-xs:.75em;--rc-font-size-sm:.8125em;--rc-font-size-md:.875em;--rc-font-size-lg:1.25em;--rc-font-size-base:16px;--rc-font-size-small:14px;--rc-line-height:1.7;--rc-line-height-tight:1.4;--rc-font-family:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm:4px;--rc-radius-md:8px;--rc-radius-lg:12px}._11h7prk1{--rc-text:#000;--rc-text-secondary:#27272a;--rc-text-tertiary:#71717a;--rc-text-quaternary:#a1a1aa;--rc-bg:#fff;--rc-bg-secondary:#fafafa;--rc-bg-tertiary:#f4f4f5;--rc-fill:#e8e8ec;--rc-fill-secondary:#eeeeef;--rc-fill-tertiary:#f4f4f6;--rc-fill-quaternary:#f9f9fa;--rc-border:#f4f4f5;--rc-accent:#2563eb;--rc-accent-light:#2563eb20;--rc-link:#2563eb;--rc-code-text:#3f3f46;--rc-code-bg:#f4f4f5;--rc-hr-border:#e4e4e7;--rc-quote-border:#2563eb;--rc-quote-bg:#eff6ff;--rc-alert-info:#006bb7;--rc-alert-warning:#c50;--rc-alert-tip:#1c0;--rc-alert-caution:#c01;--rc-alert-important:#50c;--rc-max-width:700px;--rc-shadow-top-bar:0 8px 30px #0000001f, 0 2px 8px #0000000f;--rc-shadow-modal:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--rc-shadow-menu:0 1px 4px #0000000a, 0 4px 16px #00000014;--rc-space-xs:4px;--rc-space-sm:8px;--rc-space-md:16px;--rc-space-lg:24px;--rc-space-xl:32px;--rc-font-family-sans:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-mono:"SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs:.625em;--rc-font-size-xs:.75em;--rc-font-size-sm:.8125em;--rc-font-size-md:.875em;--rc-font-size-lg:1.25em;--rc-font-size-base:16px;--rc-font-size-small:14px;--rc-line-height:1.8;--rc-line-height-tight:1.4;--rc-font-family:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-radius-sm:4px;--rc-radius-md:8px;--rc-radius-lg:12px}._11h7prk2{--rc-text:#000;--rc-text-secondary:#27272a;--rc-text-tertiary:#71717a;--rc-text-quaternary:#a1a1aa;--rc-bg:#fff;--rc-bg-secondary:#fafafa;--rc-bg-tertiary:#f4f4f5;--rc-fill:#e8e8ec;--rc-fill-secondary:#eeeeef;--rc-fill-tertiary:#f4f4f6;--rc-fill-quaternary:#f9f9fa;--rc-border:#f4f4f5;--rc-accent:#2563eb;--rc-accent-light:#2563eb20;--rc-link:#2563eb;--rc-code-text:#3f3f46;--rc-code-bg:#f4f4f5;--rc-hr-border:#e4e4e7;--rc-quote-border:#a1a1aa;--rc-quote-bg:#fafafa;--rc-alert-info:#006bb7;--rc-alert-warning:#c50;--rc-alert-tip:#1c0;--rc-alert-caution:#c01;--rc-alert-important:#50c;--rc-max-width:none;--rc-shadow-top-bar:0 8px 30px #0000001f, 0 2px 8px #0000000f;--rc-shadow-modal:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--rc-shadow-menu:0 1px 4px #0000000a, 0 4px 16px #00000014;--rc-space-xs:2px;--rc-space-sm:4px;--rc-space-md:10px;--rc-space-lg:16px;--rc-space-xl:20px;--rc-font-family-sans:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-mono:"SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs:.625em;--rc-font-size-xs:.75em;--rc-font-size-sm:.8125em;--rc-font-size-md:.875em;--rc-font-size-lg:1.25em;--rc-font-size-base:14px;--rc-font-size-small:12px;--rc-line-height:1.5;--rc-line-height-tight:1.3;--rc-font-family:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm:3px;--rc-radius-md:6px;--rc-radius-lg:12px}.dark ._11h7prk0,[data-theme=dark] ._11h7prk0,.dark._11h7prk0,[data-theme=dark]._11h7prk0,.dark ._11h7prk1,[data-theme=dark] ._11h7prk1,.dark._11h7prk1,[data-theme=dark]._11h7prk1,.dark ._11h7prk2,[data-theme=dark] ._11h7prk2,.dark._11h7prk2,[data-theme=dark]._11h7prk2{--rc-text:#fafafa;--rc-text-secondary:#a1a1aa;--rc-text-tertiary:#71717a;--rc-text-quaternary:#52525b;--rc-bg:#09090b;--rc-bg-secondary:#18181b;--rc-bg-tertiary:#27272a;--rc-fill:#2a2a2f;--rc-fill-secondary:#222226;--rc-fill-tertiary:#1b1b1f;--rc-fill-quaternary:#131316;--rc-border:#27272a;--rc-accent:#60a5fa;--rc-accent-light:#60a5fa20;--rc-link:#60a5fa;--rc-code-text:#e4e4e7;--rc-code-bg:#27272a;--rc-hr-border:#27272a;--rc-quote-border:#60a5fa;--rc-quote-bg:#1e3a5f;--rc-alert-info:#7db9e5;--rc-alert-warning:#da864a;--rc-alert-tip:#54da48;--rc-alert-caution:#e16973;--rc-alert-important:#9966e0;--rc-shadow-top-bar:0 8px 30px #00000073, 0 2px 8px #0000004d;--rc-shadow-modal:0 10px 15px -3px #0006, 0 4px 6px -4px #00000059;--rc-shadow-menu:0 1px 4px #00000040, 0 4px 16px #0006}@keyframes _1m6axz70{0%{opacity:0;transform:translateY(4px)scale(.96)}to{opacity:1;transform:translateY(0)scale(1)}}._1m6axz71{border:1px solid var(--rc-border);background-color:color-mix(in srgb, var(--rc-bg) 95%, transparent);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);box-shadow:var(--rc-shadow-top-bar);border-radius:12px;align-items:center;gap:2px;padding:4px 6px;animation:.15s ease-out _1m6axz70;display:flex}._1m6axz72{width:32px;height:32px;color:var(--rc-text-secondary);cursor:pointer;background:0 0;border:none;border-radius:8px;justify-content:center;align-items:center;padding:0;transition:color .1s,background-color .1s;display:flex;position:relative}._1m6axz72:hover{color:var(--rc-text);background-color:color-mix(in srgb, var(--rc-text) 4%, transparent)}._1m6axz73{color:var(--rc-text);background-color:color-mix(in srgb, var(--rc-text) 6%, transparent)}._1m6axz74{background-color:var(--rc-text);border-radius:1px;width:14px;height:2px;position:absolute;bottom:2px;left:50%;transform:translate(-50%)}._1m6axz75{border:1px solid var(--rc-border);background-color:color-mix(in srgb, var(--rc-bg) 95%, transparent);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);box-shadow:var(--rc-shadow-top-bar);border-radius:12px;flex-direction:column;align-items:center;gap:8px;min-width:240px;padding:12px 16px;animation:.15s ease-out _1m6axz70;display:flex}._1m6axz76{flex-direction:column;align-items:center;gap:2px;padding:4px 16px 8px;display:flex}._1m6axz77{color:var(--rc-text-secondary);font-size:12px;line-height:1.2}._1m6axz78{font-size:20px;font-weight:600;line-height:1.3}._1m6axz79{align-items:center;gap:6px;width:100%;display:flex}._1m6axz7a{border:1.5px solid var(--rc-border);color:var(--rc-text);background-color:#0000;border-radius:8px;outline:none;flex:1;padding:6px 10px;font-size:14px;line-height:1.4}._1m6axz7a:focus{border-color:var(--rc-text)}._1m6axz7b{width:28px;height:28px;color:var(--rc-text-secondary);cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;padding:0;transition:color .1s,background-color .1s;display:flex}._1m6axz7b:hover{background-color:color-mix(in srgb, var(--rc-text) 6%, transparent)}._1m6axz7c{color:var(--rc-text-secondary);opacity:.7;font-size:11px}._1m6axz7d{background-color:var(--rc-border);flex-shrink:0;width:1px;height:20px;margin-inline-start:2px;margin-inline-end:2px}
|
|
2
|
+
/*$vite$:1*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@haklex/rich-plugin-floating-toolbar",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.81",
|
|
4
4
|
"description": "Floating toolbar plugin",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
"dist"
|
|
22
22
|
],
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@haklex/rich-editor
|
|
25
|
-
"@haklex/rich-
|
|
26
|
-
"@haklex/rich-
|
|
24
|
+
"@haklex/rich-editor": "0.0.81",
|
|
25
|
+
"@haklex/rich-style-token": "0.0.81",
|
|
26
|
+
"@haklex/rich-editor-ui": "0.0.81"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@lexical/link": "^0.41.0",
|