@atlaskit/editor-plugin-expand 0.1.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 (66) hide show
  1. package/CHANGELOG.md +1 -0
  2. package/LICENSE.md +13 -0
  3. package/README.md +30 -0
  4. package/dist/cjs/commands.js +184 -0
  5. package/dist/cjs/index.js +12 -0
  6. package/dist/cjs/nodeviews/index.js +494 -0
  7. package/dist/cjs/plugin.js +101 -0
  8. package/dist/cjs/pm-plugins/keymap.js +170 -0
  9. package/dist/cjs/pm-plugins/main.js +85 -0
  10. package/dist/cjs/pm-plugins/plugin-factory.js +15 -0
  11. package/dist/cjs/reducer.js +20 -0
  12. package/dist/cjs/toolbar.js +59 -0
  13. package/dist/cjs/types.js +5 -0
  14. package/dist/cjs/ui/ExpandIconButton.js +107 -0
  15. package/dist/cjs/utils.js +24 -0
  16. package/dist/es2019/commands.js +161 -0
  17. package/dist/es2019/index.js +1 -0
  18. package/dist/es2019/nodeviews/index.js +484 -0
  19. package/dist/es2019/plugin.js +86 -0
  20. package/dist/es2019/pm-plugins/keymap.js +197 -0
  21. package/dist/es2019/pm-plugins/main.js +73 -0
  22. package/dist/es2019/pm-plugins/plugin-factory.js +9 -0
  23. package/dist/es2019/reducer.js +11 -0
  24. package/dist/es2019/toolbar.js +52 -0
  25. package/dist/es2019/types.js +1 -0
  26. package/dist/es2019/ui/ExpandIconButton.js +88 -0
  27. package/dist/es2019/utils.js +1 -0
  28. package/dist/esm/commands.js +177 -0
  29. package/dist/esm/index.js +1 -0
  30. package/dist/esm/nodeviews/index.js +486 -0
  31. package/dist/esm/plugin.js +88 -0
  32. package/dist/esm/pm-plugins/keymap.js +165 -0
  33. package/dist/esm/pm-plugins/main.js +77 -0
  34. package/dist/esm/pm-plugins/plugin-factory.js +9 -0
  35. package/dist/esm/reducer.js +13 -0
  36. package/dist/esm/toolbar.js +52 -0
  37. package/dist/esm/types.js +1 -0
  38. package/dist/esm/ui/ExpandIconButton.js +98 -0
  39. package/dist/esm/utils.js +1 -0
  40. package/dist/types/commands.d.ts +13 -0
  41. package/dist/types/index.d.ts +3 -0
  42. package/dist/types/nodeviews/index.d.ts +55 -0
  43. package/dist/types/plugin.d.ts +24 -0
  44. package/dist/types/pm-plugins/keymap.d.ts +4 -0
  45. package/dist/types/pm-plugins/main.d.ts +7 -0
  46. package/dist/types/pm-plugins/plugin-factory.d.ts +3 -0
  47. package/dist/types/reducer.d.ts +3 -0
  48. package/dist/types/toolbar.d.ts +3 -0
  49. package/dist/types/types.d.ts +31 -0
  50. package/dist/types/ui/ExpandIconButton.d.ts +43 -0
  51. package/dist/types/utils.d.ts +1 -0
  52. package/dist/types-ts4.5/commands.d.ts +13 -0
  53. package/dist/types-ts4.5/index.d.ts +3 -0
  54. package/dist/types-ts4.5/nodeviews/index.d.ts +55 -0
  55. package/dist/types-ts4.5/plugin.d.ts +24 -0
  56. package/dist/types-ts4.5/pm-plugins/keymap.d.ts +4 -0
  57. package/dist/types-ts4.5/pm-plugins/main.d.ts +7 -0
  58. package/dist/types-ts4.5/pm-plugins/plugin-factory.d.ts +3 -0
  59. package/dist/types-ts4.5/reducer.d.ts +3 -0
  60. package/dist/types-ts4.5/toolbar.d.ts +3 -0
  61. package/dist/types-ts4.5/types.d.ts +31 -0
  62. package/dist/types-ts4.5/ui/ExpandIconButton.d.ts +43 -0
  63. package/dist/types-ts4.5/utils.d.ts +1 -0
  64. package/package.json +104 -0
  65. package/report.api.md +93 -0
  66. package/tmp/api-report-tmp.d.ts +62 -0
