@atlaskit/editor-plugin-synced-block 5.1.0 → 5.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.
- package/CHANGELOG.md +8 -0
- package/dist/cjs/editor-commands/index.js +7 -1
- package/dist/cjs/pm-plugins/experience-tracking/create-reference-experience.js +113 -0
- package/dist/cjs/pm-plugins/experience-tracking/create-source-experience.js +185 -0
- package/dist/cjs/pm-plugins/experience-tracking/get-experience-tracking-plugins.js +31 -0
- package/dist/cjs/syncedBlockPlugin.js +21 -3
- package/dist/cjs/ui/CreateSyncedBlockButton.js +1 -0
- package/dist/cjs/ui/CreateSyncedBlockDropdownItem.js +1 -0
- package/dist/es2019/editor-commands/index.js +7 -1
- package/dist/es2019/pm-plugins/experience-tracking/create-reference-experience.js +105 -0
- package/dist/es2019/pm-plugins/experience-tracking/create-source-experience.js +179 -0
- package/dist/es2019/pm-plugins/experience-tracking/get-experience-tracking-plugins.js +22 -0
- package/dist/es2019/syncedBlockPlugin.js +21 -3
- package/dist/es2019/ui/CreateSyncedBlockButton.js +1 -0
- package/dist/es2019/ui/CreateSyncedBlockDropdownItem.js +1 -0
- package/dist/esm/editor-commands/index.js +7 -1
- package/dist/esm/pm-plugins/experience-tracking/create-reference-experience.js +106 -0
- package/dist/esm/pm-plugins/experience-tracking/create-source-experience.js +178 -0
- package/dist/esm/pm-plugins/experience-tracking/get-experience-tracking-plugins.js +25 -0
- package/dist/esm/syncedBlockPlugin.js +21 -3
- package/dist/esm/ui/CreateSyncedBlockButton.js +1 -0
- package/dist/esm/ui/CreateSyncedBlockDropdownItem.js +1 -0
- package/dist/types/pm-plugins/experience-tracking/create-reference-experience.d.ts +17 -0
- package/dist/types/pm-plugins/experience-tracking/create-source-experience.d.ts +21 -0
- package/dist/types/pm-plugins/experience-tracking/get-experience-tracking-plugins.d.ts +16 -0
- package/dist/types-ts4.5/pm-plugins/experience-tracking/create-reference-experience.d.ts +17 -0
- package/dist/types-ts4.5/pm-plugins/experience-tracking/create-source-experience.d.ts +21 -0
- package/dist/types-ts4.5/pm-plugins/experience-tracking/get-experience-tracking-plugins.d.ts +16 -0
- package/package.json +6 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-synced-block
|
|
2
2
|
|
|
3
|
+
## 5.1.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`656adaeec9d0b`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/656adaeec9d0b) -
|
|
8
|
+
[ux] EDITOR-1665 add experience tracking for create sync block
|
|
9
|
+
- Updated dependencies
|
|
10
|
+
|
|
3
11
|
## 5.1.0
|
|
4
12
|
|
|
5
13
|
### Minor Changes
|
|
@@ -8,6 +8,7 @@ var _analytics = require("@atlaskit/editor-common/analytics");
|
|
|
8
8
|
var _copyButton = require("@atlaskit/editor-common/copy-button");
|
|
9
9
|
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
10
10
|
var _utils = require("@atlaskit/editor-prosemirror/utils");
|
|
11
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
11
12
|
var _main = require("../pm-plugins/main");
|
|
12
13
|
var _utils2 = require("../pm-plugins/utils/utils");
|
|
13
14
|
var _types = require("../types");
|
|
@@ -39,7 +40,12 @@ var createSyncedBlock = exports.createSyncedBlock = function createSyncedBlock(_
|
|
|
39
40
|
} else {
|
|
40
41
|
var conversionInfo = (0, _utils2.canBeConvertedToSyncBlock)(tr.selection);
|
|
41
42
|
if (!conversionInfo) {
|
|
42
|
-
|
|
43
|
+
if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
|
|
44
|
+
var _syncBlockStore$sourc;
|
|
45
|
+
(_syncBlockStore$sourc = syncBlockStore.sourceManager.createExperience) === null || _syncBlockStore$sourc === void 0 || _syncBlockStore$sourc.failure({
|
|
46
|
+
reason: 'Selection is not allowed to be converted to sync block'
|
|
47
|
+
});
|
|
48
|
+
}
|
|
43
49
|
return false;
|
|
44
50
|
}
|
|
45
51
|
var _attrs = syncBlockStore.sourceManager.generateBodiedSyncBlockAttrs();
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.getCreateReferenceExperiencePlugin = void 0;
|
|
8
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
9
|
+
var _analytics = require("@atlaskit/editor-common/analytics");
|
|
10
|
+
var _experiences = require("@atlaskit/editor-common/experiences");
|
|
11
|
+
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
|
|
12
|
+
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
13
|
+
var isPastedFromFabricEditor = function isPastedFromFabricEditor(html) {
|
|
14
|
+
return !!html && html.indexOf('data-pm-slice="') >= 0;
|
|
15
|
+
};
|
|
16
|
+
var pluginKey = new _state.PluginKey('createReferenceSyncBlockExperience');
|
|
17
|
+
var START_METHOD = {
|
|
18
|
+
PASTE: 'paste'
|
|
19
|
+
};
|
|
20
|
+
var ABORT_REASON = {
|
|
21
|
+
EDITOR_DESTROYED: 'editor-destroyed'
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* This experience tracks when a reference sync block is inserted.
|
|
26
|
+
*
|
|
27
|
+
* Start: When user pastes a sync block from editor and createSyncedBlock is called
|
|
28
|
+
* Success: When the sync block is added to the DOM within 500ms of start
|
|
29
|
+
* Failure: When 500ms passes without the reference sync block being added to the DOM
|
|
30
|
+
*/
|
|
31
|
+
var getCreateReferenceExperiencePlugin = exports.getCreateReferenceExperiencePlugin = function getCreateReferenceExperiencePlugin(_ref) {
|
|
32
|
+
var refs = _ref.refs,
|
|
33
|
+
dispatchAnalyticsEvent = _ref.dispatchAnalyticsEvent;
|
|
34
|
+
var experience = getCreateReferenceExperience({
|
|
35
|
+
refs: refs,
|
|
36
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent
|
|
37
|
+
});
|
|
38
|
+
return new _safePlugin.SafePlugin({
|
|
39
|
+
key: pluginKey,
|
|
40
|
+
view: function view() {
|
|
41
|
+
return {
|
|
42
|
+
destroy: function destroy() {
|
|
43
|
+
experience.abort({
|
|
44
|
+
reason: ABORT_REASON.EDITOR_DESTROYED
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
},
|
|
49
|
+
props: {
|
|
50
|
+
handlePaste: function handlePaste(_view, rawEvent, slice) {
|
|
51
|
+
var _event$clipboardData;
|
|
52
|
+
var event = rawEvent;
|
|
53
|
+
var html = (_event$clipboardData = event.clipboardData) === null || _event$clipboardData === void 0 ? void 0 : _event$clipboardData.getData('text/html');
|
|
54
|
+
|
|
55
|
+
// do not start on paste from renderer, because this flattens the content and does not create a reference block
|
|
56
|
+
if (isPastedFromFabricEditor(html)) {
|
|
57
|
+
slice.content.forEach(function (node) {
|
|
58
|
+
if (node.type.name === 'syncBlock' || node.type.name === 'bodiedSyncBlock') {
|
|
59
|
+
experience.start({
|
|
60
|
+
method: START_METHOD.PASTE
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
var getCreateReferenceExperience = function getCreateReferenceExperience(_ref2) {
|
|
70
|
+
var refs = _ref2.refs,
|
|
71
|
+
dispatchAnalyticsEvent = _ref2.dispatchAnalyticsEvent;
|
|
72
|
+
return new _experiences.Experience(_analytics.ACTION_SUBJECT.SYNCED_BLOCK, {
|
|
73
|
+
actionSubjectId: _analytics.ACTION_SUBJECT_ID.REFERENCE_SYNCED_BLOCK_CREATE,
|
|
74
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
|
|
75
|
+
checks: [new _experiences.ExperienceCheckTimeout({
|
|
76
|
+
durationMs: 500
|
|
77
|
+
}), new _experiences.ExperienceCheckDomMutation({
|
|
78
|
+
onDomMutation: function onDomMutation(_ref3) {
|
|
79
|
+
var mutations = _ref3.mutations;
|
|
80
|
+
if (mutations.some(isReferenceSyncBlockAddedInMutation)) {
|
|
81
|
+
return {
|
|
82
|
+
status: 'success'
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
return undefined;
|
|
86
|
+
},
|
|
87
|
+
observeConfig: function observeConfig() {
|
|
88
|
+
var _refs$containerElemen;
|
|
89
|
+
var proseMirrorElement = (_refs$containerElemen = refs.containerElement) === null || _refs$containerElemen === void 0 ? void 0 : _refs$containerElemen.querySelector('.ProseMirror');
|
|
90
|
+
if (!proseMirrorElement || !(proseMirrorElement instanceof HTMLElement)) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
target: proseMirrorElement,
|
|
95
|
+
options: {
|
|
96
|
+
childList: true
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
})]
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
var isReferenceSyncBlockAddedInMutation = function isReferenceSyncBlockAddedInMutation(_ref4) {
|
|
104
|
+
var type = _ref4.type,
|
|
105
|
+
addedNodes = _ref4.addedNodes;
|
|
106
|
+
return type === 'childList' && (0, _toConsumableArray2.default)(addedNodes).some(isReferenceSyncBlockNode);
|
|
107
|
+
};
|
|
108
|
+
var isReferenceSyncBlockNode = function isReferenceSyncBlockNode(node) {
|
|
109
|
+
if (!(node instanceof HTMLElement)) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
return !!node.querySelector('[data-prosemirror-node-name="syncBlock"]');
|
|
113
|
+
};
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.getCreateSourceExperiencePlugin = void 0;
|
|
8
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
9
|
+
var _bindEventListener = require("bind-event-listener");
|
|
10
|
+
var _analytics = require("@atlaskit/editor-common/analytics");
|
|
11
|
+
var _experiences = require("@atlaskit/editor-common/experiences");
|
|
12
|
+
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
|
|
13
|
+
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
14
|
+
var pluginKey = new _state.PluginKey('createSourceSyncBlockExperience');
|
|
15
|
+
var ABORT_REASON = {
|
|
16
|
+
EDITOR_DESTROYED: 'editor-destroyed'
|
|
17
|
+
};
|
|
18
|
+
var START_METHOD = {
|
|
19
|
+
BLOCK_MENU: 'block-menu',
|
|
20
|
+
PINNED_TOOLBAR: 'pinned-toolbar',
|
|
21
|
+
QUICK_INSERT: 'quick-insert'
|
|
22
|
+
};
|
|
23
|
+
var SYNCED_BLOCK_CREATE_BUTTON_IDS = ['create-synced-block-toolbar-btn', 'create-synced-block-block-menu-btn', 'create-synced-block-quick-insert-btn'];
|
|
24
|
+
var syncedBlockCreateButtonIds = new Set(SYNCED_BLOCK_CREATE_BUTTON_IDS);
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* This experience tracks when a source sync block is inserted.
|
|
28
|
+
*
|
|
29
|
+
* Start: When user inserts a sync block via block menu, quick insert or pinned toolbar
|
|
30
|
+
* Success: When the sync block is added to the DOM within 2000ms of start
|
|
31
|
+
* Failure: When 500ms passes without the source sync block being added to the DOM
|
|
32
|
+
*/
|
|
33
|
+
var getCreateSourceExperiencePlugin = exports.getCreateSourceExperiencePlugin = function getCreateSourceExperiencePlugin(_ref) {
|
|
34
|
+
var refs = _ref.refs,
|
|
35
|
+
dispatchAnalyticsEvent = _ref.dispatchAnalyticsEvent,
|
|
36
|
+
syncBlockStore = _ref.syncBlockStore;
|
|
37
|
+
var popupsTargetEl;
|
|
38
|
+
var editorViewEl;
|
|
39
|
+
var getPopupsTarget = function getPopupsTarget() {
|
|
40
|
+
if (!popupsTargetEl) {
|
|
41
|
+
popupsTargetEl = refs.popupsMountPoint || refs.wrapperElement || (0, _experiences.getPopupContainerFromEditorView)(editorViewEl);
|
|
42
|
+
}
|
|
43
|
+
return popupsTargetEl;
|
|
44
|
+
};
|
|
45
|
+
var experience = getCreateSourceExperience({
|
|
46
|
+
refs: refs,
|
|
47
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
|
|
48
|
+
syncBlockStore: syncBlockStore
|
|
49
|
+
});
|
|
50
|
+
syncBlockStore.sourceManager.setCreateExperience(experience);
|
|
51
|
+
var unbindClickListener = (0, _bindEventListener.bind)(document, {
|
|
52
|
+
type: 'click',
|
|
53
|
+
listener: function listener(event) {
|
|
54
|
+
var target = event.target;
|
|
55
|
+
if (!target) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
var button = target.closest('button[data-testid]');
|
|
59
|
+
if (!button || !(button instanceof HTMLButtonElement)) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
var testId = button.dataset.testid;
|
|
63
|
+
if (!isSyncedBlockCreateButtonId(testId)) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
handleButtonClick(testId, experience);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
var unbindKeydownListener = (0, _bindEventListener.bind)(document, {
|
|
70
|
+
type: 'keydown',
|
|
71
|
+
listener: function listener(event) {
|
|
72
|
+
if (isEnterKey(event.key)) {
|
|
73
|
+
var typeaheadPopup = (0, _experiences.popupWithNestedElement)(getPopupsTarget(), '.fabric-editor-typeahead');
|
|
74
|
+
if (!typeaheadPopup || !(typeaheadPopup instanceof HTMLElement)) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
var firstItem = typeaheadPopup.querySelector('[role="option"]');
|
|
78
|
+
if (!firstItem || !(firstItem instanceof HTMLElement)) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
var testId = firstItem.dataset.testid;
|
|
82
|
+
if (testId === 'create-synced-block-quick-insert-btn') {
|
|
83
|
+
experience.start({
|
|
84
|
+
method: START_METHOD.QUICK_INSERT
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
options: {
|
|
90
|
+
capture: true
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
return new _safePlugin.SafePlugin({
|
|
94
|
+
key: pluginKey,
|
|
95
|
+
view: function view(editorView) {
|
|
96
|
+
editorViewEl = editorView.dom;
|
|
97
|
+
return {
|
|
98
|
+
destroy: function destroy() {
|
|
99
|
+
experience.abort({
|
|
100
|
+
reason: ABORT_REASON.EDITOR_DESTROYED
|
|
101
|
+
});
|
|
102
|
+
unbindClickListener();
|
|
103
|
+
unbindKeydownListener();
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
var getCreateSourceExperience = function getCreateSourceExperience(_ref2) {
|
|
110
|
+
var refs = _ref2.refs,
|
|
111
|
+
dispatchAnalyticsEvent = _ref2.dispatchAnalyticsEvent;
|
|
112
|
+
return new _experiences.Experience(_analytics.ACTION_SUBJECT.SYNCED_BLOCK, {
|
|
113
|
+
actionSubjectId: _analytics.ACTION_SUBJECT_ID.SYNCED_BLOCK_CREATE,
|
|
114
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
|
|
115
|
+
checks: [new _experiences.ExperienceCheckTimeout({
|
|
116
|
+
durationMs: 2000
|
|
117
|
+
}), new _experiences.ExperienceCheckDomMutation({
|
|
118
|
+
onDomMutation: function onDomMutation(_ref3) {
|
|
119
|
+
var mutations = _ref3.mutations;
|
|
120
|
+
if (mutations.some(isSourceSyncBlockAddedInMutation)) {
|
|
121
|
+
return {
|
|
122
|
+
status: 'success'
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
return undefined;
|
|
126
|
+
},
|
|
127
|
+
observeConfig: function observeConfig() {
|
|
128
|
+
var _refs$containerElemen;
|
|
129
|
+
var proseMirrorElement = (_refs$containerElemen = refs.containerElement) === null || _refs$containerElemen === void 0 ? void 0 : _refs$containerElemen.querySelector('.ProseMirror');
|
|
130
|
+
if (!proseMirrorElement || !(proseMirrorElement instanceof HTMLElement)) {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
target: proseMirrorElement,
|
|
135
|
+
options: {
|
|
136
|
+
childList: true
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
})]
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
var isSyncedBlockCreateButtonId = function isSyncedBlockCreateButtonId(value) {
|
|
144
|
+
return !!value && syncedBlockCreateButtonIds.has(value);
|
|
145
|
+
};
|
|
146
|
+
var handleButtonClick = function handleButtonClick(testId, experience) {
|
|
147
|
+
switch (testId) {
|
|
148
|
+
case 'create-synced-block-toolbar-btn':
|
|
149
|
+
experience.start({
|
|
150
|
+
method: START_METHOD.PINNED_TOOLBAR
|
|
151
|
+
});
|
|
152
|
+
break;
|
|
153
|
+
case 'create-synced-block-block-menu-btn':
|
|
154
|
+
experience.start({
|
|
155
|
+
method: START_METHOD.BLOCK_MENU
|
|
156
|
+
});
|
|
157
|
+
break;
|
|
158
|
+
case 'create-synced-block-quick-insert-btn':
|
|
159
|
+
experience.start({
|
|
160
|
+
method: START_METHOD.QUICK_INSERT
|
|
161
|
+
});
|
|
162
|
+
break;
|
|
163
|
+
default:
|
|
164
|
+
{
|
|
165
|
+
// Exhaustiveness check: if a new SyncedBlockToolbarButtonId is added
|
|
166
|
+
// but not handled above, TypeScript will error here.
|
|
167
|
+
var _exhaustiveCheck = testId;
|
|
168
|
+
return _exhaustiveCheck;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
var isEnterKey = function isEnterKey(key) {
|
|
173
|
+
return key === 'Enter';
|
|
174
|
+
};
|
|
175
|
+
var isSourceSyncBlockAddedInMutation = function isSourceSyncBlockAddedInMutation(_ref4) {
|
|
176
|
+
var type = _ref4.type,
|
|
177
|
+
addedNodes = _ref4.addedNodes;
|
|
178
|
+
return type === 'childList' && (0, _toConsumableArray2.default)(addedNodes).some(isSourceSyncBlockNode);
|
|
179
|
+
};
|
|
180
|
+
var isSourceSyncBlockNode = function isSourceSyncBlockNode(node) {
|
|
181
|
+
if (!(node instanceof HTMLElement)) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
return !!node.querySelector('[data-prosemirror-node-name="bodiedSyncBlock"]');
|
|
185
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.getExperienceTrackingPlugins = void 0;
|
|
7
|
+
var _createReferenceExperience = require("./create-reference-experience");
|
|
8
|
+
var _createSourceExperience = require("./create-source-experience");
|
|
9
|
+
var getExperienceTrackingPlugins = exports.getExperienceTrackingPlugins = function getExperienceTrackingPlugins(_ref) {
|
|
10
|
+
var refs = _ref.refs,
|
|
11
|
+
dispatchAnalyticsEvent = _ref.dispatchAnalyticsEvent,
|
|
12
|
+
syncBlockStore = _ref.syncBlockStore;
|
|
13
|
+
return [{
|
|
14
|
+
name: 'createReferenceSyncedBlockExperiencePlugin',
|
|
15
|
+
plugin: function plugin() {
|
|
16
|
+
return (0, _createReferenceExperience.getCreateReferenceExperiencePlugin)({
|
|
17
|
+
refs: refs,
|
|
18
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}, {
|
|
22
|
+
name: 'createSourceSyncedBlockExperiencePlugin',
|
|
23
|
+
plugin: function plugin() {
|
|
24
|
+
return (0, _createSourceExperience.getCreateSourceExperiencePlugin)({
|
|
25
|
+
refs: refs,
|
|
26
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
|
|
27
|
+
syncBlockStore: syncBlockStore
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}];
|
|
31
|
+
};
|
|
@@ -5,14 +5,17 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
7
|
exports.syncedBlockPlugin = void 0;
|
|
8
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
8
9
|
var _react = _interopRequireDefault(require("react"));
|
|
9
10
|
var _adfSchema = require("@atlaskit/adf-schema");
|
|
10
11
|
var _messages = require("@atlaskit/editor-common/messages");
|
|
11
12
|
var _quickInsert = require("@atlaskit/editor-common/quick-insert");
|
|
12
13
|
var _editorSyncedBlockProvider = require("@atlaskit/editor-synced-block-provider");
|
|
13
14
|
var _lozenge = _interopRequireDefault(require("@atlaskit/lozenge"));
|
|
15
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
14
16
|
var _editorActions = require("./editor-actions");
|
|
15
17
|
var _editorCommands = require("./editor-commands");
|
|
18
|
+
var _getExperienceTrackingPlugins = require("./pm-plugins/experience-tracking/get-experience-tracking-plugins");
|
|
16
19
|
var _main = require("./pm-plugins/main");
|
|
17
20
|
var _blockMenuComponents = require("./ui/block-menu-components");
|
|
18
21
|
var _DeleteConfirmationModal = require("./ui/DeleteConfirmationModal");
|
|
@@ -24,6 +27,7 @@ var syncedBlockPlugin = exports.syncedBlockPlugin = function syncedBlockPlugin(_
|
|
|
24
27
|
var _api$analytics, _api$blockMenu, _config$enableSourceC, _api$toolbar, _config$enableSourceC2;
|
|
25
28
|
var config = _ref.config,
|
|
26
29
|
api = _ref.api;
|
|
30
|
+
var refs = {};
|
|
27
31
|
var syncBlockStore = new _editorSyncedBlockProvider.SyncBlockStoreManager(config === null || config === void 0 ? void 0 : config.syncBlockDataProvider);
|
|
28
32
|
syncBlockStore.setFireAnalyticsEvent(api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || (_api$analytics = _api$analytics.actions) === null || _api$analytics === void 0 ? void 0 : _api$analytics.fireAnalyticsEvent);
|
|
29
33
|
api === null || api === void 0 || (_api$blockMenu = api.blockMenu) === null || _api$blockMenu === void 0 || _api$blockMenu.actions.registerBlockMenuComponents((0, _blockMenuComponents.getBlockMenuComponents)(api, (_config$enableSourceC = config === null || config === void 0 ? void 0 : config.enableSourceCreation) !== null && _config$enableSourceC !== void 0 ? _config$enableSourceC : false));
|
|
@@ -45,7 +49,14 @@ var syncedBlockPlugin = exports.syncedBlockPlugin = function syncedBlockPlugin(_
|
|
|
45
49
|
plugin: function plugin(params) {
|
|
46
50
|
return (0, _main.createPlugin)(config, params, syncBlockStore, api);
|
|
47
51
|
}
|
|
48
|
-
}]
|
|
52
|
+
}].concat((0, _toConsumableArray2.default)((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding') ? (0, _getExperienceTrackingPlugins.getExperienceTrackingPlugins)({
|
|
53
|
+
refs: refs,
|
|
54
|
+
dispatchAnalyticsEvent: function dispatchAnalyticsEvent(payload) {
|
|
55
|
+
var _api$analytics2;
|
|
56
|
+
return api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions.fireAnalyticsEvent(payload);
|
|
57
|
+
},
|
|
58
|
+
syncBlockStore: syncBlockStore
|
|
59
|
+
}) : []));
|
|
49
60
|
},
|
|
50
61
|
commands: {
|
|
51
62
|
copySyncedBlockReferenceToClipboard: function copySyncedBlockReferenceToClipboard() {
|
|
@@ -100,14 +111,21 @@ var syncedBlockPlugin = exports.syncedBlockPlugin = function syncedBlockPlugin(_
|
|
|
100
111
|
syncBlockStore: syncBlockStore,
|
|
101
112
|
typeAheadInsert: insert
|
|
102
113
|
});
|
|
103
|
-
}
|
|
114
|
+
},
|
|
115
|
+
testId: (0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding') ? 'create-synced-block-quick-insert-btn' : undefined
|
|
104
116
|
}];
|
|
105
117
|
},
|
|
106
118
|
floatingToolbar: function floatingToolbar(state, intl) {
|
|
107
119
|
return (0, _floatingToolbar.getToolbarConfig)(state, intl, api, syncBlockStore);
|
|
108
120
|
}
|
|
109
121
|
},
|
|
110
|
-
contentComponent: function contentComponent() {
|
|
122
|
+
contentComponent: function contentComponent(_ref4) {
|
|
123
|
+
var containerElement = _ref4.containerElement,
|
|
124
|
+
wrapperElement = _ref4.wrapperElement,
|
|
125
|
+
popupsMountPoint = _ref4.popupsMountPoint;
|
|
126
|
+
refs.containerElement = containerElement || undefined;
|
|
127
|
+
refs.popupsMountPoint = popupsMountPoint || undefined;
|
|
128
|
+
refs.wrapperElement = wrapperElement || undefined;
|
|
111
129
|
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_SyncBlockRefresher.SyncBlockRefresher, {
|
|
112
130
|
syncBlockStoreManager: syncBlockStore,
|
|
113
131
|
api: api
|
|
@@ -51,6 +51,7 @@ var CreateSyncedBlockDropdownItem = function CreateSyncedBlockDropdownItem(_ref)
|
|
|
51
51
|
}),
|
|
52
52
|
onClick: onClick,
|
|
53
53
|
isDisabled: isOffline,
|
|
54
|
+
testId: "create-synced-block-block-menu-btn",
|
|
54
55
|
elemAfter: /*#__PURE__*/_react.default.createElement(_lozenge.default, {
|
|
55
56
|
appearance: "new"
|
|
56
57
|
}, formatMessage(_messages.blockMenuMessages.newLozenge))
|
|
@@ -2,6 +2,7 @@ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit
|
|
|
2
2
|
import { copyDomNode, toDOM } from '@atlaskit/editor-common/copy-button';
|
|
3
3
|
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
4
4
|
import { findSelectedNodeOfType, removeParentNodeOfType, removeSelectedNode, safeInsert } from '@atlaskit/editor-prosemirror/utils';
|
|
5
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
5
6
|
import { syncedBlockPluginKey } from '../pm-plugins/main';
|
|
6
7
|
import { canBeConvertedToSyncBlock, findSyncBlock, findSyncBlockOrBodiedSyncBlock, isBodiedSyncBlockNode } from '../pm-plugins/utils/utils';
|
|
7
8
|
import { FLAG_ID } from '../types';
|
|
@@ -39,7 +40,12 @@ export const createSyncedBlock = ({
|
|
|
39
40
|
} else {
|
|
40
41
|
const conversionInfo = canBeConvertedToSyncBlock(tr.selection);
|
|
41
42
|
if (!conversionInfo) {
|
|
42
|
-
|
|
43
|
+
if (fg('platform_synced_block_dogfooding')) {
|
|
44
|
+
var _syncBlockStore$sourc;
|
|
45
|
+
(_syncBlockStore$sourc = syncBlockStore.sourceManager.createExperience) === null || _syncBlockStore$sourc === void 0 ? void 0 : _syncBlockStore$sourc.failure({
|
|
46
|
+
reason: 'Selection is not allowed to be converted to sync block'
|
|
47
|
+
});
|
|
48
|
+
}
|
|
43
49
|
return false;
|
|
44
50
|
}
|
|
45
51
|
const attrs = syncBlockStore.sourceManager.generateBodiedSyncBlockAttrs();
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { ACTION_SUBJECT, ACTION_SUBJECT_ID } from '@atlaskit/editor-common/analytics';
|
|
2
|
+
import { Experience, ExperienceCheckDomMutation, ExperienceCheckTimeout } from '@atlaskit/editor-common/experiences';
|
|
3
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
4
|
+
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
5
|
+
const isPastedFromFabricEditor = html => !!html && html.indexOf('data-pm-slice="') >= 0;
|
|
6
|
+
const pluginKey = new PluginKey('createReferenceSyncBlockExperience');
|
|
7
|
+
const START_METHOD = {
|
|
8
|
+
PASTE: 'paste'
|
|
9
|
+
};
|
|
10
|
+
const ABORT_REASON = {
|
|
11
|
+
EDITOR_DESTROYED: 'editor-destroyed'
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* This experience tracks when a reference sync block is inserted.
|
|
16
|
+
*
|
|
17
|
+
* Start: When user pastes a sync block from editor and createSyncedBlock is called
|
|
18
|
+
* Success: When the sync block is added to the DOM within 500ms of start
|
|
19
|
+
* Failure: When 500ms passes without the reference sync block being added to the DOM
|
|
20
|
+
*/
|
|
21
|
+
export const getCreateReferenceExperiencePlugin = ({
|
|
22
|
+
refs,
|
|
23
|
+
dispatchAnalyticsEvent
|
|
24
|
+
}) => {
|
|
25
|
+
const experience = getCreateReferenceExperience({
|
|
26
|
+
refs,
|
|
27
|
+
dispatchAnalyticsEvent
|
|
28
|
+
});
|
|
29
|
+
return new SafePlugin({
|
|
30
|
+
key: pluginKey,
|
|
31
|
+
view: () => {
|
|
32
|
+
return {
|
|
33
|
+
destroy: () => {
|
|
34
|
+
experience.abort({
|
|
35
|
+
reason: ABORT_REASON.EDITOR_DESTROYED
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
},
|
|
40
|
+
props: {
|
|
41
|
+
handlePaste: (_view, rawEvent, slice) => {
|
|
42
|
+
var _event$clipboardData;
|
|
43
|
+
const event = rawEvent;
|
|
44
|
+
const html = (_event$clipboardData = event.clipboardData) === null || _event$clipboardData === void 0 ? void 0 : _event$clipboardData.getData('text/html');
|
|
45
|
+
|
|
46
|
+
// do not start on paste from renderer, because this flattens the content and does not create a reference block
|
|
47
|
+
if (isPastedFromFabricEditor(html)) {
|
|
48
|
+
slice.content.forEach(node => {
|
|
49
|
+
if (node.type.name === 'syncBlock' || node.type.name === 'bodiedSyncBlock') {
|
|
50
|
+
experience.start({
|
|
51
|
+
method: START_METHOD.PASTE
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
const getCreateReferenceExperience = ({
|
|
61
|
+
refs,
|
|
62
|
+
dispatchAnalyticsEvent
|
|
63
|
+
}) => {
|
|
64
|
+
return new Experience(ACTION_SUBJECT.SYNCED_BLOCK, {
|
|
65
|
+
actionSubjectId: ACTION_SUBJECT_ID.REFERENCE_SYNCED_BLOCK_CREATE,
|
|
66
|
+
dispatchAnalyticsEvent,
|
|
67
|
+
checks: [new ExperienceCheckTimeout({
|
|
68
|
+
durationMs: 500
|
|
69
|
+
}), new ExperienceCheckDomMutation({
|
|
70
|
+
onDomMutation: ({
|
|
71
|
+
mutations
|
|
72
|
+
}) => {
|
|
73
|
+
if (mutations.some(isReferenceSyncBlockAddedInMutation)) {
|
|
74
|
+
return {
|
|
75
|
+
status: 'success'
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
return undefined;
|
|
79
|
+
},
|
|
80
|
+
observeConfig: () => {
|
|
81
|
+
var _refs$containerElemen;
|
|
82
|
+
const proseMirrorElement = (_refs$containerElemen = refs.containerElement) === null || _refs$containerElemen === void 0 ? void 0 : _refs$containerElemen.querySelector('.ProseMirror');
|
|
83
|
+
if (!proseMirrorElement || !(proseMirrorElement instanceof HTMLElement)) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
target: proseMirrorElement,
|
|
88
|
+
options: {
|
|
89
|
+
childList: true
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
})]
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
const isReferenceSyncBlockAddedInMutation = ({
|
|
97
|
+
type,
|
|
98
|
+
addedNodes
|
|
99
|
+
}) => type === 'childList' && [...addedNodes].some(isReferenceSyncBlockNode);
|
|
100
|
+
const isReferenceSyncBlockNode = node => {
|
|
101
|
+
if (!(node instanceof HTMLElement)) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
return !!node.querySelector('[data-prosemirror-node-name="syncBlock"]');
|
|
105
|
+
};
|