@kerebron/extension-menu 0.2.0 → 0.3.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.
Files changed (68) hide show
  1. package/esm/editor/src/CoreEditor.d.ts +31 -0
  2. package/esm/editor/src/CoreEditor.d.ts.map +1 -0
  3. package/esm/editor/src/CoreEditor.js +198 -0
  4. package/esm/editor/src/DummyEditorView.d.ts +60 -0
  5. package/esm/editor/src/DummyEditorView.d.ts.map +1 -0
  6. package/esm/editor/src/DummyEditorView.js +277 -0
  7. package/esm/editor/src/Extension.d.ts +26 -0
  8. package/esm/editor/src/Extension.d.ts.map +1 -0
  9. package/esm/editor/src/Extension.js +33 -0
  10. package/esm/editor/src/ExtensionManager.d.ts +33 -0
  11. package/esm/editor/src/ExtensionManager.d.ts.map +1 -0
  12. package/esm/editor/src/ExtensionManager.js +272 -0
  13. package/esm/editor/src/Mark.d.ts +20 -0
  14. package/esm/editor/src/Mark.d.ts.map +1 -0
  15. package/esm/editor/src/Mark.js +40 -0
  16. package/esm/editor/src/Node.d.ts +29 -0
  17. package/esm/editor/src/Node.d.ts.map +1 -0
  18. package/esm/editor/src/Node.js +49 -0
  19. package/esm/editor/src/commands/CommandManager.d.ts +16 -0
  20. package/esm/editor/src/commands/CommandManager.d.ts.map +1 -0
  21. package/esm/editor/src/commands/CommandManager.js +61 -0
  22. package/esm/editor/src/commands/createChainableState.d.ts +3 -0
  23. package/esm/editor/src/commands/createChainableState.d.ts.map +1 -0
  24. package/esm/editor/src/commands/createChainableState.js +29 -0
  25. package/esm/editor/src/commands/mod.d.ts +55 -0
  26. package/esm/editor/src/commands/mod.d.ts.map +1 -0
  27. package/esm/editor/src/commands/mod.js +883 -0
  28. package/esm/editor/src/mod.d.ts +7 -0
  29. package/esm/editor/src/mod.d.ts.map +1 -0
  30. package/esm/editor/src/mod.js +6 -0
  31. package/esm/editor/src/nodeToTreeString.d.ts +4 -0
  32. package/esm/editor/src/nodeToTreeString.d.ts.map +1 -0
  33. package/esm/editor/src/nodeToTreeString.js +58 -0
  34. package/esm/editor/src/plugins/input-rules/InputRulesPlugin.d.ts +23 -0
  35. package/esm/editor/src/plugins/input-rules/InputRulesPlugin.d.ts.map +1 -0
  36. package/esm/editor/src/plugins/input-rules/InputRulesPlugin.js +163 -0
  37. package/esm/editor/src/plugins/keymap/keymap.d.ts +11 -0
  38. package/esm/editor/src/plugins/keymap/keymap.d.ts.map +1 -0
  39. package/esm/editor/src/plugins/keymap/keymap.js +125 -0
  40. package/esm/editor/src/plugins/keymap/w3c-keyname.d.ts +4 -0
  41. package/esm/editor/src/plugins/keymap/w3c-keyname.d.ts.map +1 -0
  42. package/esm/editor/src/plugins/keymap/w3c-keyname.js +124 -0
  43. package/esm/editor/src/types.d.ts +34 -0
  44. package/esm/editor/src/types.d.ts.map +1 -0
  45. package/esm/editor/src/types.js +1 -0
  46. package/esm/editor/src/utilities/createNodeFromContent.d.ts +9 -0
  47. package/esm/editor/src/utilities/createNodeFromContent.d.ts.map +1 -0
  48. package/esm/editor/src/utilities/createNodeFromContent.js +32 -0
  49. package/esm/editor/src/utilities/getHtmlAttributes.d.ts +9 -0
  50. package/esm/editor/src/utilities/getHtmlAttributes.d.ts.map +1 -0
  51. package/esm/editor/src/utilities/getHtmlAttributes.js +47 -0
  52. package/esm/extension-menu/src/ExtensionMenu.d.ts +17 -0
  53. package/esm/extension-menu/src/ExtensionMenu.d.ts.map +1 -0
  54. package/esm/extension-menu/src/ExtensionMenu.js +318 -0
  55. package/esm/extension-menu/src/MenuPlugin.d.ts +9 -0
  56. package/esm/extension-menu/src/MenuPlugin.d.ts.map +1 -0
  57. package/esm/extension-menu/src/MenuPlugin.js +245 -0
  58. package/esm/extension-menu/src/icons.d.ts +15 -0
  59. package/esm/extension-menu/src/icons.d.ts.map +1 -0
  60. package/esm/extension-menu/src/icons.js +118 -0
  61. package/esm/extension-menu/src/menu.d.ts +88 -0
  62. package/esm/extension-menu/src/menu.d.ts.map +1 -0
  63. package/esm/extension-menu/src/menu.js +392 -0
  64. package/esm/extension-menu/src/prompt.d.ts +36 -0
  65. package/esm/extension-menu/src/prompt.d.ts.map +1 -0
  66. package/esm/extension-menu/src/prompt.js +158 -0
  67. package/esm/package.json +3 -0
  68. package/package.json +2 -6