@@ -0,0 +1,484 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import React from 'react';
3
+ import ReactDOM from 'react-dom';
4
+ import { keyName } from 'w3c-keyname';
5
+ import { GapCursorSelection, RelativeSelectionPos, Side } from '@atlaskit/editor-common/selection';
6
+ import { expandClassNames } from '@atlaskit/editor-common/styles';
7
+ import { expandMessages } from '@atlaskit/editor-common/ui';
8
+ import { closestElement, isEmptyNode } from '@atlaskit/editor-common/utils';
9
+ import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
10
+ import { NodeSelection, Selection } from '@atlaskit/editor-prosemirror/state';
11
+ import { deleteExpandAtPos, setSelectionInsideExpand, toggleExpandExpanded, updateExpandTitle } from '../commands';
12
+ import { ExpandIconButton } from '../ui/ExpandIconButton';
13
+ function buildExpandClassName(type, expanded) {
14
+ return `${expandClassNames.prefix} ${expandClassNames.type(type)} ${expanded ? expandClassNames.expanded : ''}`;
15
+ }
16
+ const toDOM = (node, intl) => ['div', {
17
+ // prettier-ignore
18
+ 'class': buildExpandClassName(node.type.name, node.attrs.__expanded),
19
+ 'data-node-type': node.type.name,
20
+ 'data-title': node.attrs.title
21
+ }, ['div', {
22
+ // prettier-ignore
23
+ 'class': expandClassNames.titleContainer,
24
+ contenteditable: 'false',
25
+ // Element gains access to focus events.
26
+ // This is needed to prevent PM gaining access
27
+ // on interacting with our controls.
28
+ tabindex: '-1'
29
+ },
30
+ // prettier-ignore
31
+ ['div', {
32
+ 'class': expandClassNames.icon
33
+ }], ['div', {
34
+ // prettier-ignore
35
+ 'class': expandClassNames.inputContainer
36
+ }, ['input', {
37
+ // prettier-ignore
38
+ 'class': expandClassNames.titleInput,
39
+ value: node.attrs.title,
40
+ placeholder: intl && intl.formatMessage(expandMessages.expandPlaceholderText) || expandMessages.expandPlaceholderText.defaultMessage,
41
+ type: 'text'
42
+ }]]],
43
+ // prettier-ignore
44
+ ['div', {
45
+ 'class': expandClassNames.content
46
+ }, 0]];
47
+ export class ExpandNodeView {
48
+ constructor(node, view, getPos, getIntl, isMobile, featureFlags, selectNearNode, api) {
49
+ _defineProperty(this, "allowInteractiveExpand", true);
50
+ _defineProperty(this, "isMobile", false);
51
+ _defineProperty(this, "focusTitle", () => {
52
+ if (this.input) {
53
+ const {
54
+ state,
55
+ dispatch
56
+ } = this.view;
57
+ if (this.selectNearNode) {
58
+ const tr = this.selectNearNode({
59
+ selectionRelativeToNode: RelativeSelectionPos.Start
60
+ })(state);
61
+ if (dispatch) {
62
+ dispatch(tr);
63
+ }
64
+ }
65
+ const pos = this.getPos();
66
+ if (typeof pos === 'number') {
67
+ setSelectionInsideExpand(pos)(state, dispatch, this.view);
68
+ }
69
+ this.input.focus();
70
+ }
71
+ });
72
+ _defineProperty(this, "handleIconKeyDown", event => {
73
+ switch (keyName(event)) {
74
+ case 'Tab':
75
+ event.preventDefault();
76
+ this.focusTitle();
77
+ break;
78
+ case 'Enter':
79
+ event.preventDefault();
80
+ this.handleClick(event);
81
+ break;
82
+ }
83
+ });
84
+ _defineProperty(this, "isAllowInteractiveExpandEnabled", () => {
85
+ return this.featureFlags && !!this.featureFlags.interactiveExpand;
86
+ });
87
+ _defineProperty(this, "handleClick", event => {
88
+ const pos = this.getPos();
89
+ if (typeof pos !== 'number') {
90
+ return;
91
+ }
92
+ const target = event.target;
93
+ const {
94
+ state,
95
+ dispatch
96
+ } = this.view;
97
+ if (closestElement(target, `.${expandClassNames.icon}`)) {
98
+ var _this$api, _this$api$analytics;
99
+ if (!this.isAllowInteractiveExpandEnabled()) {
100
+ return;
101
+ }
102
+ event.stopPropagation();
103
+
104
+ // We blur the editorView, to prevent any keyboard showing on mobile
105
+ // When we're interacting with the expand toggle
106
+ if (this.view.dom instanceof HTMLElement) {
107
+ this.view.dom.blur();
108
+ }
109
+ toggleExpandExpanded((_this$api = this.api) === null || _this$api === void 0 ? void 0 : (_this$api$analytics = _this$api.analytics) === null || _this$api$analytics === void 0 ? void 0 : _this$api$analytics.actions)(pos, this.node.type)(state, dispatch);
110
+ return;
111
+ }
112
+ if (target === this.input) {
113
+ event.stopPropagation();
114
+ this.focusTitle();
115
+ return;
116
+ }
117
+ });
118
+ _defineProperty(this, "handleInput", event => {
119
+ const pos = this.getPos();
120
+ if (typeof pos !== 'number') {
121
+ return;
122
+ }
123
+ const target = event.target;
124
+ if (target === this.input) {
125
+ event.stopPropagation();
126
+ const {
127
+ state,
128
+ dispatch
129
+ } = this.view;
130
+ updateExpandTitle(target.value, pos, this.node.type)(state, dispatch);
131
+ }
132
+ });
133
+ _defineProperty(this, "handleFocus", event => {
134
+ event.stopImmediatePropagation();
135
+ });
136
+ _defineProperty(this, "handleTitleKeydown", event => {
137
+ switch (keyName(event)) {
138
+ case 'Enter':
139
+ this.toggleExpand();
140
+ break;
141
+ case 'Tab':
142
+ case 'ArrowDown':
143
+ this.moveToOutsideOfTitle(event);
144
+ break;
145
+ case 'ArrowRight':
146
+ this.handleArrowRightFromTitle(event);
147
+ break;
148
+ case 'ArrowLeft':
149
+ this.handleArrowLeftFromTitle(event);
150
+ break;
151
+ case 'ArrowUp':
152
+ this.setLeftGapCursor(event);
153
+ break;
154
+ case 'Backspace':
155
+ this.deleteExpand(event);
156
+ break;
157
+ }
158
+ });
159
+ _defineProperty(this, "deleteExpand", event => {
160
+ if (!this.input) {
161
+ return;
162
+ }
163
+ const pos = this.getPos();
164
+ if (typeof pos !== 'number') {
165
+ return;
166
+ }
167
+ const {
168
+ selectionStart,
169
+ selectionEnd
170
+ } = this.input;
171
+ if (selectionStart !== selectionEnd || selectionStart !== 0) {
172
+ return;
173
+ }
174
+ const {
175
+ state
176
+ } = this.view;
177
+ const expandNode = this.node;
178
+ if (expandNode && isEmptyNode(state.schema)(expandNode)) {
179
+ var _this$api2, _this$api2$analytics;
180
+ deleteExpandAtPos((_this$api2 = this.api) === null || _this$api2 === void 0 ? void 0 : (_this$api2$analytics = _this$api2.analytics) === null || _this$api2$analytics === void 0 ? void 0 : _this$api2$analytics.actions)(pos, expandNode)(state, this.view.dispatch);
181
+ }
182
+ });
183
+ _defineProperty(this, "toggleExpand", () => {
184
+ const pos = this.getPos();
185
+ if (typeof pos !== 'number') {
186
+ return;
187
+ }
188
+ if (this.isAllowInteractiveExpandEnabled()) {
189
+ var _this$api3, _this$api3$analytics;
190
+ const {
191
+ state,
192
+ dispatch
193
+ } = this.view;
194
+ toggleExpandExpanded((_this$api3 = this.api) === null || _this$api3 === void 0 ? void 0 : (_this$api3$analytics = _this$api3.analytics) === null || _this$api3$analytics === void 0 ? void 0 : _this$api3$analytics.actions)(pos, this.node.type)(state, dispatch);
195
+ }
196
+ });
197
+ _defineProperty(this, "moveToOutsideOfTitle", event => {
198
+ event.preventDefault();
199
+ const {
200
+ state,
201
+ dispatch
202
+ } = this.view;
203
+ const expandPos = this.getPos();
204
+ if (typeof expandPos !== 'number') {
205
+ return;
206
+ }
207
+ let pos = expandPos;
208
+ if (this.isCollapsed()) {
209
+ pos = expandPos + this.node.nodeSize;
210
+ }
211
+ const resolvedPos = state.doc.resolve(pos);
212
+ if (!resolvedPos) {
213
+ return;
214
+ }
215
+ if (this.isCollapsed() && resolvedPos.nodeAfter && ['expand', 'nestedExpand'].indexOf(resolvedPos.nodeAfter.type.name) > -1) {
216
+ return this.setRightGapCursor(event);
217
+ }
218
+ const sel = Selection.findFrom(resolvedPos, 1, true);
219
+ if (sel) {
220
+ // If the input has focus, ProseMirror doesn't
221
+ // Give PM focus back before changing our selection
222
+ this.view.focus();
223
+ dispatch(state.tr.setSelection(sel));
224
+ }
225
+ });
226
+ _defineProperty(this, "isCollapsed", () => {
227
+ return !this.node.attrs.__expanded;
228
+ });
229
+ _defineProperty(this, "setRightGapCursor", event => {
230
+ if (!this.input) {
231
+ return;
232
+ }
233
+ const pos = this.getPos();
234
+ if (typeof pos !== 'number') {
235
+ return;
236
+ }
237
+ const {
238
+ value,
239
+ selectionStart,
240
+ selectionEnd
241
+ } = this.input;
242
+ if (selectionStart === selectionEnd && selectionStart === value.length) {
243
+ const {
244
+ state,
245
+ dispatch
246
+ } = this.view;
247
+ event.preventDefault();
248
+ this.view.focus();
249
+ dispatch(state.tr.setSelection(new GapCursorSelection(state.doc.resolve(this.node.nodeSize + pos), Side.RIGHT)));
250
+ }
251
+ });
252
+ _defineProperty(this, "setLeftGapCursor", event => {
253
+ if (!this.input) {
254
+ return;
255
+ }
256
+ const pos = this.getPos();
257
+ if (typeof pos !== 'number') {
258
+ return;
259
+ }
260
+ const {
261
+ selectionStart,
262
+ selectionEnd
263
+ } = this.input;
264
+ if (selectionStart === selectionEnd && selectionStart === 0) {
265
+ event.preventDefault();
266
+ const {
267
+ state,
268
+ dispatch
269
+ } = this.view;
270
+ this.view.focus();
271
+ dispatch(state.tr.setSelection(new GapCursorSelection(state.doc.resolve(pos), Side.LEFT)));
272
+ }
273
+ });
274
+ _defineProperty(this, "handleArrowRightFromTitle", event => {
275
+ if (!this.input || !this.selectNearNode) {
276
+ return;
277
+ }
278
+ const pos = this.getPos();
279
+ if (typeof pos !== 'number') {
280
+ return;
281
+ }
282
+ const {
283
+ value,
284
+ selectionStart,
285
+ selectionEnd
286
+ } = this.input;
287
+ if (selectionStart === selectionEnd && selectionStart === value.length) {
288
+ event.preventDefault();
289
+ const {
290
+ state,
291
+ dispatch
292
+ } = this.view;
293
+ this.view.focus();
294
+ const tr = this.selectNearNode({
295
+ selectionRelativeToNode: RelativeSelectionPos.End,
296
+ selection: NodeSelection.create(state.doc, pos)
297
+ })(state);
298
+ if (dispatch) {
299
+ dispatch(tr);
300
+ }
301
+ }
302
+ });
303
+ _defineProperty(this, "handleArrowLeftFromTitle", event => {
304
+ if (!this.input || !this.selectNearNode) {
305
+ return;
306
+ }
307
+ const pos = this.getPos();
308
+ if (typeof pos !== 'number') {
309
+ return;
310
+ }
311
+ const {
312
+ selectionStart,
313
+ selectionEnd
314
+ } = this.input;
315
+ if (selectionStart === selectionEnd && selectionStart === 0) {
316
+ var _this$api4, _this$api4$selection;
317
+ event.preventDefault();
318
+ const {
319
+ state,
320
+ dispatch
321
+ } = this.view;
322
+ this.view.focus();
323
+ const selectionSharedState = ((_this$api4 = this.api) === null || _this$api4 === void 0 ? void 0 : (_this$api4$selection = _this$api4.selection) === null || _this$api4$selection === void 0 ? void 0 : _this$api4$selection.sharedState.currentState()) || {};
324
+ // selectionRelativeToNode is undefined when user clicked to select node, then hit left to get focus in title
325
+ // This is a special case where we want to bypass node selection and jump straight to gap cursor
326
+ if ((selectionSharedState === null || selectionSharedState === void 0 ? void 0 : selectionSharedState.selectionRelativeToNode) === undefined) {
327
+ const tr = this.selectNearNode({
328
+ selectionRelativeToNode: undefined,
329
+ selection: new GapCursorSelection(state.doc.resolve(pos), Side.LEFT)
330
+ })(state);
331
+ if (dispatch) {
332
+ dispatch(tr);
333
+ }
334
+ } else {
335
+ const tr = this.selectNearNode({
336
+ selectionRelativeToNode: RelativeSelectionPos.Start,
337
+ selection: NodeSelection.create(state.doc, pos)
338
+ })(state);
339
+ if (dispatch) {
340
+ dispatch(tr);
341
+ }
342
+ }
343
+ }
344
+ });
345
+ this.selectNearNode = selectNearNode;
346
+ this.intl = getIntl();
347
+ const {
348
+ dom,
349
+ contentDOM
350
+ } = DOMSerializer.renderSpec(document, toDOM(node, this.intl));
351
+ this.getPos = getPos;
352
+ this.view = view;
353
+ this.node = node;
354
+ this.dom = dom;
355
+ this.contentDOM = contentDOM;
356
+ this.isMobile = isMobile;
357
+ this.featureFlags = featureFlags;
358
+ this.api = api;
359
+ this.icon = this.dom.querySelector(`.${expandClassNames.icon}`);
360
+ this.input = this.dom.querySelector(`.${expandClassNames.titleInput}`);
361
+ this.titleContainer = this.dom.querySelector(`.${expandClassNames.titleContainer}`);
362
+ this.content = this.dom.querySelector(`.${expandClassNames.content}`);
363
+ this.renderIcon(this.intl);
364
+ this.initHandlers();
365
+ }
366
+ initHandlers() {
367
+ if (this.dom) {
368
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
369
+ this.dom.addEventListener('click', this.handleClick);
370
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
371
+ this.dom.addEventListener('input', this.handleInput);
372
+ }
373
+ if (this.input) {
374
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
375
+ this.input.addEventListener('keydown', this.handleTitleKeydown);
376
+ }
377
+ if (this.titleContainer) {
378
+ // If the user interacts in our title bar (either toggle or input)
379
+ // Prevent ProseMirror from getting a focus event (causes weird selection issues).
380
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
381
+ this.titleContainer.addEventListener('focus', this.handleFocus);
382
+ }
383
+ if (this.icon) {
384
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
385
+ this.icon.addEventListener('keydown', this.handleIconKeyDown);
386
+ }
387
+ }
388
+ renderIcon(intl, node) {
389
+ if (!this.icon) {
390
+ return;
391
+ }
392
+ const {
393
+ __expanded
394
+ } = node && node.attrs || this.node.attrs;
395
+ ReactDOM.render( /*#__PURE__*/React.createElement(ExpandIconButton, {
396
+ intl: intl,
397
+ allowInteractiveExpand: this.isAllowInteractiveExpandEnabled(),
398
+ expanded: __expanded
399
+ }), this.icon);
400
+ }
401
+ stopEvent(event) {
402
+ const target = event.target;
403
+ return target === this.input || target === this.icon || !!closestElement(target, `.${expandClassNames.icon}`);
404
+ }
405
+ ignoreMutation(mutationRecord) {
406
+ // ME-1931: Mobile relies on composition which creates dom mutations. If we ignore them, prosemirror
407
+ // does not recognise the changes and reverts them.
408
+ if (this.isMobile && (mutationRecord.type === 'characterData' || mutationRecord.type === 'childList')) {
409
+ return false;
410
+ }
411
+ if (mutationRecord.type === 'selection') {
412
+ return false;
413
+ }
414
+ return true;
415
+ }
416
+ update(node, _decorations) {
417
+ if (this.node.type === node.type) {
418
+ if (this.node.attrs.__expanded !== node.attrs.__expanded) {
419
+ // Instead of re-rendering the view on an expand toggle
420
+ // we toggle a class name to hide the content and animate the chevron.
421
+ if (this.dom) {
422
+ this.dom.classList.toggle(expandClassNames.expanded);
423
+ this.renderIcon(this && this.intl, node);
424
+ }
425
+ if (this.content) {
426
+ // Disallow interaction/selection inside when collapsed.
427
+ this.content.setAttribute('contenteditable', node.attrs.__expanded);
428
+ }
429
+ }
430
+
431
+ // During a collab session the title doesn't sync with other users
432
+ // since we're intentionally being less aggressive about re-rendering.
433
+ // We also apply a rAF to avoid abrupt continuous replacement of the title.
434
+ window.requestAnimationFrame(() => {
435
+ if (this.input && this.node.attrs.title !== this.input.value) {
436
+ this.input.value = this.node.attrs.title;
437
+ }
438
+ });
439
+ this.node = node;
440
+ return true;
441
+ }
442
+ return false;
443
+ }
444
+ destroy() {
445
+ if (this.dom) {
446
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
447
+ this.dom.removeEventListener('click', this.handleClick);
448
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
449
+ this.dom.removeEventListener('input', this.handleInput);
450
+ }
451
+ if (this.input) {
452
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
453
+ this.input.removeEventListener('keydown', this.handleTitleKeydown);
454
+ }
455
+ if (this.titleContainer) {
456
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
457
+ this.titleContainer.removeEventListener('focus', this.handleFocus);
458
+ }
459
+ if (this.icon) {
460
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
461
+ this.icon.removeEventListener('keydown', this.handleIconKeyDown);
462
+ ReactDOM.unmountComponentAtNode(this.icon);
463
+ }
464
+
465
+ // @ts-ignore - [unblock prosemirror bump] reset non optional prop to undefined to clear reference
466
+ this.dom = undefined;
467
+ this.contentDOM = undefined;
468
+ this.icon = undefined;
469
+ this.input = undefined;
470
+ this.titleContainer = undefined;
471
+ this.content = undefined;
472
+ }
473
+ }
474
+ export default function ({
475
+ getIntl,
476
+ isMobile,
477
+ featureFlags,
478
+ api
479
+ }) {
480
+ return (node, view, getPos) => {
481
+ var _api$selection, _api$selection$action;
482
+ return new ExpandNodeView(node, view, getPos, getIntl, isMobile, featureFlags, api === null || api === void 0 ? void 0 : (_api$selection = api.selection) === null || _api$selection === void 0 ? void 0 : (_api$selection$action = _api$selection.actions) === null || _api$selection$action === void 0 ? void 0 : _api$selection$action.selectNearNode, api);
483
+ };
484
+ }
@@ -0,0 +1,86 @@
1
+ import React from 'react';
2
+ import { expand, nestedExpand } from '@atlaskit/adf-schema';
3
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
4
+ import { toolbarInsertBlockMessages as messages } from '@atlaskit/editor-common/messages';
5
+ import { IconExpand } from '@atlaskit/editor-common/quick-insert';
6
+ import { createWrapSelectionTransaction } from '@atlaskit/editor-common/utils';
7
+ import { createExpandNode, insertExpand } from './commands';
8
+ import { expandKeymap } from './pm-plugins/keymap';
9
+ import { createPlugin } from './pm-plugins/main';
10
+ import { getToolbarConfig } from './toolbar';
11
+ export const expandPlugin = ({
12
+ config: options = {},
13
+ api
14
+ }) => {
15
+ var _api$featureFlags, _api$analytics;
16
+ const featureFlags = (api === null || api === void 0 ? void 0 : (_api$featureFlags = api.featureFlags) === null || _api$featureFlags === void 0 ? void 0 : _api$featureFlags.sharedState.currentState()) || {};
17
+ return {
18
+ name: 'expand',
19
+ nodes() {
20
+ return [{
21
+ name: 'expand',
22
+ node: expand
23
+ }, {
24
+ name: 'nestedExpand',
25
+ node: nestedExpand
26
+ }];
27
+ },
28
+ actions: {
29
+ insertExpand: insertExpand(api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions)
30
+ },
31
+ pmPlugins() {
32
+ return [{
33
+ name: 'expand',
34
+ plugin: ({
35
+ dispatch,
36
+ getIntl
37
+ }) => {
38
+ return createPlugin(dispatch, getIntl, options.appearance, options.useLongPressSelection, featureFlags, api);
39
+ }
40
+ }, {
41
+ name: 'expandKeymap',
42
+ plugin: () => expandKeymap(api)
43
+ }];
44
+ },
45
+ pluginsOptions: {
46
+ floatingToolbar: getToolbarConfig(api),
47
+ quickInsert: ({
48
+ formatMessage
49
+ }) => {
50
+ if (options && options.allowInsertion !== true) {
51
+ return [];
52
+ }
53
+ return [{
54
+ id: 'expand',
55
+ title: formatMessage(messages.expand),
56
+ description: formatMessage(messages.expandDescription),
57
+ keywords: ['accordion', 'collapse'],
58
+ priority: 600,
59
+ icon: () => /*#__PURE__*/React.createElement(IconExpand, null),
60
+ action(insert, state) {
61
+ var _api$analytics2;
62
+ const node = createExpandNode(state);
63
+ if (!node) {
64
+ return false;
65
+ }
66
+ const tr = state.selection.empty ? insert(node) : createWrapSelectionTransaction({
67
+ state,
68
+ type: node.type
69
+ });
70
+ api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions.attachAnalyticsEvent({
71
+ action: ACTION.INSERTED,
72
+ actionSubject: ACTION_SUBJECT.DOCUMENT,
73
+ actionSubjectId: node.type === state.schema.nodes.nestedExpand ? ACTION_SUBJECT_ID.NESTED_EXPAND : ACTION_SUBJECT_ID.EXPAND,
74
+ attributes: {
75
+ inputMethod: INPUT_METHOD.QUICK_INSERT
76
+ },
77
+ eventType: EVENT_TYPE.TRACK
78
+ })(tr);
79
+ return tr;
80
+ }
81
+ }];
82
+ }
83
+ }
84
+ };
85
+ };
86
+ export { pluginKey } from './pm-plugins/plugin-factory';