@haklex/rich-plugin-toolbar 0.15.9 → 0.16.0
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/ToolbarPlugin.d.ts.map +1 -1
- package/dist/actions.d.ts +18 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/constants.d.ts +12 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +144 -93
- package/dist/use-toolbar-state.d.ts +24 -0
- package/dist/use-toolbar-state.d.ts.map +1 -0
- package/package.json +6 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolbarPlugin.d.ts","sourceRoot":"","sources":["../src/ToolbarPlugin.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ToolbarPlugin.d.ts","sourceRoot":"","sources":["../src/ToolbarPlugin.tsx"],"names":[],"mappings":"AAwDA,OAAO,KAAK,EAAiB,YAAY,EAAE,MAAM,OAAO,CAAC;AAuBzD,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,wBAAgB,aAAa,CAAC,EAC5B,SAAS,EACT,qBAAwD,EACxD,eAAe,GAChB,EAAE,kBAAkB,GAAG,YAAY,CAkUnC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ElementNode, LexicalEditor } from 'lexical';
|
|
2
|
+
import { BlockType } from './constants';
|
|
3
|
+
/**
|
|
4
|
+
* Derive the canonical block type from an element node.
|
|
5
|
+
* Exposed so downstream toolbars can recompute block type for any selection target.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getBlockType(anchorNode: ElementNode): BlockType;
|
|
8
|
+
/**
|
|
9
|
+
* Apply a block type (paragraph / heading / list) to the current selection.
|
|
10
|
+
* For list types this delegates to the corresponding INSERT_*_LIST_COMMAND.
|
|
11
|
+
*/
|
|
12
|
+
export declare function applyBlockType(editor: LexicalEditor, type: BlockType): void;
|
|
13
|
+
/**
|
|
14
|
+
* Patch the `font-family` style on the current selection.
|
|
15
|
+
* Passing an empty string clears the override and inherits the editor default.
|
|
16
|
+
*/
|
|
17
|
+
export declare function applyFontFamily(editor: LexicalEditor, value: string): void;
|
|
18
|
+
//# sourceMappingURL=actions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAO1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C;;;GAGG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,WAAW,GAAG,SAAS,CAgB/D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI,CA0B3E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAO1E"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
export interface FontFamilyDef {
|
|
3
|
+
label: string;
|
|
4
|
+
value: string;
|
|
5
|
+
/** Suggested style for the dropdown menu entry. */
|
|
6
|
+
style?: CSSProperties;
|
|
7
|
+
}
|
|
8
|
+
export declare const FONT_FAMILIES: FontFamilyDef[];
|
|
9
|
+
export declare function getFontLabel(fontFamily: string): string;
|
|
10
|
+
export type BlockType = 'paragraph' | 'h1' | 'h2' | 'h3' | 'bullet' | 'number' | 'check' | 'other';
|
|
11
|
+
export declare const BLOCK_TYPE_LABELS: Record<BlockType, string>;
|
|
12
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAED,eAAO,MAAM,aAAa,EAAE,aAAa,EAcxC,CAAC;AAEF,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAUvD;AAED,MAAM,MAAM,SAAS,GACjB,WAAW,GACX,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,OAAO,CAAC;AAEZ,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CASvD,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
export { applyBlockType, applyFontFamily, getBlockType } from './actions';
|
|
2
|
+
export { BLOCK_TYPE_LABELS, FONT_FAMILIES, getFontLabel, } from './constants';
|
|
3
|
+
export type { BlockType, FontFamilyDef } from './constants';
|
|
4
|
+
export { ToolbarButton } from './ToolbarButton';
|
|
5
|
+
export { ToolbarDropdown } from './ToolbarDropdown';
|
|
6
|
+
export { ToolbarSeparator } from './ToolbarSeparator';
|
|
1
7
|
export type { ToolbarPluginProps } from './ToolbarPlugin';
|
|
2
8
|
export { ToolbarPlugin } from './ToolbarPlugin';
|
|
9
|
+
export { INITIAL_TOOLBAR_STATE, useToolbarState } from './use-toolbar-state';
|
|
10
|
+
export type { ToolbarState } from './use-toolbar-state';
|
|
3
11
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC1E,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,YAAY,GACb,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC7E,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,14 +1,122 @@
|
|
|
1
|
-
import { $selectionTouchesSpoiler, $toggleSpoilerSelection, collectCommandItems } from "@haklex/rich-editor/commands";
|
|
2
|
-
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, TooltipContent, TooltipProvider, TooltipRoot, TooltipTrigger, createTooltipHandle } from "@haklex/rich-editor-ui";
|
|
3
1
|
import { $isListNode, INSERT_CHECK_LIST_COMMAND, INSERT_ORDERED_LIST_COMMAND, INSERT_UNORDERED_LIST_COMMAND } from "@lexical/list";
|
|
4
|
-
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
|
|
5
2
|
import { $createHeadingNode, $isHeadingNode } from "@lexical/rich-text";
|
|
6
3
|
import { $getSelectionStyleValueForProperty, $patchStyleText, $setBlocksType } from "@lexical/selection";
|
|
7
|
-
import { $findMatchingParent } from "@lexical/utils";
|
|
8
4
|
import { $createParagraphNode, $getSelection, $isElementNode, $isRangeSelection, $isRootOrShadowRoot, CAN_REDO_COMMAND, CAN_UNDO_COMMAND, COMMAND_PRIORITY_LOW, FORMAT_ELEMENT_COMMAND, FORMAT_TEXT_COMMAND, REDO_COMMAND, UNDO_COMMAND } from "lexical";
|
|
5
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, TooltipContent, TooltipProvider, TooltipRoot, TooltipTrigger, createTooltipHandle } from "@haklex/rich-editor-ui";
|
|
6
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
9
7
|
import { AlignCenter, AlignJustify, AlignLeft, AlignRight, Bold, ChevronDown, Code, Ellipsis, EyeOff, Heading1, Heading2, Heading3, Highlighter, Italic, List, ListChecks, ListOrdered, Pilcrow, Redo, Strikethrough, Underline, Undo } from "lucide-react";
|
|
8
|
+
import { $selectionTouchesSpoiler, $toggleSpoilerSelection, collectCommandItems } from "@haklex/rich-editor/commands";
|
|
9
|
+
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
|
|
10
10
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
11
|
-
import {
|
|
11
|
+
import { $findMatchingParent } from "@lexical/utils";
|
|
12
|
+
//#region src/actions.ts
|
|
13
|
+
/**
|
|
14
|
+
* Derive the canonical block type from an element node.
|
|
15
|
+
* Exposed so downstream toolbars can recompute block type for any selection target.
|
|
16
|
+
*/
|
|
17
|
+
function getBlockType(anchorNode) {
|
|
18
|
+
if ($isHeadingNode(anchorNode)) {
|
|
19
|
+
const tag = anchorNode.getTag();
|
|
20
|
+
if (tag === "h1" || tag === "h2" || tag === "h3") return tag;
|
|
21
|
+
return "other";
|
|
22
|
+
}
|
|
23
|
+
if ($isListNode(anchorNode)) {
|
|
24
|
+
const listType = anchorNode.getListType();
|
|
25
|
+
if (listType === "bullet") return "bullet";
|
|
26
|
+
if (listType === "number") return "number";
|
|
27
|
+
if (listType === "check") return "check";
|
|
28
|
+
return "other";
|
|
29
|
+
}
|
|
30
|
+
if (anchorNode.getType() === "paragraph") return "paragraph";
|
|
31
|
+
return "other";
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Apply a block type (paragraph / heading / list) to the current selection.
|
|
35
|
+
* For list types this delegates to the corresponding INSERT_*_LIST_COMMAND.
|
|
36
|
+
*/
|
|
37
|
+
function applyBlockType(editor, type) {
|
|
38
|
+
if (type === "bullet") {
|
|
39
|
+
editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, void 0);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (type === "number") {
|
|
43
|
+
editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, void 0);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (type === "check") {
|
|
47
|
+
editor.dispatchCommand(INSERT_CHECK_LIST_COMMAND, void 0);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
editor.update(() => {
|
|
51
|
+
const selection = $getSelection();
|
|
52
|
+
if (!$isRangeSelection(selection)) return;
|
|
53
|
+
if (type === "paragraph" || type === "other") {
|
|
54
|
+
$setBlocksType(selection, () => $createParagraphNode());
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (type === "h1" || type === "h2" || type === "h3") $setBlocksType(selection, () => $createHeadingNode(type));
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Patch the `font-family` style on the current selection.
|
|
62
|
+
* Passing an empty string clears the override and inherits the editor default.
|
|
63
|
+
*/
|
|
64
|
+
function applyFontFamily(editor, value) {
|
|
65
|
+
editor.update(() => {
|
|
66
|
+
const selection = $getSelection();
|
|
67
|
+
if ($isRangeSelection(selection)) $patchStyleText(selection, { "font-family": value || "" });
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
//#region src/constants.ts
|
|
72
|
+
var FONT_FAMILIES = [
|
|
73
|
+
{
|
|
74
|
+
label: "默认",
|
|
75
|
+
value: ""
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
label: "宋体",
|
|
79
|
+
value: "\"Noto Serif CJK SC\", \"Source Han Serif SC\", SimSun, serif"
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
label: "黑体",
|
|
83
|
+
value: "\"Noto Sans CJK SC\", \"Source Han Sans SC\", SimHei, sans-serif"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
label: "楷体",
|
|
87
|
+
value: "KaiTi, STKaiti, serif"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
label: "Sans",
|
|
91
|
+
value: "system-ui, -apple-system, sans-serif"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
label: "Serif",
|
|
95
|
+
value: "Georgia, \"Times New Roman\", serif"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
label: "Mono",
|
|
99
|
+
value: "ui-monospace, \"SF Mono\", \"Fira Code\", monospace"
|
|
100
|
+
}
|
|
101
|
+
];
|
|
102
|
+
function getFontLabel(fontFamily) {
|
|
103
|
+
if (!fontFamily) return "默认";
|
|
104
|
+
const match = FONT_FAMILIES.find((f) => f.value === fontFamily);
|
|
105
|
+
if (match) return match.label;
|
|
106
|
+
for (const def of FONT_FAMILIES) if (def.value && fontFamily.startsWith(def.value.split(",")[0])) return def.label;
|
|
107
|
+
return "默认";
|
|
108
|
+
}
|
|
109
|
+
var BLOCK_TYPE_LABELS = {
|
|
110
|
+
paragraph: "Text",
|
|
111
|
+
h1: "Heading 1",
|
|
112
|
+
h2: "Heading 2",
|
|
113
|
+
h3: "Heading 3",
|
|
114
|
+
bullet: "Bulleted List",
|
|
115
|
+
number: "Numbered List",
|
|
116
|
+
check: "To-do List",
|
|
117
|
+
other: "Other"
|
|
118
|
+
};
|
|
119
|
+
//#endregion
|
|
12
120
|
//#region src/styles.css.ts
|
|
13
121
|
var toolbarContainer = "_1e1ersc0";
|
|
14
122
|
var toolbarRow = "_1e1ersc1";
|
|
@@ -103,57 +211,8 @@ function ToolbarSeparator() {
|
|
|
103
211
|
return /* @__PURE__ */ jsx("div", { className: toolbarSeparator });
|
|
104
212
|
}
|
|
105
213
|
//#endregion
|
|
106
|
-
//#region src/
|
|
107
|
-
var
|
|
108
|
-
var ICON_STROKE = 2;
|
|
109
|
-
var FONT_FAMILIES = [
|
|
110
|
-
{
|
|
111
|
-
label: "默认",
|
|
112
|
-
value: ""
|
|
113
|
-
},
|
|
114
|
-
{
|
|
115
|
-
label: "宋体",
|
|
116
|
-
value: "\"Noto Serif CJK SC\", \"Source Han Serif SC\", SimSun, serif"
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
label: "黑体",
|
|
120
|
-
value: "\"Noto Sans CJK SC\", \"Source Han Sans SC\", SimHei, sans-serif"
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
label: "楷体",
|
|
124
|
-
value: "KaiTi, STKaiti, serif"
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
label: "Sans",
|
|
128
|
-
value: "system-ui, -apple-system, sans-serif"
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
label: "Serif",
|
|
132
|
-
value: "Georgia, \"Times New Roman\", serif"
|
|
133
|
-
},
|
|
134
|
-
{
|
|
135
|
-
label: "Mono",
|
|
136
|
-
value: "ui-monospace, \"SF Mono\", \"Fira Code\", monospace"
|
|
137
|
-
}
|
|
138
|
-
];
|
|
139
|
-
function getFontLabel(fontFamily) {
|
|
140
|
-
if (!fontFamily) return "默认";
|
|
141
|
-
const match = FONT_FAMILIES.find((f) => f.value === fontFamily);
|
|
142
|
-
if (match) return match.label;
|
|
143
|
-
for (const def of FONT_FAMILIES) if (def.value && fontFamily.startsWith(def.value.split(",")[0])) return def.label;
|
|
144
|
-
return "默认";
|
|
145
|
-
}
|
|
146
|
-
var BLOCK_TYPE_LABELS = {
|
|
147
|
-
paragraph: "Text",
|
|
148
|
-
h1: "Heading 1",
|
|
149
|
-
h2: "Heading 2",
|
|
150
|
-
h3: "Heading 3",
|
|
151
|
-
bullet: "Bulleted List",
|
|
152
|
-
number: "Numbered List",
|
|
153
|
-
check: "To-do List",
|
|
154
|
-
other: "Other"
|
|
155
|
-
};
|
|
156
|
-
var INITIAL_STATE = {
|
|
214
|
+
//#region src/use-toolbar-state.ts
|
|
215
|
+
var INITIAL_TOOLBAR_STATE = {
|
|
157
216
|
canUndo: false,
|
|
158
217
|
canRedo: false,
|
|
159
218
|
blockType: "paragraph",
|
|
@@ -167,36 +226,14 @@ var INITIAL_STATE = {
|
|
|
167
226
|
isHighlight: false,
|
|
168
227
|
isSpoiler: false
|
|
169
228
|
};
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
if ($isListNode(anchorNode)) {
|
|
177
|
-
const listType = anchorNode.getListType();
|
|
178
|
-
if (listType === "bullet") return "bullet";
|
|
179
|
-
if (listType === "number") return "number";
|
|
180
|
-
if (listType === "check") return "check";
|
|
181
|
-
return "other";
|
|
182
|
-
}
|
|
183
|
-
if (anchorNode.getType() === "paragraph") return "paragraph";
|
|
184
|
-
return "other";
|
|
185
|
-
}
|
|
186
|
-
var DEFAULT_MAX_VISIBLE_INSERT_ITEMS = 5;
|
|
187
|
-
function ToolbarPlugin({ className, maxVisibleInsertItems = DEFAULT_MAX_VISIBLE_INSERT_ITEMS, insertItemOrder }) {
|
|
229
|
+
/**
|
|
230
|
+
* Subscribe to selection/format/history changes and return a reactive ToolbarState.
|
|
231
|
+
* Use inside a component mounted under a LexicalComposer (e.g. via `header={...}`
|
|
232
|
+
* slot of the editor) so the lexical context is available.
|
|
233
|
+
*/
|
|
234
|
+
function useToolbarState() {
|
|
188
235
|
const [editor] = useLexicalComposerContext();
|
|
189
|
-
const [state, setState] = useState(
|
|
190
|
-
const [tooltipHandle] = useState(() => createTooltipHandle());
|
|
191
|
-
const toolbarItems = useMemo(() => {
|
|
192
|
-
const items = collectCommandItems(editor).filter((item) => item.placement?.includes("toolbar") && item.group === "insert");
|
|
193
|
-
if (!insertItemOrder || insertItemOrder.length === 0) return items;
|
|
194
|
-
return items.sort((a, b) => {
|
|
195
|
-
const ai = insertItemOrder.indexOf(a.title);
|
|
196
|
-
const bi = insertItemOrder.indexOf(b.title);
|
|
197
|
-
return (ai === -1 ? Infinity : ai) - (bi === -1 ? Infinity : bi);
|
|
198
|
-
});
|
|
199
|
-
}, [editor, insertItemOrder]);
|
|
236
|
+
const [state, setState] = useState(INITIAL_TOOLBAR_STATE);
|
|
200
237
|
const updateToolbar = useCallback(() => {
|
|
201
238
|
const selection = $getSelection();
|
|
202
239
|
if (!$isRangeSelection(selection)) return;
|
|
@@ -259,18 +296,32 @@ function ToolbarPlugin({ className, maxVisibleInsertItems = DEFAULT_MAX_VISIBLE_
|
|
|
259
296
|
unregisterUpdate();
|
|
260
297
|
};
|
|
261
298
|
}, [editor, updateToolbar]);
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
299
|
+
return state;
|
|
300
|
+
}
|
|
301
|
+
//#endregion
|
|
302
|
+
//#region src/ToolbarPlugin.tsx
|
|
303
|
+
var ICON_SIZE = 15;
|
|
304
|
+
var ICON_STROKE = 2;
|
|
305
|
+
var DEFAULT_MAX_VISIBLE_INSERT_ITEMS = 5;
|
|
306
|
+
function ToolbarPlugin({ className, maxVisibleInsertItems = DEFAULT_MAX_VISIBLE_INSERT_ITEMS, insertItemOrder }) {
|
|
307
|
+
const [editor] = useLexicalComposerContext();
|
|
308
|
+
const state = useToolbarState();
|
|
309
|
+
const [tooltipHandle] = useState(() => createTooltipHandle());
|
|
310
|
+
const toolbarItems = useMemo(() => {
|
|
311
|
+
const items = collectCommandItems(editor).filter((item) => item.placement?.includes("toolbar") && item.group === "insert");
|
|
312
|
+
if (!insertItemOrder || insertItemOrder.length === 0) return items;
|
|
313
|
+
return items.sort((a, b) => {
|
|
314
|
+
const ai = insertItemOrder.indexOf(a.title);
|
|
315
|
+
const bi = insertItemOrder.indexOf(b.title);
|
|
316
|
+
return (ai === -1 ? Infinity : ai) - (bi === -1 ? Infinity : bi);
|
|
266
317
|
});
|
|
267
|
-
}, [editor]);
|
|
318
|
+
}, [editor, insertItemOrder]);
|
|
268
319
|
const fontFamilyItems = useMemo(() => FONT_FAMILIES.map((def) => ({
|
|
269
320
|
label: def.label,
|
|
270
321
|
active: state.fontFamily === def.value,
|
|
271
322
|
style: def.value ? { fontFamily: def.value } : void 0,
|
|
272
|
-
onSelect: () => applyFontFamily(def.value)
|
|
273
|
-
})), [state.fontFamily
|
|
323
|
+
onSelect: () => applyFontFamily(editor, def.value)
|
|
324
|
+
})), [editor, state.fontFamily]);
|
|
274
325
|
const headingItems = useMemo(() => [
|
|
275
326
|
{
|
|
276
327
|
label: "Text",
|
|
@@ -582,4 +633,4 @@ function ToolbarPlugin({ className, maxVisibleInsertItems = DEFAULT_MAX_VISIBLE_
|
|
|
582
633
|
});
|
|
583
634
|
}
|
|
584
635
|
//#endregion
|
|
585
|
-
export { ToolbarPlugin };
|
|
636
|
+
export { BLOCK_TYPE_LABELS, FONT_FAMILIES, INITIAL_TOOLBAR_STATE, ToolbarButton, ToolbarDropdown, ToolbarPlugin, ToolbarSeparator, applyBlockType, applyFontFamily, getBlockType, getFontLabel, useToolbarState };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ElementFormatType } from 'lexical';
|
|
2
|
+
import { BlockType } from './constants';
|
|
3
|
+
export interface ToolbarState {
|
|
4
|
+
blockType: BlockType;
|
|
5
|
+
canRedo: boolean;
|
|
6
|
+
canUndo: boolean;
|
|
7
|
+
elementFormat: ElementFormatType;
|
|
8
|
+
fontFamily: string;
|
|
9
|
+
isBold: boolean;
|
|
10
|
+
isCode: boolean;
|
|
11
|
+
isHighlight: boolean;
|
|
12
|
+
isItalic: boolean;
|
|
13
|
+
isSpoiler: boolean;
|
|
14
|
+
isStrikethrough: boolean;
|
|
15
|
+
isUnderline: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare const INITIAL_TOOLBAR_STATE: ToolbarState;
|
|
18
|
+
/**
|
|
19
|
+
* Subscribe to selection/format/history changes and return a reactive ToolbarState.
|
|
20
|
+
* Use inside a component mounted under a LexicalComposer (e.g. via `header={...}`
|
|
21
|
+
* slot of the editor) so the lexical context is available.
|
|
22
|
+
*/
|
|
23
|
+
export declare function useToolbarState(): ToolbarState;
|
|
24
|
+
//# sourceMappingURL=use-toolbar-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-toolbar-state.d.ts","sourceRoot":"","sources":["../src/use-toolbar-state.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAe,MAAM,SAAS,CAAC;AAa9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,iBAAiB,CAAC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,eAAe,EAAE,OAAO,CAAC;IACzB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,qBAAqB,EAAE,YAanC,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAyF9C"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@haklex/rich-plugin-toolbar",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Top toolbar plugin for rich editor",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"@vanilla-extract/vite-plugin": "^5.2.2",
|
|
33
33
|
"lexical": "^0.44.0",
|
|
34
34
|
"lucide-react": "^1.16.0",
|
|
35
|
-
"react": "19.2.
|
|
36
|
-
"react-dom": "19.2.
|
|
35
|
+
"react": "19.2.5",
|
|
36
|
+
"react-dom": "19.2.5",
|
|
37
37
|
"typescript": "^5.9.3",
|
|
38
38
|
"unplugin-dts": "^1.0.1",
|
|
39
39
|
"vite": "^8.0.13"
|
|
@@ -48,9 +48,9 @@
|
|
|
48
48
|
"lucide-react": "^1.0.0",
|
|
49
49
|
"react": ">=19",
|
|
50
50
|
"react-dom": ">=19",
|
|
51
|
-
"@haklex/rich-
|
|
52
|
-
"@haklex/rich-editor": "0.15.
|
|
53
|
-
"@haklex/rich-
|
|
51
|
+
"@haklex/rich-editor": "0.15.4",
|
|
52
|
+
"@haklex/rich-editor-ui": "0.15.4",
|
|
53
|
+
"@haklex/rich-style-token": "0.15.4"
|
|
54
54
|
},
|
|
55
55
|
"publishConfig": {
|
|
56
56
|
"access": "public"
|