@atlaskit/editor-plugin-synced-block 2.1.0 → 2.1.1

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 (49) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/afm-cc/tsconfig.json +3 -0
  3. package/afm-dev-agents/tsconfig.json +3 -0
  4. package/afm-jira/tsconfig.json +3 -0
  5. package/afm-passionfruit/tsconfig.json +3 -0
  6. package/afm-post-office/tsconfig.json +3 -0
  7. package/afm-rovo-extension/tsconfig.json +3 -0
  8. package/afm-townsquare/tsconfig.json +3 -0
  9. package/dist/cjs/nodeviews/syncedBlock.js +118 -75
  10. package/dist/cjs/pm-plugins/actions.js +23 -9
  11. package/dist/cjs/pm-plugins/main.js +4 -3
  12. package/dist/cjs/pm-plugins/utils/utils.js +11 -0
  13. package/dist/cjs/syncedBlockPlugin.js +6 -3
  14. package/dist/cjs/ui/SyncBlockEditorWrapper.js +38 -0
  15. package/dist/cjs/ui/SyncBlockRendererWrapper.js +26 -0
  16. package/dist/cjs/ui/floating-toolbar.js +58 -3
  17. package/dist/es2019/nodeviews/syncedBlock.js +103 -67
  18. package/dist/es2019/pm-plugins/actions.js +23 -8
  19. package/dist/es2019/pm-plugins/main.js +4 -3
  20. package/dist/es2019/pm-plugins/utils/utils.js +7 -0
  21. package/dist/es2019/syncedBlockPlugin.js +4 -3
  22. package/dist/es2019/ui/SyncBlockEditorWrapper.js +28 -0
  23. package/dist/es2019/ui/SyncBlockRendererWrapper.js +20 -0
  24. package/dist/es2019/ui/floating-toolbar.js +56 -2
  25. package/dist/esm/nodeviews/syncedBlock.js +116 -72
  26. package/dist/esm/pm-plugins/actions.js +21 -8
  27. package/dist/esm/pm-plugins/main.js +4 -3
  28. package/dist/esm/pm-plugins/utils/utils.js +5 -0
  29. package/dist/esm/syncedBlockPlugin.js +6 -3
  30. package/dist/esm/ui/SyncBlockEditorWrapper.js +31 -0
  31. package/dist/esm/ui/SyncBlockRendererWrapper.js +19 -0
  32. package/dist/esm/ui/floating-toolbar.js +57 -3
  33. package/dist/types/nodeviews/syncedBlock.d.ts +29 -15
  34. package/dist/types/pm-plugins/actions.d.ts +3 -1
  35. package/dist/types/pm-plugins/main.d.ts +3 -3
  36. package/dist/types/pm-plugins/utils/utils.d.ts +3 -0
  37. package/dist/types/syncedBlockPluginType.d.ts +4 -2
  38. package/dist/types/ui/SyncBlockEditorWrapper.d.ts +16 -0
  39. package/dist/types/ui/SyncBlockRendererWrapper.d.ts +9 -0
  40. package/dist/types/ui/floating-toolbar.d.ts +6 -2
  41. package/dist/types-ts4.5/nodeviews/syncedBlock.d.ts +29 -15
  42. package/dist/types-ts4.5/pm-plugins/actions.d.ts +3 -1
  43. package/dist/types-ts4.5/pm-plugins/main.d.ts +3 -3
  44. package/dist/types-ts4.5/pm-plugins/utils/utils.d.ts +3 -0
  45. package/dist/types-ts4.5/syncedBlockPluginType.d.ts +6 -2
  46. package/dist/types-ts4.5/ui/SyncBlockEditorWrapper.d.ts +16 -0
  47. package/dist/types-ts4.5/ui/SyncBlockRendererWrapper.d.ts +9 -0
  48. package/dist/types-ts4.5/ui/floating-toolbar.d.ts +6 -2
  49. package/package.json +6 -4
@@ -1,105 +1,141 @@
1
- /* eslint-disable @atlaskit/ui-styling-standard/enforce-style-prop */
2
- import React, { useMemo, useRef, useState } from 'react';
1
+ import React from 'react';
3
2
  import ReactNodeView from '@atlaskit/editor-common/react-node-view';