@@ -0,0 +1,47 @@
1
+ export function getHtmlAttributes(extension, node) {
2
+ const attrs = {};
3
+ if (extension.attributes) {
4
+ for (const [key, value] of Object.entries(extension.attributes)) {
5
+ if ('undefined' !== typeof node.attrs[key]) {
6
+ attrs[key] = node.attrs[key];
7
+ }
8
+ else {
9
+ if (value.toDom) {
10
+ attrs[key] = value.toDom(node);
11
+ }
12
+ else {
13
+ attrs[key] = value.default;
14
+ }
15
+ }
16
+ }
17
+ }
18
+ return attrs;
19
+ }
20
+ export function setHtmlAttributes(extension, element) {
21
+ const attrs = {};
22
+ if (extension.attributes) {
23
+ for (const [key, value] of Object.entries(extension.attributes)) {
24
+ if (value.fromDom) {
25
+ attrs[key] = value.fromDom(element);
26
+ }
27
+ else {
28
+ attrs[key] = value.default;
29
+ }
30
+ }
31
+ }
32
+ return attrs;
33
+ }
34
+ export function addAttributesToSchema(spec, extension) {
35
+ const attrs = {};
36
+ if (extension.attributes) {
37
+ if (!spec.attrs) {
38
+ spec.attrs = {};
39
+ }
40
+ for (const [key, value] of Object.entries(extension.attributes)) {
41
+ spec.attrs[key] = value;
42
+ if (!value.toDom) {
43
+ value.toDom = (node) => node.attrs[key];
44
+ }
45
+ }
46
+ }
47
+ }
@@ -0,0 +1,17 @@
1
+ import { Plugin } from 'prosemirror-state';
2
+ import { Schema } from 'prosemirror-model';
3
+ import { type CoreEditor, Extension } from '../../editor/src/mod.js';
4
+ import { MenuElement } from './menu.js';
5
+ export { blockTypeItem, Dropdown, DropdownSubmenu, MenuItem, wrapItem, } from './menu.js';
6
+ export declare function buildMenu(editor: CoreEditor, schema: Schema): MenuElement[][];
7
+ export interface MenuConfig {
8
+ modifyMenu?(menus: MenuElement[][]): MenuElement[][];
9
+ floating: boolean;
10
+ }
11
+ export declare class ExtensionMenu extends Extension {
12
+ protected config: MenuConfig;
13
+ name: string;
14
+ constructor(config?: MenuConfig);
15
+ getProseMirrorPlugins(editor: CoreEditor, schema: Schema): Plugin[];
16
+ }
17
+ //# sourceMappingURL=ExtensionMenu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExtensionMenu.d.ts","sourceRoot":"","sources":["../../../src/extension-menu/src/ExtensionMenu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuC,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAAsB,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE/D,OAAO,EAAE,KAAK,UAAU,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGrE,OAAO,EAIL,WAAW,EAIZ,MAAM,WAAW,CAAC;AAKnB,OAAO,EACL,aAAa,EACb,QAAQ,EACR,eAAe,EAEf,QAAQ,EAER,QAAQ,GACT,MAAM,WAAW,CAAC;AAkDnB,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,EAAE,EAAE,CA2R7E;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,CAAC,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,GAAG,WAAW,EAAE,EAAE,CAAC;IACrD,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,qBAAa,aAAc,SAAQ,SAAS;IAG9B,SAAS,CAAC,MAAM,EAAE,UAAU;IAFxC,IAAI,SAAU;gBAEQ,MAAM,GAAE,UAA+B;IAIpD,qBAAqB,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;CAgB7E"}
@@ -0,0 +1,318 @@
1
+ import { NodeSelection } from 'prosemirror-state';
2
+ import { Extension } from '../../editor/src/mod.js';
3
+ import { toggleMark, wrapInList } from '../../editor/src/commands/mod.js';
4
+ import { blockTypeItem, Dropdown, DropdownSubmenu, MenuItem, wrapItem, } from './menu.js';
5
+ import { MenuPlugin } from './MenuPlugin.js';
6
+ import { icons } from './icons.js';
7
+ import { openPrompt, TextField } from './prompt.js';
8
+ export { blockTypeItem, Dropdown, DropdownSubmenu,
9
+ // MenuElement,
10
+ MenuItem,
11
+ // MenuItemSpec,
12
+ wrapItem, } from './menu.js';
13
+ function canInsert(state, nodeType) {
14
+ let $from = state.selection.$from;
15
+ for (let d = $from.depth; d >= 0; d--) {
16
+ let index = $from.index(d);
17
+ if ($from.node(d).canReplaceWith(index, index, nodeType))
18
+ return true;
19
+ }
20
+ return false;
21
+ }
22
+ function cmdItem(cmd, options) {
23
+ let passedOptions = {
24
+ label: options.title,
25
+ run: cmd,
26
+ };
27
+ for (let prop in options) {
28
+ passedOptions[prop] = options[prop];
29
+ }
30
+ if (!options.enable && !options.select) {
31
+ passedOptions[options.enable ? 'enable' : 'select'] = (state) => cmd(state);
32
+ }
33
+ return new MenuItem(passedOptions);
34
+ }
35
+ function markActive(state, type) {
36
+ let { from, $from, to, empty } = state.selection;
37
+ if (empty)
38
+ return !!type.isInSet(state.storedMarks || $from.marks());
39
+ else
40
+ return state.doc.rangeHasMark(from, to, type);
41
+ }
42
+ function markItem(markType, options) {
43
+ let passedOptions = {
44
+ active(state) {
45
+ return markActive(state, markType);
46
+ },
47
+ };
48
+ for (let prop in options) {
49
+ passedOptions[prop] = options[prop];
50
+ }
51
+ return cmdItem(toggleMark(markType), passedOptions);
52
+ }
53
+ function wrapListItem(nodeType, options) {
54
+ return cmdItem(wrapInList(nodeType, options.attrs), options);
55
+ }
56
+ const cut = (arr) => arr.filter((x) => x);
57
+ export function buildMenu(editor, schema) {
58
+ const menu = [];
59
+ if (schema.marks.strong) {
60
+ menu.push(new MenuItem({
61
+ title: 'Toggle strong assets',
62
+ run: () => editor.chain().toggleStrong().run(),
63
+ enable: (state) => editor.can().toggleStrong().run(),
64
+ icon: icons.strong,
65
+ }));
66
+ }
67
+ if (schema.marks.em) {
68
+ menu.push(new MenuItem({
69
+ title: 'Toggle emphasis',
70
+ run: () => editor.chain().toggleItalic().run(),
71
+ enable: (state) => editor.can().toggleItalic().run(),
72
+ icon: icons.em,
73
+ }));
74
+ }
75
+ if (schema.marks.underline) {
76
+ menu.push(new MenuItem({
77
+ title: 'Toggle underline',
78
+ label: '_',
79
+ run: () => editor.chain().toggleUnderline().run(),
80
+ enable: (state) => editor.can().toggleUnderline().run(),
81
+ // icon: icons.underline
82
+ }));
83
+ }
84
+ if (schema.marks.code) {
85
+ menu.push(markItem(schema.marks.code, {
86
+ title: 'Toggle code font',
87
+ icon: icons.code,
88
+ }));
89
+ }
90
+ if (schema.marks.link) {
91
+ const markType = schema.marks.link;
92
+ menu.push(new MenuItem({
93
+ title: 'Add or remove link',
94
+ icon: icons.link,
95
+ active(state) {
96
+ return markActive(state, markType);
97
+ },
98
+ enable(state) {
99
+ return !state.selection.empty;
100
+ },
101
+ run(state, dispatch, view) {
102
+ if (markActive(state, markType)) {
103
+ toggleMark(markType)(state, dispatch);
104
+ return true;
105
+ }
106
+ openPrompt({
107
+ title: 'Create a link',
108
+ fields: {
109
+ href: new TextField({
110
+ label: 'Link target',
111
+ required: true,
112
+ }),
113
+ title: new TextField({ label: 'Title' }),
114
+ },
115
+ callback(attrs) {
116
+ toggleMark(markType, attrs)(view.state, view.dispatch);
117
+ view.focus();
118
+ },
119
+ });
120
+ },
121
+ }));
122
+ }
123
+ const blockMenu = [];
124
+ const insertMenu = [];
125
+ const typeMenu = [];
126
+ if (schema.nodes.bullet_list) {
127
+ blockMenu.push(wrapListItem(schema.nodes.bullet_list, {
128
+ title: 'Wrap in bullet list',
129
+ icon: icons.bulletList,
130
+ }));
131
+ }
132
+ if (schema.nodes.ordered_list) {
133
+ blockMenu.push(wrapListItem(schema.nodes.ordered_list, {
134
+ title: 'Wrap in ordered list',
135
+ icon: icons.orderedList,
136
+ }));
137
+ }
138
+ if (schema.nodes.blockquote) {
139
+ blockMenu.push(wrapItem(schema.nodes.blockquote, {
140
+ title: 'Wrap in block quote',
141
+ icon: icons.blockquote,
142
+ }));
143
+ }
144
+ if (schema.nodes.paragraph) {
145
+ typeMenu.push(blockTypeItem(schema.nodes.paragraph, {
146
+ title: 'Change to paragraph',
147
+ label: 'Plain',
148
+ }));
149
+ }
150
+ if (schema.nodes.code_block) {
151
+ typeMenu.push(blockTypeItem(schema.nodes.code_block, {
152
+ title: 'Change to code block',
153
+ label: 'Code',
154
+ }));
155
+ }
156
+ if (schema.nodes.heading) {
157
+ const makeHeadMenu = [];
158
+ for (let i = 1; i <= 6; i++) {
159
+ makeHeadMenu.push(blockTypeItem(schema.nodes.heading, {
160
+ title: 'Change to heading ' + i,
161
+ label: 'Level ' + i,
162
+ attrs: { level: i },
163
+ }));
164
+ }
165
+ typeMenu.push(new DropdownSubmenu(makeHeadMenu, { label: 'Heading' }));
166
+ }
167
+ blockMenu.push(new MenuItem({
168
+ title: 'Join with above block',
169
+ run: () => editor.chain().joinUp().run(),
170
+ select: () => editor.can().joinUp().run(),
171
+ icon: icons.join,
172
+ }));
173
+ blockMenu.push(new MenuItem({
174
+ title: 'Lift out of enclosing block',
175
+ run: () => editor.chain().lift().run(),
176
+ select: () => editor.can().lift().run(),
177
+ icon: icons.lift,
178
+ }));
179
+ blockMenu.push(new MenuItem({
180
+ title: 'Select parent node',
181
+ run: () => editor.chain().selectParentNode().run(),
182
+ select: () => editor.can().selectParentNode().run(),
183
+ icon: icons.selectParentNode,
184
+ }));
185
+ if (schema.nodes.image) {
186
+ const nodeType = schema.nodes.image;
187
+ insertMenu.push(new MenuItem({
188
+ title: 'Insert image',
189
+ label: 'Image',
190
+ // enable: (state) => editor.can().setHorizontalRule().run(),
191
+ enable: (state) => canInsert(state, nodeType),
192
+ run(state, _, view) {
193
+ let { from, to } = state.selection, attrs = null;
194
+ if (state.selection instanceof NodeSelection &&
195
+ state.selection.node.type == nodeType) {
196
+ attrs = state.selection.node.attrs;
197
+ }
198
+ openPrompt({
199
+ title: 'Insert image',
200
+ fields: {
201
+ src: new TextField({
202
+ label: 'Location',
203
+ required: true,
204
+ value: attrs && attrs.src,
205
+ }),
206
+ title: new TextField({
207
+ label: 'Title',
208
+ value: attrs && attrs.title,
209
+ }),
210
+ alt: new TextField({
211
+ label: 'Description',
212
+ value: attrs ? attrs.alt : state.doc.textBetween(from, to, ' '),
213
+ }),
214
+ },
215
+ callback(attrs) {
216
+ view.dispatch(view.state.tr.replaceSelectionWith(nodeType.createAndFill(attrs)));
217
+ view.focus();
218
+ },
219
+ });
220
+ },
221
+ }));
222
+ }
223
+ if (schema.nodes.hr) {
224
+ insertMenu.push(new MenuItem({
225
+ title: 'Insert horizontal rule',
226
+ label: 'Horizontal rule',
227
+ run: () => editor.chain().setHorizontalRule().run(),
228
+ enable: (state) => editor.can().setHorizontalRule().run(),
229
+ }));
230
+ }
231
+ menu.push(new Dropdown(cut(insertMenu), {
232
+ label: 'Insert',
233
+ }));
234
+ menu.push(new Dropdown(cut(typeMenu), {
235
+ label: 'Type...',
236
+ }));
237
+ /*
238
+ r.blockMenu = [
239
+ cut([
240
+ r.wrapBulletList,
241
+ r.wrapOrderedList,
242
+ r.wrapBlockQuote,
243
+ joinUpItem,
244
+ liftItem,
245
+ selectParentNodeItem,
246
+ ]),
247
+ ];
248
+ */
249
+ menu.push(new MenuItem({
250
+ title: 'Undo last change',
251
+ run: () => editor.chain().undo().run(),
252
+ enable: () => editor.can().undo().run(),
253
+ icon: icons.undo,
254
+ }));
255
+ menu.push(new MenuItem({
256
+ title: 'Redo last undone change',
257
+ run: () => editor.chain().redo().run(),
258
+ enable: () => editor.can().redo().run(),
259
+ icon: icons.redo,
260
+ }));
261
+ if (schema.nodes.table) {
262
+ const item = (label, cmdName) => {
263
+ return new MenuItem({
264
+ label,
265
+ enable: () => editor.can()[cmdName]().run(),
266
+ run: () => editor.chain()[cmdName]().run(),
267
+ });
268
+ };
269
+ const tableMenu = [
270
+ item('Insert table', 'insertTable'),
271
+ item('Insert column before', 'addColumnBefore'),
272
+ item('Insert column after', 'addColumnAfter'),
273
+ item('Delete column', 'deleteColumn'),
274
+ item('Insert row before', 'addRowBefore'),
275
+ item('Insert row after', 'addRowAfter'),
276
+ item('Delete row', 'deleteRow'),
277
+ item('Delete table', 'deleteTable'),
278
+ item('Merge cells', 'mergeCells'),
279
+ item('Split cell', 'splitCell'),
280
+ item('Toggle header column', 'toggleHeaderColumn'),
281
+ item('Toggle header row', 'toggleHeaderRow'),
282
+ item('Toggle header cells', 'toggleHeaderCell'),
283
+ // item('Make cell green', setCellAttr('background', '#dfd')),
284
+ // item('Make cell not-green', setCellAttr('background', null)),
285
+ ];
286
+ menu.push(new Dropdown(tableMenu, { label: 'Table' }));
287
+ }
288
+ return [menu, blockMenu];
289
+ }
290
+ export class ExtensionMenu extends Extension {
291
+ constructor(config = { floating: true }) {
292
+ super(config);
293
+ Object.defineProperty(this, "config", {
294
+ enumerable: true,
295
+ configurable: true,
296
+ writable: true,
297
+ value: config
298
+ });
299
+ Object.defineProperty(this, "name", {
300
+ enumerable: true,
301
+ configurable: true,
302
+ writable: true,
303
+ value: 'menu'
304
+ });
305
+ }
306
+ getProseMirrorPlugins(editor, schema) {
307
+ const plugins = [];
308
+ let content = buildMenu(editor, schema);
309
+ if (this.config.modifyMenu) {
310
+ content = this.config.modifyMenu(content);
311
+ }
312
+ plugins.push(new MenuPlugin({
313
+ content,
314
+ floating: this.config.floating,
315
+ }));
316
+ return plugins;
317
+ }
318
+ }
@@ -0,0 +1,9 @@
1
+ import { Plugin } from 'prosemirror-state';
2
+ import { MenuElement } from './menu.js';
3
+ export declare class MenuPlugin extends Plugin {
4
+ constructor(options: {
5
+ content: readonly (readonly MenuElement[])[];
6
+ floating?: boolean;
7
+ });
8
+ }
9
+ //# sourceMappingURL=MenuPlugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MenuPlugin.d.ts","sourceRoot":"","sources":["../../../src/extension-menu/src/MenuPlugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,MAAM,EAAa,MAAM,mBAAmB,CAAC;AAEnE,OAAO,EAAE,WAAW,EAAiB,MAAM,WAAW,CAAC;AAyLvD,qBAAa,UAAW,SAAQ,MAAM;gBACxB,OAAO,EAAE;QAGnB,OAAO,EAAE,SAAS,CAAC,SAAS,WAAW,EAAE,CAAC,EAAE,CAAC;QAK7C,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB;CAOF"}
@@ -0,0 +1,245 @@
1
+ import { Plugin } from 'prosemirror-state';
2
+ import { renderGrouped } from './menu.js';
3
+ const CSS_PREFIX = 'kb-menu';
4
+ function isIOS() {
5
+ if (typeof navigator == 'undefined')
6
+ return false;
7
+ let agent = navigator?.userAgent;
8
+ return !/Edge\/\d/.test(agent) && /AppleWebKit/.test(agent) &&
9
+ /Mobile\/\w+/.test(agent);
10
+ }
11
+ class MenuBarView {
12
+ constructor(editorView, options) {
13
+ Object.defineProperty(this, "editorView", {
14
+ enumerable: true,
15
+ configurable: true,
16
+ writable: true,
17
+ value: editorView
18
+ });
19
+ Object.defineProperty(this, "options", {
20
+ enumerable: true,
21
+ configurable: true,
22
+ writable: true,
23
+ value: options
24
+ });
25
+ Object.defineProperty(this, "wrapper", {
26
+ enumerable: true,
27
+ configurable: true,
28
+ writable: true,
29
+ value: void 0
30
+ });
31
+ Object.defineProperty(this, "menu", {
32
+ enumerable: true,
33
+ configurable: true,
34
+ writable: true,
35
+ value: void 0
36
+ });
37
+ Object.defineProperty(this, "spacer", {
38
+ enumerable: true,
39
+ configurable: true,
40
+ writable: true,
41
+ value: null
42
+ });
43
+ Object.defineProperty(this, "maxHeight", {
44
+ enumerable: true,
45
+ configurable: true,
46
+ writable: true,
47
+ value: 0
48
+ });
49
+ Object.defineProperty(this, "widthForMaxHeight", {
50
+ enumerable: true,
51
+ configurable: true,
52
+ writable: true,
53
+ value: 0
54
+ });
55
+ Object.defineProperty(this, "floating", {
56
+ enumerable: true,
57
+ configurable: true,
58
+ writable: true,
59
+ value: false
60
+ });
61
+ Object.defineProperty(this, "contentUpdate", {
62
+ enumerable: true,
63
+ configurable: true,
64
+ writable: true,
65
+ value: void 0
66
+ });
67
+ Object.defineProperty(this, "scrollHandler", {
68
+ enumerable: true,
69
+ configurable: true,
70
+ writable: true,
71
+ value: null
72
+ });
73
+ Object.defineProperty(this, "root", {
74
+ enumerable: true,
75
+ configurable: true,
76
+ writable: true,
77
+ value: void 0
78
+ });
79
+ this.root = editorView.root;
80
+ this.wrapper = document.createElement('div');
81
+ this.wrapper.classList.add(CSS_PREFIX + '__wrapper');
82
+ this.menu = document.createElement('div');
83
+ this.menu.classList.add(CSS_PREFIX);
84
+ this.wrapper.appendChild(this.menu);
85
+ this.menu.className = CSS_PREFIX;
86
+ if (editorView.dom.parentNode) {
87
+ editorView.dom.parentNode.replaceChild(this.wrapper, editorView.dom);
88
+ }
89
+ this.wrapper.appendChild(editorView.dom);
90
+ let { dom, update } = renderGrouped(this.editorView, this.options.content);
91
+ this.contentUpdate = update;
92
+ this.menu.appendChild(dom);
93
+ this.update();
94
+ if (options.floating && !isIOS()) {
95
+ this.updateFloat();
96
+ let potentialScrollers = getAllWrapping(this.wrapper);
97
+ this.scrollHandler = (e) => {
98
+ let root = this.editorView.root;
99
+ if (!(root.body || root).contains(this.wrapper)) {
100
+ potentialScrollers.forEach((el) => el.removeEventListener('scroll', this.scrollHandler));
101
+ }
102
+ else {
103
+ this.updateFloat(e.target.getBoundingClientRect
104
+ ? e.target
105
+ : undefined);
106
+ }
107
+ };
108
+ potentialScrollers.forEach((el) => el.addEventListener('scroll', this.scrollHandler));
109
+ }
110
+ }
111
+ update() {
112
+ if (this.editorView.root != this.root) {
113
+ let { dom, update } = renderGrouped(this.editorView, this.options.content);
114
+ this.contentUpdate = update;
115
+ this.menu.replaceChild(dom, this.menu.firstChild);
116
+ this.root = this.editorView.root;
117
+ }
118
+ // this.contentUpdate(this.editorView.state);
119
+ if (this.floating) {
120
+ this.updateScrollCursor();
121
+ }
122
+ else {
123
+ if (this.menu.offsetWidth != this.widthForMaxHeight) {
124
+ this.widthForMaxHeight = this.menu.offsetWidth;
125
+ this.maxHeight = 0;
126
+ }
127
+ if (this.menu.offsetHeight > this.maxHeight) {
128
+ this.maxHeight = this.menu.offsetHeight;
129
+ }
130
+ }
131
+ }
132
+ updateScrollCursor() {
133
+ let selection = this.editorView.root.getSelection();
134
+ if (!selection.focusNode)
135
+ return;
136
+ let rects = selection.getRangeAt(0).getClientRects();
137
+ let selRect = rects[selectionIsInverted(selection) ? 0 : rects.length - 1];
138
+ if (!selRect)
139
+ return;
140
+ let menuRect = this.menu.getBoundingClientRect();
141
+ if (selRect.top < menuRect.bottom && selRect.bottom > menuRect.top) {
142
+ let scrollable = findWrappingScrollable(this.wrapper);
143
+ if (scrollable)
144
+ scrollable.scrollTop -= menuRect.bottom - selRect.top;
145
+ }
146
+ }
147
+ updateFloat(scrollAncestor) {
148
+ let parent = this.wrapper, editorRect = parent.getBoundingClientRect(), top = scrollAncestor
149
+ ? Math.max(0, scrollAncestor.getBoundingClientRect().top)
150
+ : 0;
151
+ if (this.floating) {
152
+ if (editorRect.top >= top || editorRect.bottom < this.menu.offsetHeight + 10) {
153
+ this.floating = false;
154
+ this.menu.style.position =
155
+ this.menu.style.left =
156
+ this.menu.style.top =
157
+ this.menu.style.width =
158
+ '';
159
+ this.menu.style.display = '';
160
+ this.spacer.parentNode.removeChild(this.spacer);
161
+ this.spacer = null;
162
+ }
163
+ else {
164
+ let border = (parent.offsetWidth - parent.clientWidth) / 2;
165
+ this.menu.style.left = (editorRect.left + border) + 'px';
166
+ this.menu.style.display = editorRect.top >
167
+ this.editorView.dom.ownerDocument.defaultView
168
+ .innerHeight
169
+ ? 'none'
170
+ : '';
171
+ if (scrollAncestor)
172
+ this.menu.style.top = top + 'px';
173
+ }
174
+ }
175
+ else {
176
+ if (editorRect.top < top && editorRect.bottom >= this.menu.offsetHeight + 10) {
177
+ this.floating = true;
178
+ let menuRect = this.menu.getBoundingClientRect();
179
+ this.menu.style.left = menuRect.left + 'px';
180
+ this.menu.style.width = menuRect.width + 'px';
181
+ if (scrollAncestor)
182
+ this.menu.style.top = top + 'px';
183
+ this.menu.style.position = 'fixed';
184
+ this.spacer = document.createElement('div');
185
+ this.spacer.classList.add(CSS_PREFIX + '__spacer');
186
+ this.spacer.style.height = `${menuRect.height}px`;
187
+ parent.insertBefore(this.spacer, this.menu);
188
+ }
189
+ }
190
+ }
191
+ destroy() {
192
+ if (this.wrapper.parentNode) {
193
+ this.wrapper.parentNode.replaceChild(this.editorView.dom, this.wrapper);
194
+ }
195
+ }
196
+ }
197
+ // Not precise, but close enough
198
+ function selectionIsInverted(selection) {
199
+ if (selection.anchorNode == selection.focusNode) {
200
+ return selection.anchorOffset > selection.focusOffset;
201
+ }
202
+ return selection.anchorNode.compareDocumentPosition(selection.focusNode) ==
203
+ Node.DOCUMENT_POSITION_FOLLOWING;
204
+ }
205
+ function findWrappingScrollable(node) {
206
+ for (let cur = node.parentNode; cur; cur = cur.parentNode) {
207
+ if (cur.scrollHeight > cur.clientHeight) {
208
+ return cur;
209
+ }
210
+ }
211
+ }
212
+ function getAllWrapping(node) {
213
+ let res = [node.ownerDocument.defaultView];
214
+ for (let cur = node.parentNode; cur; cur = cur.parentNode) {
215
+ res.push(cur);
216
+ }
217
+ return res;
218
+ }
219
+ export class MenuPlugin extends Plugin {
220
+ constructor(options) {
221
+ super({
222
+ view(editorView) {
223
+ return new MenuBarView(editorView, options);
224
+ },
225
+ });
226
+ }
227
+ }
228
+ /*
229
+ /// A plugin that will place a menu bar above the editor. Note that
230
+ /// this involves wrapping the editor in an additional `<div>`.
231
+ export function menuBar(options: {
232
+ /// Provides the content of the menu, as a nested array to be
233
+ /// passed to `renderGrouped`.
234
+ content: readonly (readonly MenuElement[])[]
235
+
236
+ /// Determines whether the menu floats, i.e. whether it sticks to
237
+ /// the top of the viewport when the editor is partially scrolled
238
+ /// out of view.
239
+ floating?: boolean
240
+ }): Plugin {
241
+ return new Plugin({
242
+ view(editorView) { return new MenuBarView(editorView, options) }
243
+ })
244
+ }
245
+ */
@@ -0,0 +1,15 @@
1
+ import { IconSpec } from './menu.js';
2
+ export declare function getIcon(root: Document | ShadowRoot, icon: {
3
+ path: string;
4
+ width: number;
5
+ height: number;
6
+ } | {
7
+ text: string;
8
+ css?: string;
9
+ } | {
10
+ dom: Node;
11
+ }): HTMLElement;
12
+ export declare const icons: {
13
+ [name: string]: IconSpec;
14
+ };
15
+ //# sourceMappingURL=icons.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../../src/extension-menu/src/icons.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAerC,wBAAgB,OAAO,CACrB,IAAI,EAAE,QAAQ,GAAG,UAAU,EAC3B,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG;IAAE,GAAG,EAAE,IAAI,CAAA;CAAE,GAChB,WAAW,CAmCb;AA8BD,eAAO,MAAM,KAAK,EAAE;IAAE,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAA;CAoE7C,CAAC"}