@atlaskit/editor-plugin-synced-block 3.3.6 → 3.4.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/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @atlaskit/editor-plugin-synced-block
2
2
 
3
+ ## 3.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`218e1d54178bb`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/218e1d54178bb) -
8
+ Pre-fetch URL to source blocks
9
+
10
+ ### Patch Changes
11
+
12
+ - Updated dependencies
13
+
3
14
  ## 3.3.6
4
15
 
5
16
  ### Patch Changes
@@ -28,6 +28,9 @@
28
28
  {
29
29
  "path": "../../editor-json-transformer/afm-cc/tsconfig.json"
30
30
  },
31
+ {
32
+ "path": "../../editor-plugin-analytics/afm-cc/tsconfig.json"
33
+ },
31
34
  {
32
35
  "path": "../../editor-plugin-block-menu/afm-cc/tsconfig.json"
33
36
  },
@@ -28,6 +28,9 @@
28
28
  {
29
29
  "path": "../../editor-json-transformer/afm-dev-agents/tsconfig.json"
30
30
  },
31
+ {
32
+ "path": "../../editor-plugin-analytics/afm-dev-agents/tsconfig.json"
33
+ },
31
34
  {
32
35
  "path": "../../editor-plugin-block-menu/afm-dev-agents/tsconfig.json"
33
36
  },
@@ -28,6 +28,9 @@
28
28
  {
29
29
  "path": "../../editor-json-transformer/afm-jira/tsconfig.json"
30
30
  },
31
+ {
32
+ "path": "../../editor-plugin-analytics/afm-jira/tsconfig.json"
33
+ },
31
34
  {
32
35
  "path": "../../editor-plugin-block-menu/afm-jira/tsconfig.json"
33
36
  },
@@ -28,6 +28,9 @@
28
28
  {
29
29
  "path": "../../editor-json-transformer/afm-passionfruit/tsconfig.json"
30
30
  },
31
+ {
32
+ "path": "../../editor-plugin-analytics/afm-passionfruit/tsconfig.json"
33
+ },
31
34
  {
32
35
  "path": "../../editor-plugin-block-menu/afm-passionfruit/tsconfig.json"
33
36
  },
@@ -28,6 +28,9 @@
28
28
  {
29
29
  "path": "../../editor-json-transformer/afm-post-office/tsconfig.json"
30
30
  },
31
+ {
32
+ "path": "../../editor-plugin-analytics/afm-post-office/tsconfig.json"
33
+ },
31
34
  {
32
35
  "path": "../../editor-plugin-block-menu/afm-post-office/tsconfig.json"
33
36
  },
@@ -28,6 +28,9 @@
28
28
  {
29
29
  "path": "../../editor-json-transformer/afm-rovo-extension/tsconfig.json"
30
30
  },
31
+ {
32
+ "path": "../../editor-plugin-analytics/afm-rovo-extension/tsconfig.json"
33
+ },
31
34
  {
32
35
  "path": "../../editor-plugin-block-menu/afm-rovo-extension/tsconfig.json"
33
36
  },
@@ -28,6 +28,9 @@
28
28
  {
29
29
  "path": "../../editor-json-transformer/afm-townsquare/tsconfig.json"
30
30
  },
31
+ {
32
+ "path": "../../editor-plugin-analytics/afm-townsquare/tsconfig.json"
33
+ },
31
34
  {
32
35
  "path": "../../editor-plugin-block-menu/afm-townsquare/tsconfig.json"
33
36
  },
@@ -50,6 +50,7 @@ var SyncBlock = /*#__PURE__*/function (_ReactNodeView) {
50
50
  _this = _callSuper(this, SyncBlock, [props.node, props.view, props.getPos, props.portalProviderAPI, props.eventDispatcher, props]);
51
51
  _this.options = props.options;
52
52
  _this.syncBlockStore = props.syncBlockStore;
53
+ _this.syncBlockStore.updateSyncBlockNode(_this.node);
53
54
  return _this;
54
55
  }
55
56
  (0, _inherits2.default)(SyncBlock, _ReactNodeView);
@@ -8,7 +8,6 @@ exports.removeSyncedBlock = exports.editSyncedBlockSource = exports.createSynced
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _analytics = require("@atlaskit/editor-common/analytics");
10
10
  var _utils = require("@atlaskit/editor-prosemirror/utils");
11
- var _editorSyncedBlockProvider = require("@atlaskit/editor-synced-block-provider");
12
11
  var _utils2 = require("./utils/utils");