4
- export const defaultSyncBlockDocument = {
3
+ import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
4
+ import { SyncBlockEditorWrapper, SyncBlockEditorWrapperDataId } from '../ui/SyncBlockEditorWrapper';
5
+ import { SyncBlockRendererWrapper } from '../ui/SyncBlockRendererWrapper';
6
+ const defaultSyncBlockEditorDocument = {
5
7
  version: 1,
6
8
  type: 'doc',
7
9
  content: [{
8
10
  type: 'paragraph',
9
11
  content: [{
10
12
  type: 'text',
11
- text: 'This is a synced block. Edit the source to update the content.'
13
+ text: 'This is a source sync block. Edit me to update the content.'
12
14
  }]
13
15
  }]
14
16
  };
15
- const SyncBlockEditorWrapperDataId = 'sync-block-plugin-editor-wrapper';
16
- export const SyncBlockPluginComponent = ({
17
- config,
18
- dom
19
- }) => {
20
- const innerEditorView = useRef(null);
21
-
22
- /* Tmp solution to demonstrate the synced block renderer */
23
- const [rendererDocument, setRendererDocument] = useState(defaultSyncBlockDocument);
24
- const onChange = (editorView, _meta) => {
25
- const content = editorView.state.doc.toJSON().content;
26
- const rendererDocument = {
27
- version: 1,
28
- type: 'doc',
29
- content
30
- };
31
- setRendererDocument(rendererDocument);
32
- };
33
- const onEditorReady = ({
34
- editorView
35
- }) => {
36
- innerEditorView.current = editorView || null;
37
- };
38
- const boundariesElement = useMemo(() => {
39
- // eslint-disable-next-line @atlaskit/editor/no-as-casting
40
- return dom.closest('.fabric-editor-popup-scroll-parent');
41
- }, [dom]);
42
- if (!boundariesElement || !(boundariesElement instanceof HTMLElement)) {
43
- return null;
44
- }
45
- if (!(config !== null && config !== void 0 && config.getSyncedBlockEditor) || !(config !== null && config !== void 0 && config.getSyncedBlockRenderer)) {
46
- return null;
47
- }
48
- return /*#__PURE__*/React.createElement("div", {
49
- "data-testid": SyncBlockEditorWrapperDataId
50
- }, config.getSyncedBlockEditor({
51
- boundariesElement: boundariesElement,
52
- defaultDocument: defaultSyncBlockDocument,
53
- mountPoint: dom,
54
- onChange: onChange,
55
- onEditorReady: onEditorReady
56
- }), /*#__PURE__*/React.createElement("div", {
57
- style: {
58
- width: '100%',
59
- height: '1px',
60
- // eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage
61
- backgroundColor: 'purple'
62
- }
63
- }), config.getSyncedBlockRenderer({
64
- docNode: rendererDocument
65
- }));
17
+ const defaultSyncBlockRendererDocument = {
18
+ version: 1,
19
+ type: 'doc',
20
+ content: [{
21
+ type: 'paragraph',
22
+ content: [{
23
+ type: 'text',
24
+ text: 'This is a reference sync block. Stay tuned for updates...'
25
+ }]
26
+ }]
66
27
  };
67
28
  class SyncBlock extends ReactNodeView {
29
+ constructor(props) {
30
+ super(props.node, props.view, props.getPos, props.portalProviderAPI, props.eventDispatcher, props);
31
+ const {
32
+ resourceId,
33
+ localId
34
+ } = props.node.attrs;
35
+ // Temporary solution to identify the source
36
+ this.isSource = resourceId === localId;
37
+ this.options = props.options;
38
+ }
68
39
  createDomRef() {
69
40
  const domRef = document.createElement('div');
70
- domRef.setAttribute('style', 'border: purple solid 1px;');
71
41
  return domRef;
72
42
  }
73
- render() {
74
- return /*#__PURE__*/React.createElement(SyncBlockPluginComponent, {
75
- config: this.reactComponentProps.config,
76
- dom: this.dom
43
+ handleContentChanges(_updatedDoc) {
44
+ // write data
45
+ }
46
+ setInnerEditorView(_editorView) {
47
+ // set inner editor view
48
+ }
49
+ renderEditor() {
50
+ var _this$options, _this$options2;
51
+ const popupsBoundariesElement = this.dom.closest('.fabric-editor-popup-scroll-parent');
52
+ if (!(popupsBoundariesElement instanceof HTMLElement)) {
53
+ return null;
54
+ }
55
+ if (!((_this$options = this.options) !== null && _this$options !== void 0 && _this$options.getSyncedBlockEditor)) {
56
+ return null;
57
+ }
58
+ return /*#__PURE__*/React.createElement(SyncBlockEditorWrapper, {
59
+ popupsBoundariesElement: popupsBoundariesElement,
60
+ popupsMountPoint: this.dom,
61
+ defaultDocument: defaultSyncBlockEditorDocument,
62
+ handleContentChanges: this.handleContentChanges,
63
+ setInnerEditorView: this.setInnerEditorView,
64
+ getSyncedBlockEditor: (_this$options2 = this.options) === null || _this$options2 === void 0 ? void 0 : _this$options2.getSyncedBlockEditor
65
+ });
66
+ }
67
+ renderRenderer() {
68
+ var _this$options3, _this$options4;
69
+ if (!((_this$options3 = this.options) !== null && _this$options3 !== void 0 && _this$options3.getSyncedBlockRenderer)) {
70
+ return null;
71
+ }
72
+
73
+ // get document node from data provider
74
+ const docNode = defaultSyncBlockRendererDocument;
75
+ return /*#__PURE__*/React.createElement(SyncBlockRendererWrapper, {
76
+ docNode: docNode,
77
+ getSyncedBlockRenderer: (_this$options4 = this.options) === null || _this$options4 === void 0 ? void 0 : _this$options4.getSyncedBlockRenderer
77
78
  });
78
79
  }
80
+ render() {
81
+ if (this.isSource) {
82
+ return this.renderEditor();
83
+ }
84
+ return this.renderRenderer();
85
+ }
79
86
  stopEvent(event) {
80
87
  var _target$closest;
81
88
  const target = event.target;
82
89
  if (!target) {
83
90
  return false;
84
91
  }
85
- return ((_target$closest = target.closest) === null || _target$closest === void 0 ? void 0 : _target$closest.call(target, `[data-testid="${SyncBlockEditorWrapperDataId}"]`)) != null;
92
+ const isInNestedEditor = ((_target$closest = target.closest) === null || _target$closest === void 0 ? void 0 : _target$closest.call(target, `[data-testid="${SyncBlockEditorWrapperDataId}"]`)) != null;
93
+ if (isInNestedEditor) {
94
+ this.selectNode();
95
+ return true;
96
+ }
97
+ return false;
98
+ }
99
+ selectNode() {
100
+ this.selectSyncBlockNode(undefined);
86
101
  }
87
102
  destroy() {
88
103
  var _this$unsubscribe;
89
104
  (_this$unsubscribe = this.unsubscribe) === null || _this$unsubscribe === void 0 ? void 0 : _this$unsubscribe.call(this);
90
105
  super.destroy();
91
106
  }
107
+ selectSyncBlockNode(relativeSelectionPos) {
108
+ var _this$reactComponentP, _this$reactComponentP2;
109
+ const getPos = typeof this.getPos === 'function' ? this.getPos() : 0;
110
+ const selectionAPI = (_this$reactComponentP = this.reactComponentProps.api) === null || _this$reactComponentP === void 0 ? void 0 : (_this$reactComponentP2 = _this$reactComponentP.selection) === null || _this$reactComponentP2 === void 0 ? void 0 : _this$reactComponentP2.actions;
111
+ if (!selectionAPI) {
112
+ return;
113
+ }
114
+ const tr = selectionAPI.selectNearNode({
115
+ selectionRelativeToNode: relativeSelectionPos,
116
+ selection: NodeSelection.create(this.view.state.doc, getPos !== null && getPos !== void 0 ? getPos : 0)
117
+ })(this.view.state);
118
+ if (tr) {
119
+ this.view.dispatch(tr);
120
+ }
121
+ }
92
122
  }
93
123
  export const syncBlockNodeView = ({
94
- config,
95
- pmPluginFactoryParams
124
+ options,
125
+ pmPluginFactoryParams,
126
+ api
96
127
  }) => (node, view, getPos) => {
97
128
  const {
98
129
  portalProviderAPI,
99
130
  eventDispatcher
100
131
  } = pmPluginFactoryParams;
101
- const reactComponentProps = {
102
- config
103
- };
104
- return new SyncBlock(node, view, getPos, portalProviderAPI, eventDispatcher, reactComponentProps, undefined).init();
132
+ return new SyncBlock({
133
+ api,
134
+ options,
135
+ node,
136
+ view,
137
+ getPos,
138
+ portalProviderAPI,
139
+ eventDispatcher
140
+ }).init();
105
141
  };
@@ -1,19 +1,34 @@
1
+ import uuid from 'uuid';
2
+ import { toDOM, copyDomNode } from '@atlaskit/editor-common/copy-button';
3
+ import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
1
4
  import { safeInsert } from '@atlaskit/editor-prosemirror/utils';
2
- const getRandomId = () => {
3
- if (!globalThis.crypto || typeof globalThis.crypto.randomUUID !== 'function') {
4
- return new Date().toISOString();
5
- }
6
- return globalThis.crypto.randomUUID();
7
- };
8
5
  export const createSyncedBlock = state => {
6
+ const id = uuid();
9
7
  const tr = state.tr;
10
8
  // const { breakout } = state.schema.marks;
11
9
  const node = state.schema.nodes.syncBlock.createChecked({
12
- resourceId: getRandomId(),
13
- localId: getRandomId()
10
+ resourceId: id,
11
+ localId: id
14
12
  }, null
15
13
  // [breakout.create({ mode: 'wide' })],
16
14
  );
17
15
  safeInsert(node)(tr);
18
16
  return tr;
17
+ };
18
+ export const copySyncedBlockReferenceToClipboard = (state, _dispatch, _view) => {
19
+ const {
20
+ schema,
21
+ selection
22
+ } = state;
23
+ if (selection instanceof NodeSelection) {
24
+ const nodeType = selection.node.type;
25
+ const domNode = toDOM(selection.node, schema);
26
+ // clear local-id
27
+ if (domNode instanceof HTMLElement) {
28
+ domNode.setAttribute('data-local-id', '');
29
+ }
30
+ copyDomNode(domNode, nodeType, selection);
31
+ return true;
32
+ }
33
+ return false;
19
34
  };
@@ -5,7 +5,7 @@ export const syncedBlockPluginKey = new PluginKey('syncedBlockPlugin');
5
5
 
6
6
  // eslint-disable-next-line @typescript-eslint/no-empty-object-type
7
7
 
8
- export const createPlugin = (config, pmPluginFactoryParams, _syncBlockStore) => {
8
+ export const createPlugin = (options, pmPluginFactoryParams, _syncBlockStore, api) => {
9
9
  return new SafePlugin({
10
10
  key: syncedBlockPluginKey,
11
11
  state: {
@@ -23,8 +23,9 @@ export const createPlugin = (config, pmPluginFactoryParams, _syncBlockStore) =>
23
23
  props: {
24
24
  nodeViews: {
25
25
  syncBlock: lazySyncBlockView({
26
- config,
27
- pmPluginFactoryParams
26
+ options,
27
+ pmPluginFactoryParams,
28
+ api
28
29
  })
29
30
  }
30
31
  }
@@ -0,0 +1,7 @@
1
+ import { findParentNodeOfType, findSelectedNodeOfType } from '@atlaskit/editor-prosemirror/utils';
2
+ export const findSyncBlock = (state, selection) => {
3
+ const {
4
+ syncBlock
5
+ } = state.schema.nodes;
6
+ return findSelectedNodeOfType(syncBlock)(selection || state.selection) || findParentNodeOfType(syncBlock)(selection || state.selection);
7
+ };
@@ -6,7 +6,8 @@ import { createSyncedBlock } from './pm-plugins/actions';
6
6
  import { createPlugin } from './pm-plugins/main';
7
7
  import { getToolbarConfig } from './ui/floating-toolbar';
8
8
  export const syncedBlockPlugin = ({
9
- config
9
+ config,
10
+ api
10
11
  }) => {
11
12
  const syncBlockStore = new SyncBlockStoreManager(config === null || config === void 0 ? void 0 : config.dataProvider);
12
13
  return {
@@ -20,7 +21,7 @@ export const syncedBlockPlugin = ({
20
21
  pmPlugins() {
21
22
  return [{
22
23
  name: 'syncedBlockPlugin',
23
- plugin: params => createPlugin(config, params, syncBlockStore)
24
+ plugin: params => createPlugin(config, params, syncBlockStore, api)
24
25
  }];
25
26
  },
26
27
  pluginsOptions: {
@@ -38,7 +39,7 @@ export const syncedBlockPlugin = ({
38
39
  return createSyncedBlock(state);
39
40
  }
40
41
  }],
41
- floatingToolbar: getToolbarConfig()
42
+ floatingToolbar: (state, intl, providerFactory) => getToolbarConfig(state, intl, config, providerFactory)
42
43
  }
43
44
  };
44
45
  };
@@ -0,0 +1,28 @@
1
+ import React from 'react';
2
+ export const SyncBlockEditorWrapperDataId = 'sync-block-plugin-editor-wrapper';
3
+ const SyncBlockEditorWrapperComponent = ({
4
+ defaultDocument,
5
+ getSyncedBlockEditor,
6
+ popupsBoundariesElement,
7
+ popupsMountPoint,
8
+ setInnerEditorView,
9
+ handleContentChanges
10
+ }) => {
11
+ return (
12
+ /*#__PURE__*/
13
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop, @atlaskit/design-system/ensure-design-token-usage
14
+ React.createElement("div", {
15
+ "data-testid": SyncBlockEditorWrapperDataId,
16
+ style: {
17
+ border: 'purple solid 1px'
18
+ }
19
+ }, getSyncedBlockEditor({
20
+ popupsBoundariesElement,
21
+ defaultDocument,
22
+ popupsMountPoint,
23
+ onChange: value => handleContentChanges(value.state.doc),
24
+ onEditorReady: value => setInnerEditorView(value.editorView)
25
+ }))
26
+ );
27
+ };
28
+ export const SyncBlockEditorWrapper = /*#__PURE__*/React.memo(SyncBlockEditorWrapperComponent);
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ const SyncBlockRendererWrapperDataId = 'sync-block-plugin-renderer-wrapper';
3
+ const SyncBlockRendererWrapperComponent = ({
4
+ getSyncedBlockRenderer,
5
+ docNode
6
+ }) => {
7
+ return (
8
+ /*#__PURE__*/
9
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop, @atlaskit/design-system/ensure-design-token-usage
10
+ React.createElement("div", {
11
+ "data-testid": SyncBlockRendererWrapperDataId,
12
+ style: {
13
+ border: 'blue solid 1px'
14
+ }
15
+ }, getSyncedBlockRenderer({
16
+ docNode
17
+ }))
18
+ );
19
+ };
20
+ export const SyncBlockRendererWrapper = /*#__PURE__*/React.memo(SyncBlockRendererWrapperComponent);
@@ -1,3 +1,57 @@
1
- export const getToolbarConfig = () => (_state, _intl) => {
2
- return undefined;
1
+ import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils';
2
+ import CopyIcon from '@atlaskit/icon/core/copy';
3
+ import LinkExternalIcon from '@atlaskit/icon/core/link-external';
4
+ import { copySyncedBlockReferenceToClipboard } from '../pm-plugins/actions';
5
+ import { findSyncBlock } from '../pm-plugins/utils/utils';
6
+ export const getToolbarConfig = (state, _intl, _options = {}, _providerFactory) => {
7
+ const syncBlockObject = findSyncBlock(state);
8
+ if (!syncBlockObject) {
9
+ return;
10
+ }
11
+ const nodeType = state.schema.nodes.syncBlock;
12
+ const items = [];
13
+ const copyButton = {
14
+ id: 'editor.syncedBlock.copy',
15
+ type: 'button',
16
+ appearance: 'subtle',
17
+ icon: CopyIcon,
18
+ title: 'Copy',
19
+ showTitle: true,
20
+ tooltipContent: 'Copy reference to clipboard',
21
+ onClick: copySyncedBlockReferenceToClipboard
22
+ };
23
+ items.push(copyButton);
24
+ if (syncBlockObject.node.attrs.resourceId !== syncBlockObject.node.attrs.localId) {
25
+ const editSourceButton = {
26
+ id: 'editor.syncedBlock.editSource',
27
+ type: 'button',
28
+ appearance: 'subtle',
29
+ icon: LinkExternalIcon,
30
+ title: 'Edit source',
31
+ showTitle: true,
32
+ tooltipContent: 'Navigate to source page of the sync block',
33
+ disabled: true,
34
+ onClick: (_state, _dispatch, view) => {
35
+ if (!view) {
36
+ return false;
37
+ }
38
+ // to be implemented in a follow up PR
39
+ return true;
40
+ }
41
+ };
42
+ items.push(editSourceButton);
43
+ }
44
+ const getDomRef = editorView => {
45
+ const domAtPos = editorView.domAtPos.bind(editorView);
46
+ const element = findDomRefAtPos(syncBlockObject.pos, domAtPos);
47
+ return element;
48
+ };
49
+ return {
50
+ title: 'Synced Block floating controls',
51
+ getDomRef,
52
+ nodeType,
53
+ items,
54
+ scrollable: true,
55
+ groupLabel: 'Synced blocks'
56
+ };
3
57
  };
@@ -4,97 +4,108 @@ import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstruct
4
4
  import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
5
5
  import _get from "@babel/runtime/helpers/get";
6
6
  import _inherits from "@babel/runtime/helpers/inherits";
7
- import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
8
7
  function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
9
8
  function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
10
9
  function _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && "function" == typeof p ? function (t) { return p.apply(e, t); } : p; }
11
- /* eslint-disable @atlaskit/ui-styling-standard/enforce-style-prop */
12
- import React, { useMemo, useRef, useState } from 'react';
10
+ import React from 'react';
13
11
  import ReactNodeView from '@atlaskit/editor-common/react-node-view';
14
- export var defaultSyncBlockDocument = {
12
+ import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
13
+ import { SyncBlockEditorWrapper, SyncBlockEditorWrapperDataId } from '../ui/SyncBlockEditorWrapper';
14
+ import { SyncBlockRendererWrapper } from '../ui/SyncBlockRendererWrapper';
15
+ var defaultSyncBlockEditorDocument = {
15
16
  version: 1,
16
17
  type: 'doc',
17
18
  content: [{
18
19
  type: 'paragraph',
19
20
  content: [{
20
21
  type: 'text',
21
- text: 'This is a synced block. Edit the source to update the content.'
22
+ text: 'This is a source sync block. Edit me to update the content.'
22
23
  }]
23
24
  }]
24
25
  };
25
- var SyncBlockEditorWrapperDataId = 'sync-block-plugin-editor-wrapper';
26
- export var SyncBlockPluginComponent = function SyncBlockPluginComponent(_ref) {
27
- var config = _ref.config,
28
- dom = _ref.dom;
29
- var innerEditorView = useRef(null);
30
-
31
- /* Tmp solution to demonstrate the synced block renderer */
32
- var _useState = useState(defaultSyncBlockDocument),
33
- _useState2 = _slicedToArray(_useState, 2),
34
- rendererDocument = _useState2[0],
35
- setRendererDocument = _useState2[1];
36
- var onChange = function onChange(editorView, _meta) {
37
- var content = editorView.state.doc.toJSON().content;
38
- var rendererDocument = {
39
- version: 1,
40
- type: 'doc',
41
- content: content
42
- };
43
- setRendererDocument(rendererDocument);
44
- };
45
- var onEditorReady = function onEditorReady(_ref2) {
46
- var editorView = _ref2.editorView;
47
- innerEditorView.current = editorView || null;
48
- };
49
- var boundariesElement = useMemo(function () {
50
- // eslint-disable-next-line @atlaskit/editor/no-as-casting
51
- return dom.closest('.fabric-editor-popup-scroll-parent');
52
- }, [dom]);
53
- if (!boundariesElement || !(boundariesElement instanceof HTMLElement)) {
54
- return null;
55
- }
56
- if (!(config !== null && config !== void 0 && config.getSyncedBlockEditor) || !(config !== null && config !== void 0 && config.getSyncedBlockRenderer)) {
57
- return null;
58
- }
59
- return /*#__PURE__*/React.createElement("div", {
60
- "data-testid": SyncBlockEditorWrapperDataId
61
- }, config.getSyncedBlockEditor({
62
- boundariesElement: boundariesElement,
63
- defaultDocument: defaultSyncBlockDocument,
64
- mountPoint: dom,
65
- onChange: onChange,
66
- onEditorReady: onEditorReady
67
- }), /*#__PURE__*/React.createElement("div", {
68
- style: {
69
- width: '100%',
70
- height: '1px',
71
- // eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage
72
- backgroundColor: 'purple'
73
- }
74
- }), config.getSyncedBlockRenderer({
75
- docNode: rendererDocument
76
- }));
26
+ var defaultSyncBlockRendererDocument = {
27
+ version: 1,
28
+ type: 'doc',
29
+ content: [{
30
+ type: 'paragraph',
31
+ content: [{
32
+ type: 'text',
33
+ text: 'This is a reference sync block. Stay tuned for updates...'
34
+ }]
35
+ }]
77
36
  };
78
37
  var SyncBlock = /*#__PURE__*/function (_ReactNodeView) {
79
- function SyncBlock() {
38
+ function SyncBlock(props) {
39
+ var _this;
80
40
  _classCallCheck(this, SyncBlock);
81
- return _callSuper(this, SyncBlock, arguments);
41
+ _this = _callSuper(this, SyncBlock, [props.node, props.view, props.getPos, props.portalProviderAPI, props.eventDispatcher, props]);
42
+ var _props$node$attrs = props.node.attrs,
43
+ resourceId = _props$node$attrs.resourceId,
44
+ localId = _props$node$attrs.localId;
45
+ // Temporary solution to identify the source
46
+ _this.isSource = resourceId === localId;
47
+ _this.options = props.options;
48
+ return _this;
82
49
  }
83
50
  _inherits(SyncBlock, _ReactNodeView);
84
51
  return _createClass(SyncBlock, [{
85
52
  key: "createDomRef",
86
53
  value: function createDomRef() {
87
54
  var domRef = document.createElement('div');
88
- domRef.setAttribute('style', 'border: purple solid 1px;');
89
55
  return domRef;
90
56
  }
57
+ }, {
58
+ key: "handleContentChanges",
59
+ value: function handleContentChanges(_updatedDoc) {
60
+ // write data
61
+ }
62
+ }, {
63
+ key: "setInnerEditorView",
64
+ value: function setInnerEditorView(_editorView) {
65
+ // set inner editor view
66
+ }
67
+ }, {
68
+ key: "renderEditor",
69
+ value: function renderEditor() {
70
+ var _this$options, _this$options2;
71
+ var popupsBoundariesElement = this.dom.closest('.fabric-editor-popup-scroll-parent');
72
+ if (!(popupsBoundariesElement instanceof HTMLElement)) {
73
+ return null;
74
+ }
75
+ if (!((_this$options = this.options) !== null && _this$options !== void 0 && _this$options.getSyncedBlockEditor)) {
76
+ return null;
77
+ }
78
+ return /*#__PURE__*/React.createElement(SyncBlockEditorWrapper, {
79
+ popupsBoundariesElement: popupsBoundariesElement,
80
+ popupsMountPoint: this.dom,
81
+ defaultDocument: defaultSyncBlockEditorDocument,
82
+ handleContentChanges: this.handleContentChanges,
83
+ setInnerEditorView: this.setInnerEditorView,
84
+ getSyncedBlockEditor: (_this$options2 = this.options) === null || _this$options2 === void 0 ? void 0 : _this$options2.getSyncedBlockEditor
85
+ });
86
+ }
87
+ }, {
88
+ key: "renderRenderer",
89
+ value: function renderRenderer() {
90
+ var _this$options3, _this$options4;
91
+ if (!((_this$options3 = this.options) !== null && _this$options3 !== void 0 && _this$options3.getSyncedBlockRenderer)) {
92
+ return null;
93
+ }
94
+
95
+ // get document node from data provider
96
+ var docNode = defaultSyncBlockRendererDocument;
97
+ return /*#__PURE__*/React.createElement(SyncBlockRendererWrapper, {
98
+ docNode: docNode,
99
+ getSyncedBlockRenderer: (_this$options4 = this.options) === null || _this$options4 === void 0 ? void 0 : _this$options4.getSyncedBlockRenderer
100
+ });
101
+ }
91
102
  }, {
92
103
  key: "render",
93
104
  value: function render() {
94
- return /*#__PURE__*/React.createElement(SyncBlockPluginComponent, {
95
- config: this.reactComponentProps.config,
96
- dom: this.dom
97
- });
105
+ if (this.isSource) {
106
+ return this.renderEditor();
107
+ }
108
+ return this.renderRenderer();
98
109
  }
99
110
  }, {
100
111
  key: "stopEvent",
@@ -104,7 +115,17 @@ var SyncBlock = /*#__PURE__*/function (_ReactNodeView) {
104
115
  if (!target) {
105
116
  return false;
106
117
  }
107
- return ((_target$closest = target.closest) === null || _target$closest === void 0 ? void 0 : _target$closest.call(target, "[data-testid=\"".concat(SyncBlockEditorWrapperDataId, "\"]"))) != null;
118
+ var isInNestedEditor = ((_target$closest = target.closest) === null || _target$closest === void 0 ? void 0 : _target$closest.call(target, "[data-testid=\"".concat(SyncBlockEditorWrapperDataId, "\"]"))) != null;
119
+ if (isInNestedEditor) {
120
+ this.selectNode();
121
+ return true;
122
+ }
123
+ return false;
124
+ }
125
+ }, {
126
+ key: "selectNode",
127
+ value: function selectNode() {
128
+ this.selectSyncBlockNode(undefined);
108
129
  }
109
130
  }, {
110
131
  key: "destroy",
@@ -113,17 +134,40 @@ var SyncBlock = /*#__PURE__*/function (_ReactNodeView) {
113
134
  (_this$unsubscribe = this.unsubscribe) === null || _this$unsubscribe === void 0 || _this$unsubscribe.call(this);
114
135
  _superPropGet(SyncBlock, "destroy", this, 3)([]);
115
136
  }
137
+ }, {
138
+ key: "selectSyncBlockNode",
139
+ value: function selectSyncBlockNode(relativeSelectionPos) {
140
+ var _this$reactComponentP;
141
+ var getPos = typeof this.getPos === 'function' ? this.getPos() : 0;
142
+ var selectionAPI = (_this$reactComponentP = this.reactComponentProps.api) === null || _this$reactComponentP === void 0 || (_this$reactComponentP = _this$reactComponentP.selection) === null || _this$reactComponentP === void 0 ? void 0 : _this$reactComponentP.actions;
143
+ if (!selectionAPI) {
144
+ return;
145
+ }
146
+ var tr = selectionAPI.selectNearNode({
147
+ selectionRelativeToNode: relativeSelectionPos,
148
+ selection: NodeSelection.create(this.view.state.doc, getPos !== null && getPos !== void 0 ? getPos : 0)
149
+ })(this.view.state);
150
+ if (tr) {
151
+ this.view.dispatch(tr);
152
+ }
153
+ }
116
154
  }]);
117
155
  }(ReactNodeView);
118
- export var syncBlockNodeView = function syncBlockNodeView(_ref3) {
119
- var config = _ref3.config,
120
- pmPluginFactoryParams = _ref3.pmPluginFactoryParams;
156
+ export var syncBlockNodeView = function syncBlockNodeView(_ref) {
157
+ var options = _ref.options,
158
+ pmPluginFactoryParams = _ref.pmPluginFactoryParams,
159
+ api = _ref.api;
121
160
  return function (node, view, getPos) {
122
161
  var portalProviderAPI = pmPluginFactoryParams.portalProviderAPI,
123
162
  eventDispatcher = pmPluginFactoryParams.eventDispatcher;
124
- var reactComponentProps = {
125
- config: config
126
- };
127
- return new SyncBlock(node, view, getPos, portalProviderAPI, eventDispatcher, reactComponentProps, undefined).init();
163
+ return new SyncBlock({
164
+ api: api,
165
+ options: options,
166
+ node: node,
167
+ view: view,
168
+ getPos: getPos,
169
+ portalProviderAPI: portalProviderAPI,
170
+ eventDispatcher: eventDispatcher
171
+ }).init();
128
172
  };
129
173
  };