13
12
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
14
13
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -73,17 +72,31 @@ var copySyncedBlockReferenceToClipboard = exports.copySyncedBlockReferenceToClip
73
72
  return true;
74
73
  };
75
74
  };
76
- var editSyncedBlockSource = exports.editSyncedBlockSource = function editSyncedBlockSource(_api) {
77
- return function (state, _dispatch, _view) {
75
+ var editSyncedBlockSource = exports.editSyncedBlockSource = function editSyncedBlockSource(syncBlockStore, api) {
76
+ return function (state, dispatch, _view) {
77
+ var _syncBlock$node;
78
78
  var syncBlock = (0, _utils2.findSyncBlock)(state);
79
- if (!syncBlock) {
79
+ var resourceId = syncBlock === null || syncBlock === void 0 || (_syncBlock$node = syncBlock.node) === null || _syncBlock$node === void 0 || (_syncBlock$node = _syncBlock$node.attrs) === null || _syncBlock$node === void 0 ? void 0 : _syncBlock$node.resourceId;
80
+ if (!resourceId) {
80
81
  return false;
81
82
  }
82
- var url = (0, _editorSyncedBlockProvider.generateSyncBlockSourceUrl)(syncBlock.node);
83
- if (!url) {
84
- return false;
83
+ var syncBlockURL = syncBlockStore.getSyncBlockURL(resourceId);
84
+ if (syncBlockURL) {
85
+ window.open(syncBlockURL, '_blank');
86
+ } else {
87
+ var _api$analytics;
88
+ var tr = state.tr;
89
+ api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || (_api$analytics = _api$analytics.actions) === null || _api$analytics === void 0 || _api$analytics.attachAnalyticsEvent({
90
+ eventType: _analytics.EVENT_TYPE.OPERATIONAL,
91
+ action: _analytics.ACTION.ERROR,
92
+ actionSubject: _analytics.ACTION_SUBJECT.SYNCED_BLOCK,
93
+ actionSubjectId: _analytics.ACTION_SUBJECT_ID.SYNCED_BLOCK_SOURCE_URL,
94
+ attributes: {
95
+ error: 'No URL resolved for synced block'
96
+ }
97
+ })(tr);
98
+ dispatch === null || dispatch === void 0 || dispatch(tr);
85
99
  }
86
- window.open(url, '_blank');
87
100
  return true;
88
101
  };
89
102
  };
@@ -56,12 +56,13 @@ var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig(stat
56
56
  var editSourceButton = _objectSpread({
57
57
  id: 'editor.syncedBlock.editSource',
58
58
  type: 'button',
59
+ disabled: !syncBlockStore.getSyncBlockURL(syncBlockObject.node.attrs.resourceId),
59
60
  appearance: 'subtle',
60
61
  icon: _linkExternal.default,
61
62
  title: formatMessage(_messages.syncBlockMessages.editSourceLabel),
62
63
  showTitle: true,
63
64
  tooltipContent: formatMessage(_messages.syncBlockMessages.editSourceTooltip),
64
- onClick: (0, _actions.editSyncedBlockSource)(api)
65
+ onClick: (0, _actions.editSyncedBlockSource)(syncBlockStore, api)
65
66
  }, hoverDecorationProps(nodeType, _consts.akEditorSelectedNodeClassName));
66
67
  items.push(editSourceButton);
67
68
  }
@@ -32,6 +32,7 @@ class SyncBlock extends ReactNodeView {
32
32
  super(props.node, props.view, props.getPos, props.portalProviderAPI, props.eventDispatcher, props);
33
33
  this.options = props.options;
34
34
  this.syncBlockStore = props.syncBlockStore;
35
+ this.syncBlockStore.updateSyncBlockNode(this.node);
35
36
  }
36
37
  createDomRef() {
37
38
  const domRef = document.createElement('div');
@@ -1,6 +1,5 @@
1
- import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
1
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
2
2
  import { safeInsert } from '@atlaskit/editor-prosemirror/utils';
3
- import { generateSyncBlockSourceUrl } from '@atlaskit/editor-synced-block-provider';
4
3
  import { canBeConvertedToSyncBlock, findSyncBlock } from './utils/utils';
5
4
  export const createSyncedBlock = ({
6
5
  tr,
@@ -75,16 +74,30 @@ export const copySyncedBlockReferenceToClipboard = api => (state, dispatch, _vie
75
74
  dispatch(newTr);
76
75
  return true;
77
76
  };
78
- export const editSyncedBlockSource = _api => (state, _dispatch, _view) => {
77
+ export const editSyncedBlockSource = (syncBlockStore, api) => (state, dispatch, _view) => {
78
+ var _syncBlock$node, _syncBlock$node$attrs;
79
79
  const syncBlock = findSyncBlock(state);
80
- if (!syncBlock) {
80
+ const resourceId = syncBlock === null || syncBlock === void 0 ? void 0 : (_syncBlock$node = syncBlock.node) === null || _syncBlock$node === void 0 ? void 0 : (_syncBlock$node$attrs = _syncBlock$node.attrs) === null || _syncBlock$node$attrs === void 0 ? void 0 : _syncBlock$node$attrs.resourceId;
81
+ if (!resourceId) {
81
82
  return false;
82
83
  }
83
- const url = generateSyncBlockSourceUrl(syncBlock.node);
84
- if (!url) {
85
- return false;
84
+ const syncBlockURL = syncBlockStore.getSyncBlockURL(resourceId);
85
+ if (syncBlockURL) {
86
+ window.open(syncBlockURL, '_blank');
87
+ } else {
88
+ var _api$analytics, _api$analytics$action;
89
+ const tr = state.tr;
90
+ api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : (_api$analytics$action = _api$analytics.actions) === null || _api$analytics$action === void 0 ? void 0 : _api$analytics$action.attachAnalyticsEvent({
91
+ eventType: EVENT_TYPE.OPERATIONAL,
92
+ action: ACTION.ERROR,
93
+ actionSubject: ACTION_SUBJECT.SYNCED_BLOCK,
94
+ actionSubjectId: ACTION_SUBJECT_ID.SYNCED_BLOCK_SOURCE_URL,
95
+ attributes: {
96
+ error: 'No URL resolved for synced block'
97
+ }
98
+ })(tr);
99
+ dispatch === null || dispatch === void 0 ? void 0 : dispatch(tr);
86
100
  }
87
- window.open(url, '_blank');
88
101
  return true;
89
102
  };
90
103
  export const removeSyncedBlock = api => (state, dispatch, _view) => {
@@ -41,12 +41,13 @@ export const getToolbarConfig = (state, intl, _options = {}, _providerFactory, a
41
41
  const editSourceButton = {
42
42
  id: 'editor.syncedBlock.editSource',
43
43
  type: 'button',
44
+ disabled: !syncBlockStore.getSyncBlockURL(syncBlockObject.node.attrs.resourceId),
44
45
  appearance: 'subtle',
45
46
  icon: LinkExternalIcon,
46
47
  title: formatMessage(messages.editSourceLabel),
47
48
  showTitle: true,
48
49
  tooltipContent: formatMessage(messages.editSourceTooltip),
49
- onClick: editSyncedBlockSource(api),
50
+ onClick: editSyncedBlockSource(syncBlockStore, api),
50
51
  ...hoverDecorationProps(nodeType, akEditorSelectedNodeClassName)
51
52
  };
52
53
  items.push(editSourceButton);
@@ -43,6 +43,7 @@ var SyncBlock = /*#__PURE__*/function (_ReactNodeView) {
43
43
  _this = _callSuper(this, SyncBlock, [props.node, props.view, props.getPos, props.portalProviderAPI, props.eventDispatcher, props]);
44
44
  _this.options = props.options;
45
45
  _this.syncBlockStore = props.syncBlockStore;
46
+ _this.syncBlockStore.updateSyncBlockNode(_this.node);
46
47
  return _this;
47
48
  }
48
49
  _inherits(SyncBlock, _ReactNodeView);
@@ -1,9 +1,8 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
3
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
- import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
4
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
5
5
  import { safeInsert } from '@atlaskit/editor-prosemirror/utils';
6
- import { generateSyncBlockSourceUrl } from '@atlaskit/editor-synced-block-provider';
7
6
  import { canBeConvertedToSyncBlock, findSyncBlock } from './utils/utils';
8
7
  export var createSyncedBlock = function createSyncedBlock(_ref) {
9
8
  var tr = _ref.tr,
@@ -66,17 +65,31 @@ export var copySyncedBlockReferenceToClipboard = function copySyncedBlockReferen
66
65
  return true;
67
66
  };
68
67
  };
69
- export var editSyncedBlockSource = function editSyncedBlockSource(_api) {
70
- return function (state, _dispatch, _view) {
68
+ export var editSyncedBlockSource = function editSyncedBlockSource(syncBlockStore, api) {
69
+ return function (state, dispatch, _view) {
70
+ var _syncBlock$node;
71
71
  var syncBlock = findSyncBlock(state);
72
- if (!syncBlock) {
72
+ var resourceId = syncBlock === null || syncBlock === void 0 || (_syncBlock$node = syncBlock.node) === null || _syncBlock$node === void 0 || (_syncBlock$node = _syncBlock$node.attrs) === null || _syncBlock$node === void 0 ? void 0 : _syncBlock$node.resourceId;
73
+ if (!resourceId) {
73
74
  return false;
74
75
  }
75
- var url = generateSyncBlockSourceUrl(syncBlock.node);
76
- if (!url) {
77
- return false;
76
+ var syncBlockURL = syncBlockStore.getSyncBlockURL(resourceId);
77
+ if (syncBlockURL) {
78
+ window.open(syncBlockURL, '_blank');
79
+ } else {
80
+ var _api$analytics;
81
+ var tr = state.tr;
82
+ api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || (_api$analytics = _api$analytics.actions) === null || _api$analytics === void 0 || _api$analytics.attachAnalyticsEvent({
83
+ eventType: EVENT_TYPE.OPERATIONAL,
84
+ action: ACTION.ERROR,
85
+ actionSubject: ACTION_SUBJECT.SYNCED_BLOCK,
86
+ actionSubjectId: ACTION_SUBJECT_ID.SYNCED_BLOCK_SOURCE_URL,
87
+ attributes: {
88
+ error: 'No URL resolved for synced block'
89
+ }
90
+ })(tr);
91
+ dispatch === null || dispatch === void 0 || dispatch(tr);
78
92
  }
79
- window.open(url, '_blank');
80
93
  return true;
81
94
  };
82
95
  };
@@ -47,12 +47,13 @@ export var getToolbarConfig = function getToolbarConfig(state, intl) {
47
47
  var editSourceButton = _objectSpread({
48
48
  id: 'editor.syncedBlock.editSource',
49
49
  type: 'button',
50
+ disabled: !syncBlockStore.getSyncBlockURL(syncBlockObject.node.attrs.resourceId),
50
51
  appearance: 'subtle',
51
52
  icon: LinkExternalIcon,
52
53
  title: formatMessage(messages.editSourceLabel),
53
54
  showTitle: true,
54
55
  tooltipContent: formatMessage(messages.editSourceTooltip),
55
- onClick: editSyncedBlockSource(api)
56
+ onClick: editSyncedBlockSource(syncBlockStore, api)
56
57
  }, hoverDecorationProps(nodeType, akEditorSelectedNodeClassName));
57
58
  items.push(editSourceButton);
58
59
  }
@@ -10,6 +10,6 @@ type createSyncedBlockProps = {
10
10
  };
11
11
  export declare const createSyncedBlock: ({ tr, syncBlockStore, typeAheadInsert, }: createSyncedBlockProps) => false | Transaction;
12
12
  export declare const copySyncedBlockReferenceToClipboard: (api?: ExtractInjectionAPI<SyncedBlockPlugin>) => Command;
13
- export declare const editSyncedBlockSource: (_api?: ExtractInjectionAPI<SyncedBlockPlugin>) => Command;
13
+ export declare const editSyncedBlockSource: (syncBlockStore: SyncBlockStoreManager, api?: ExtractInjectionAPI<SyncedBlockPlugin>) => Command;
14
14
  export declare const removeSyncedBlock: (api?: ExtractInjectionAPI<SyncedBlockPlugin>) => Command;
15
15
  export {};
@@ -2,6 +2,7 @@ import type { DocNode } from '@atlaskit/adf-schema';
2
2
  import type { EventDispatcher } from '@atlaskit/editor-common/event-dispatcher';
3
3
  import type { EditorCommand, NextEditorPlugin, OptionalPlugin } from '@atlaskit/editor-common/types';
4
4
  import type { JSONDocNode } from '@atlaskit/editor-json-transformer';
5
+ import type { AnalyticsPlugin } from '@atlaskit/editor-plugin-analytics';
5
6
  import type { BlockMenuPlugin } from '@atlaskit/editor-plugin-block-menu';
6
7
  import type { DecorationsPlugin } from '@atlaskit/editor-plugin-decorations';
7
8
  import type { FloatingToolbarPlugin } from '@atlaskit/editor-plugin-floating-toolbar';
@@ -46,7 +47,8 @@ export type SyncedBlockPlugin = NextEditorPlugin<'syncedBlock', {
46
47
  SelectionPlugin,
47
48
  FloatingToolbarPlugin,
48
49
  DecorationsPlugin,
49
- OptionalPlugin<BlockMenuPlugin>
50
+ OptionalPlugin<BlockMenuPlugin>,
51
+ OptionalPlugin<AnalyticsPlugin>
50
52
  ];
51
53
  pluginConfiguration: SyncedBlockPluginOptions | undefined;
52
54
  }>;
@@ -10,6 +10,6 @@ type createSyncedBlockProps = {
10
10
  };
11
11
  export declare const createSyncedBlock: ({ tr, syncBlockStore, typeAheadInsert, }: createSyncedBlockProps) => false | Transaction;
12
12
  export declare const copySyncedBlockReferenceToClipboard: (api?: ExtractInjectionAPI<SyncedBlockPlugin>) => Command;
13
- export declare const editSyncedBlockSource: (_api?: ExtractInjectionAPI<SyncedBlockPlugin>) => Command;
13
+ export declare const editSyncedBlockSource: (syncBlockStore: SyncBlockStoreManager, api?: ExtractInjectionAPI<SyncedBlockPlugin>) => Command;
14
14
  export declare const removeSyncedBlock: (api?: ExtractInjectionAPI<SyncedBlockPlugin>) => Command;
15
15
  export {};
@@ -2,6 +2,7 @@ import type { DocNode } from '@atlaskit/adf-schema';
2
2
  import type { EventDispatcher } from '@atlaskit/editor-common/event-dispatcher';
3
3
  import type { EditorCommand, NextEditorPlugin, OptionalPlugin } from '@atlaskit/editor-common/types';
4
4
  import type { JSONDocNode } from '@atlaskit/editor-json-transformer';
5
+ import type { AnalyticsPlugin } from '@atlaskit/editor-plugin-analytics';
5
6
  import type { BlockMenuPlugin } from '@atlaskit/editor-plugin-block-menu';
6
7
  import type { DecorationsPlugin } from '@atlaskit/editor-plugin-decorations';
7
8
  import type { FloatingToolbarPlugin } from '@atlaskit/editor-plugin-floating-toolbar';
@@ -46,7 +47,8 @@ export type SyncedBlockPlugin = NextEditorPlugin<'syncedBlock', {
46
47
  SelectionPlugin,
47
48
  FloatingToolbarPlugin,
48
49
  DecorationsPlugin,
49
- OptionalPlugin<BlockMenuPlugin>
50
+ OptionalPlugin<BlockMenuPlugin>,
51
+ OptionalPlugin<AnalyticsPlugin>
50
52
  ];
51
53
  pluginConfiguration: SyncedBlockPluginOptions | undefined;
52
54
  }>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-synced-block",
3
- "version": "3.3.6",
3
+ "version": "3.4.0",
4
4
  "description": "SyncedBlock plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -31,13 +31,14 @@
31
31
  "@atlaskit/adf-schema": "^51.2.0",
32
32
  "@atlaskit/button": "23.5.1",
33
33
  "@atlaskit/editor-json-transformer": "^8.30.0",
34
+ "@atlaskit/editor-plugin-analytics": "^6.1.0",
34
35
  "@atlaskit/editor-plugin-block-menu": "^4.0.0",
35
36
  "@atlaskit/editor-plugin-decorations": "^6.1.0",
36
37
  "@atlaskit/editor-plugin-floating-toolbar": "^8.2.0",
37
38
  "@atlaskit/editor-plugin-selection": "^6.1.0",
38
39
  "@atlaskit/editor-prosemirror": "7.0.0",
39
40
  "@atlaskit/editor-shared-styles": "^3.7.0",
40
- "@atlaskit/editor-synced-block-provider": "^0.5.0",
41
+ "@atlaskit/editor-synced-block-provider": "^0.6.0",
41
42
  "@atlaskit/editor-tables": "^2.9.0",
42
43
  "@atlaskit/editor-toolbar": "^0.15.0",
43
44
  "@atlaskit/icon": "28.5.1",
@@ -46,7 +47,7 @@
46
47
  "react-intl-next": "npm:react-intl@^5.18.1"
47
48
  },
48
49
  "peerDependencies": {
49
- "@atlaskit/editor-common": "^110.12.0",
50
+ "@atlaskit/editor-common": "^110.13.0",
50
51
  "react": "^18.2.0"
51
52
  },
52
53
  "devDependencies": {