@atlaskit/editor-plugin-card 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 (200) hide show
  1. package/.eslintrc.js +15 -0
  2. package/CHANGELOG.md +1 -0
  3. package/LICENSE.md +13 -0
  4. package/README.md +7 -0
  5. package/dist/cjs/index.js +12 -0
  6. package/dist/cjs/messages.js +20 -0
  7. package/dist/cjs/nodeviews/blockCard.js +164 -0
  8. package/dist/cjs/nodeviews/datasource.js +173 -0
  9. package/dist/cjs/nodeviews/embedCard.js +398 -0
  10. package/dist/cjs/nodeviews/genericCard.js +118 -0
  11. package/dist/cjs/nodeviews/inlineCard.js +132 -0
  12. package/dist/cjs/plugin.js +138 -0
  13. package/dist/cjs/pm-plugins/actions.js +122 -0
  14. package/dist/cjs/pm-plugins/analytics/create-analytics-queue.js +48 -0
  15. package/dist/cjs/pm-plugins/analytics/events-from-tr.js +359 -0
  16. package/dist/cjs/pm-plugins/analytics/index.js +19 -0
  17. package/dist/cjs/pm-plugins/analytics/types.js +5 -0
  18. package/dist/cjs/pm-plugins/analytics/utils.js +178 -0
  19. package/dist/cjs/pm-plugins/doc.js +479 -0
  20. package/dist/cjs/pm-plugins/keymap.js +64 -0
  21. package/dist/cjs/pm-plugins/main.js +212 -0
  22. package/dist/cjs/pm-plugins/mountHyperlink.js +47 -0
  23. package/dist/cjs/pm-plugins/plugin-key.js +9 -0
  24. package/dist/cjs/pm-plugins/reducers.js +111 -0
  25. package/dist/cjs/pm-plugins/shouldReplaceLink.js +35 -0
  26. package/dist/cjs/pm-plugins/util/resolve.js +59 -0
  27. package/dist/cjs/pm-plugins/util/state.js +49 -0
  28. package/dist/cjs/toolbar.js +364 -0
  29. package/dist/cjs/types.js +5 -0
  30. package/dist/cjs/ui/DatasourceModal/ModalWithState.js +25 -0
  31. package/dist/cjs/ui/DatasourceModal/index.js +60 -0
  32. package/dist/cjs/ui/EditLinkToolbar.js +258 -0
  33. package/dist/cjs/ui/EditorSmartCardEvents.js +21 -0
  34. package/dist/cjs/ui/EditorSmartCardEventsNext.js +215 -0
  35. package/dist/cjs/ui/HyperlinkToolbarAppearance.js +174 -0
  36. package/dist/cjs/ui/LayoutButton/index.js +121 -0
  37. package/dist/cjs/ui/LayoutButton/types.js +5 -0
  38. package/dist/cjs/ui/LayoutButton/utils.js +19 -0
  39. package/dist/cjs/ui/LinkToolbarAppearance.js +152 -0
  40. package/dist/cjs/ui/ResizableEmbedCard.js +364 -0
  41. package/dist/cjs/ui/SmallerEditIcon.js +22 -0
  42. package/dist/cjs/utils.js +60 -0
  43. package/dist/cjs/version.json +5 -0
  44. package/dist/es2019/index.js +1 -0
  45. package/dist/es2019/messages.js +13 -0
  46. package/dist/es2019/nodeviews/blockCard.js +131 -0
  47. package/dist/es2019/nodeviews/datasource.js +137 -0
  48. package/dist/es2019/nodeviews/embedCard.js +370 -0
  49. package/dist/es2019/nodeviews/genericCard.js +92 -0
  50. package/dist/es2019/nodeviews/inlineCard.js +113 -0
  51. package/dist/es2019/plugin.js +129 -0
  52. package/dist/es2019/pm-plugins/actions.js +57 -0
  53. package/dist/es2019/pm-plugins/analytics/create-analytics-queue.js +38 -0
  54. package/dist/es2019/pm-plugins/analytics/events-from-tr.js +339 -0
  55. package/dist/es2019/pm-plugins/analytics/index.js +2 -0
  56. package/dist/es2019/pm-plugins/analytics/types.js +1 -0
  57. package/dist/es2019/pm-plugins/analytics/utils.js +160 -0
  58. package/dist/es2019/pm-plugins/doc.js +451 -0
  59. package/dist/es2019/pm-plugins/keymap.js +59 -0
  60. package/dist/es2019/pm-plugins/main.js +208 -0
  61. package/dist/es2019/pm-plugins/mountHyperlink.js +37 -0
  62. package/dist/es2019/pm-plugins/plugin-key.js +2 -0
  63. package/dist/es2019/pm-plugins/reducers.js +110 -0
  64. package/dist/es2019/pm-plugins/shouldReplaceLink.js +25 -0
  65. package/dist/es2019/pm-plugins/util/resolve.js +50 -0
  66. package/dist/es2019/pm-plugins/util/state.js +26 -0
  67. package/dist/es2019/toolbar.js +359 -0
  68. package/dist/es2019/types.js +1 -0
  69. package/dist/es2019/ui/DatasourceModal/ModalWithState.js +19 -0
  70. package/dist/es2019/ui/DatasourceModal/index.js +48 -0
  71. package/dist/es2019/ui/EditLinkToolbar.js +226 -0
  72. package/dist/es2019/ui/EditorSmartCardEvents.js +15 -0
  73. package/dist/es2019/ui/EditorSmartCardEventsNext.js +199 -0
  74. package/dist/es2019/ui/HyperlinkToolbarAppearance.js +86 -0
  75. package/dist/es2019/ui/LayoutButton/index.js +114 -0
  76. package/dist/es2019/ui/LayoutButton/types.js +1 -0
  77. package/dist/es2019/ui/LayoutButton/utils.js +15 -0
  78. package/dist/es2019/ui/LinkToolbarAppearance.js +118 -0
  79. package/dist/es2019/ui/ResizableEmbedCard.js +335 -0
  80. package/dist/es2019/ui/SmallerEditIcon.js +14 -0
  81. package/dist/es2019/utils.js +46 -0
  82. package/dist/es2019/version.json +5 -0
  83. package/dist/esm/index.js +1 -0
  84. package/dist/esm/messages.js +13 -0
  85. package/dist/esm/nodeviews/blockCard.js +156 -0
  86. package/dist/esm/nodeviews/datasource.js +165 -0
  87. package/dist/esm/nodeviews/embedCard.js +389 -0
  88. package/dist/esm/nodeviews/genericCard.js +111 -0
  89. package/dist/esm/nodeviews/inlineCard.js +124 -0
  90. package/dist/esm/plugin.js +130 -0
  91. package/dist/esm/pm-plugins/actions.js +102 -0
  92. package/dist/esm/pm-plugins/analytics/create-analytics-queue.js +41 -0
  93. package/dist/esm/pm-plugins/analytics/events-from-tr.js +350 -0
  94. package/dist/esm/pm-plugins/analytics/index.js +2 -0
  95. package/dist/esm/pm-plugins/analytics/types.js +1 -0
  96. package/dist/esm/pm-plugins/analytics/utils.js +160 -0
  97. package/dist/esm/pm-plugins/doc.js +460 -0
  98. package/dist/esm/pm-plugins/keymap.js +58 -0
  99. package/dist/esm/pm-plugins/main.js +199 -0
  100. package/dist/esm/pm-plugins/mountHyperlink.js +39 -0
  101. package/dist/esm/pm-plugins/plugin-key.js +2 -0
  102. package/dist/esm/pm-plugins/reducers.js +103 -0
  103. package/dist/esm/pm-plugins/shouldReplaceLink.js +29 -0
  104. package/dist/esm/pm-plugins/util/resolve.js +52 -0
  105. package/dist/esm/pm-plugins/util/state.js +40 -0
  106. package/dist/esm/toolbar.js +350 -0
  107. package/dist/esm/types.js +1 -0
  108. package/dist/esm/ui/DatasourceModal/ModalWithState.js +17 -0
  109. package/dist/esm/ui/DatasourceModal/index.js +49 -0
  110. package/dist/esm/ui/EditLinkToolbar.js +244 -0
  111. package/dist/esm/ui/EditorSmartCardEvents.js +14 -0
  112. package/dist/esm/ui/EditorSmartCardEventsNext.js +203 -0
  113. package/dist/esm/ui/HyperlinkToolbarAppearance.js +163 -0
  114. package/dist/esm/ui/LayoutButton/index.js +110 -0
  115. package/dist/esm/ui/LayoutButton/types.js +1 -0
  116. package/dist/esm/ui/LayoutButton/utils.js +12 -0
  117. package/dist/esm/ui/LinkToolbarAppearance.js +141 -0
  118. package/dist/esm/ui/ResizableEmbedCard.js +358 -0
  119. package/dist/esm/ui/SmallerEditIcon.js +14 -0
  120. package/dist/esm/utils.js +48 -0
  121. package/dist/esm/version.json +5 -0
  122. package/dist/types/index.d.ts +2 -0
  123. package/dist/types/messages.d.ts +12 -0
  124. package/dist/types/nodeviews/blockCard.d.ts +26 -0
  125. package/dist/types/nodeviews/datasource.d.ts +42 -0
  126. package/dist/types/nodeviews/embedCard.d.ts +46 -0
  127. package/dist/types/nodeviews/genericCard.d.ts +37 -0
  128. package/dist/types/nodeviews/inlineCard.d.ts +23 -0
  129. package/dist/types/plugin.d.ts +24 -0
  130. package/dist/types/pm-plugins/actions.d.ts +23 -0
  131. package/dist/types/pm-plugins/analytics/create-analytics-queue.d.ts +10 -0
  132. package/dist/types/pm-plugins/analytics/events-from-tr.d.ts +17 -0
  133. package/dist/types/pm-plugins/analytics/index.d.ts +2 -0
  134. package/dist/types/pm-plugins/analytics/types.d.ts +12 -0
  135. package/dist/types/pm-plugins/analytics/utils.d.ts +32 -0
  136. package/dist/types/pm-plugins/doc.d.ts +22 -0
  137. package/dist/types/pm-plugins/keymap.d.ts +3 -0
  138. package/dist/types/pm-plugins/main.d.ts +6 -0
  139. package/dist/types/pm-plugins/mountHyperlink.d.ts +5 -0
  140. package/dist/types/pm-plugins/plugin-key.d.ts +3 -0
  141. package/dist/types/pm-plugins/reducers.d.ts +3 -0
  142. package/dist/types/pm-plugins/shouldReplaceLink.d.ts +2 -0
  143. package/dist/types/pm-plugins/util/resolve.d.ts +8 -0
  144. package/dist/types/pm-plugins/util/state.d.ts +31 -0
  145. package/dist/types/toolbar.d.ts +9 -0
  146. package/dist/types/types.d.ts +163 -0
  147. package/dist/types/ui/DatasourceModal/ModalWithState.d.ts +9 -0
  148. package/dist/types/ui/DatasourceModal/index.d.ts +11 -0
  149. package/dist/types/ui/EditLinkToolbar.d.ts +47 -0
  150. package/dist/types/ui/EditorSmartCardEvents.d.ts +5 -0
  151. package/dist/types/ui/EditorSmartCardEventsNext.d.ts +18 -0
  152. package/dist/types/ui/HyperlinkToolbarAppearance.d.ts +32 -0
  153. package/dist/types/ui/LayoutButton/index.d.ts +9 -0
  154. package/dist/types/ui/LayoutButton/types.d.ts +19 -0
  155. package/dist/types/ui/LayoutButton/utils.d.ts +5 -0
  156. package/dist/types/ui/LinkToolbarAppearance.d.ts +29 -0
  157. package/dist/types/ui/ResizableEmbedCard.d.ts +61 -0
  158. package/dist/types/ui/SmallerEditIcon.d.ts +3 -0
  159. package/dist/types/utils.d.ts +19 -0
  160. package/dist/types-ts4.5/index.d.ts +2 -0
  161. package/dist/types-ts4.5/messages.d.ts +12 -0
  162. package/dist/types-ts4.5/nodeviews/blockCard.d.ts +26 -0
  163. package/dist/types-ts4.5/nodeviews/datasource.d.ts +42 -0
  164. package/dist/types-ts4.5/nodeviews/embedCard.d.ts +46 -0
  165. package/dist/types-ts4.5/nodeviews/genericCard.d.ts +37 -0
  166. package/dist/types-ts4.5/nodeviews/inlineCard.d.ts +23 -0
  167. package/dist/types-ts4.5/plugin.d.ts +24 -0
  168. package/dist/types-ts4.5/pm-plugins/actions.d.ts +23 -0
  169. package/dist/types-ts4.5/pm-plugins/analytics/create-analytics-queue.d.ts +10 -0
  170. package/dist/types-ts4.5/pm-plugins/analytics/events-from-tr.d.ts +17 -0
  171. package/dist/types-ts4.5/pm-plugins/analytics/index.d.ts +2 -0
  172. package/dist/types-ts4.5/pm-plugins/analytics/types.d.ts +12 -0
  173. package/dist/types-ts4.5/pm-plugins/analytics/utils.d.ts +32 -0
  174. package/dist/types-ts4.5/pm-plugins/doc.d.ts +22 -0
  175. package/dist/types-ts4.5/pm-plugins/keymap.d.ts +3 -0
  176. package/dist/types-ts4.5/pm-plugins/main.d.ts +6 -0
  177. package/dist/types-ts4.5/pm-plugins/mountHyperlink.d.ts +5 -0
  178. package/dist/types-ts4.5/pm-plugins/plugin-key.d.ts +3 -0
  179. package/dist/types-ts4.5/pm-plugins/reducers.d.ts +3 -0
  180. package/dist/types-ts4.5/pm-plugins/shouldReplaceLink.d.ts +2 -0
  181. package/dist/types-ts4.5/pm-plugins/util/resolve.d.ts +8 -0
  182. package/dist/types-ts4.5/pm-plugins/util/state.d.ts +31 -0
  183. package/dist/types-ts4.5/toolbar.d.ts +9 -0
  184. package/dist/types-ts4.5/types.d.ts +163 -0
  185. package/dist/types-ts4.5/ui/DatasourceModal/ModalWithState.d.ts +9 -0
  186. package/dist/types-ts4.5/ui/DatasourceModal/index.d.ts +11 -0
  187. package/dist/types-ts4.5/ui/EditLinkToolbar.d.ts +47 -0
  188. package/dist/types-ts4.5/ui/EditorSmartCardEvents.d.ts +5 -0
  189. package/dist/types-ts4.5/ui/EditorSmartCardEventsNext.d.ts +18 -0
  190. package/dist/types-ts4.5/ui/HyperlinkToolbarAppearance.d.ts +32 -0
  191. package/dist/types-ts4.5/ui/LayoutButton/index.d.ts +9 -0
  192. package/dist/types-ts4.5/ui/LayoutButton/types.d.ts +19 -0
  193. package/dist/types-ts4.5/ui/LayoutButton/utils.d.ts +5 -0
  194. package/dist/types-ts4.5/ui/LinkToolbarAppearance.d.ts +29 -0
  195. package/dist/types-ts4.5/ui/ResizableEmbedCard.d.ts +61 -0
  196. package/dist/types-ts4.5/ui/SmallerEditIcon.d.ts +3 -0
  197. package/dist/types-ts4.5/utils.d.ts +19 -0
  198. package/package.json +126 -0
  199. package/report.api.md +146 -0
  200. package/tmp/api-report-tmp.d.ts +117 -0
@@ -0,0 +1,359 @@
1
+ import React from 'react';
2
+ import { NodeSelection } from 'prosemirror-state';
3
+ import { findDomRefAtPos, removeSelectedNode } from 'prosemirror-utils';
4
+ import { isSafeUrl } from '@atlaskit/adf-schema';
5
+ import { ACTION, ACTION_SUBJECT, buildOpenedSettingsPayload, buildVisitedLinkPayload, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
6
+ import { buildLayoutButtons, commandWithMetadata } from '@atlaskit/editor-common/card';
7
+ import commonMessages, { linkMessages, linkToolbarMessages, cardMessages as messages } from '@atlaskit/editor-common/messages';
8
+ import { FLOATING_TOOLBAR_LINKPICKER_CLASSNAME, richMediaClassName } from '@atlaskit/editor-common/styles';
9
+ import { canRenderDatasource } from '@atlaskit/editor-common/utils';
10
+ import RemoveIcon from '@atlaskit/icon/glyph/editor/remove';
11
+ import CogIcon from '@atlaskit/icon/glyph/editor/settings';
12
+ import UnlinkIcon from '@atlaskit/icon/glyph/editor/unlink';
13
+ import OpenIcon from '@atlaskit/icon/glyph/shortcut';
14
+ import { changeSelectedCardToText } from './pm-plugins/doc';
15
+ import { pluginKey } from './pm-plugins/main';
16
+ import { buildEditLinkToolbar, editDatasource, editLink, editLinkToolbarConfig } from './ui/EditLinkToolbar';
17
+ import { LinkToolbarAppearance } from './ui/LinkToolbarAppearance';
18
+ import { SmallerEditIcon } from './ui/SmallerEditIcon';
19
+ import { appearanceForNodeType, displayInfoForCard, findCardInfo, titleUrlPairFromNode } from './utils';
20
+ export const removeCard = editorAnalyticsApi => commandWithMetadata((state, dispatch) => {
21
+ if (!(state.selection instanceof NodeSelection)) {
22
+ return false;
23
+ }
24
+ const type = state.selection.node.type.name;
25
+ const payload = {
26
+ action: ACTION.DELETED,
27
+ actionSubject: ACTION_SUBJECT.SMART_LINK,
28
+ actionSubjectId: type,
29
+ attributes: {
30
+ inputMethod: INPUT_METHOD.TOOLBAR,
31
+ displayMode: type
32
+ },
33
+ eventType: EVENT_TYPE.TRACK
34
+ };
35
+ if (dispatch) {
36
+ const {
37
+ tr
38
+ } = state;
39
+ removeSelectedNode(tr);
40
+ editorAnalyticsApi === null || editorAnalyticsApi === void 0 ? void 0 : editorAnalyticsApi.attachAnalyticsEvent(payload)(tr);
41
+ dispatch(tr);
42
+ }
43
+ return true;
44
+ }, {
45
+ action: ACTION.DELETED
46
+ });
47
+ export const visitCardLink = editorAnalyticsApi => (state, dispatch) => {
48
+ if (!(state.selection instanceof NodeSelection)) {
49
+ return false;
50
+ }
51
+ const {
52
+ type
53
+ } = state.selection.node;
54
+ const {
55
+ url
56
+ } = titleUrlPairFromNode(state.selection.node);
57
+
58
+ // All card links should open in the same tab per https://product-fabric.atlassian.net/browse/MS-1583.
59
+ // We are in edit mode here, open the smart card URL in a new window.
60
+ window.open(url);
61
+ if (dispatch) {
62
+ const {
63
+ tr
64
+ } = state;
65
+ editorAnalyticsApi === null || editorAnalyticsApi === void 0 ? void 0 : editorAnalyticsApi.attachAnalyticsEvent(buildVisitedLinkPayload(type.name))(tr);
66
+ dispatch(tr);
67
+ }
68
+ return true;
69
+ };
70
+ export const openLinkSettings = editorAnalyticsApi => (state, dispatch) => {
71
+ if (!(state.selection instanceof NodeSelection)) {
72
+ return false;
73
+ }
74
+ window.open('https://id.atlassian.com/manage-profile/link-preferences');
75
+ if (dispatch) {
76
+ const {
77
+ tr,
78
+ selection: {
79
+ node: {
80
+ type
81
+ }
82
+ }
83
+ } = state;
84
+ editorAnalyticsApi === null || editorAnalyticsApi === void 0 ? void 0 : editorAnalyticsApi.attachAnalyticsEvent(buildOpenedSettingsPayload(type.name))(tr);
85
+ dispatch(tr);
86
+ }
87
+ return true;
88
+ };
89
+ export const floatingToolbar = (cardOptions, featureFlags, platform, linkPickerOptions, pluginInjectionApi) => {
90
+ return (state, intl, providerFactory) => {
91
+ const {
92
+ inlineCard,
93
+ blockCard,
94
+ embedCard
95
+ } = state.schema.nodes;
96
+ const nodeType = [inlineCard, blockCard, embedCard];
97
+ const pluginState = pluginKey.getState(state);
98
+ if (!(state.selection instanceof NodeSelection)) {
99
+ return;
100
+ }
101
+ const selectedNode = state.selection.node;
102
+ if (!selectedNode) {
103
+ return;
104
+ }
105
+ const isEmbedCard = appearanceForNodeType(selectedNode.type) === 'embed';
106
+
107
+ /* add an offset to embeds due to extra padding */
108
+ const toolbarOffset = isEmbedCard ? {
109
+ offset: [0, 24]
110
+ } : {};
111
+
112
+ // Applies padding override for when link picker is currently displayed
113
+ const className = pluginState !== null && pluginState !== void 0 && pluginState.showLinkingToolbar ? FLOATING_TOOLBAR_LINKPICKER_CLASSNAME : undefined;
114
+
115
+ /**
116
+ * Enable focus trap only if feature flag is enabled AND for the new version of the picker
117
+ */
118
+ const {
119
+ lpLinkPicker,
120
+ lpLinkPickerFocusTrap,
121
+ preventPopupOverflow
122
+ } = featureFlags;
123
+ const shouldEnableFocusTrap = lpLinkPicker && lpLinkPickerFocusTrap;
124
+ const isLinkPickerEnabled = !!lpLinkPicker;
125
+ return {
126
+ title: intl.formatMessage(messages.card),
127
+ className,
128
+ nodeType,
129
+ preventPopupOverflow,
130
+ ...toolbarOffset,
131
+ getDomRef: view => {
132
+ const element = findDomRefAtPos(view.state.selection.from, view.domAtPos.bind(view));
133
+ if (!element) {
134
+ return undefined;
135
+ }
136
+ if (isEmbedCard) {
137
+ return element.querySelector(`.${richMediaClassName}`);
138
+ }
139
+ return element;
140
+ },
141
+ items: generateToolbarItems(state, featureFlags, intl, providerFactory, cardOptions, platform, linkPickerOptions, pluginInjectionApi),
142
+ scrollable: pluginState !== null && pluginState !== void 0 && pluginState.showLinkingToolbar ? false : true,
143
+ focusTrap: shouldEnableFocusTrap && (pluginState === null || pluginState === void 0 ? void 0 : pluginState.showLinkingToolbar),
144
+ ...editLinkToolbarConfig(Boolean(pluginState === null || pluginState === void 0 ? void 0 : pluginState.showLinkingToolbar), isLinkPickerEnabled)
145
+ };
146
+ };
147
+ };
148
+ const unlinkCard = (node, state, editorAnalyticsApi) => {
149
+ const displayInfo = displayInfoForCard(node, findCardInfo(state));
150
+ const text = displayInfo.title || displayInfo.url;
151
+ if (text) {
152
+ return commandWithMetadata(changeSelectedCardToText(text, editorAnalyticsApi), {
153
+ action: ACTION.UNLINK
154
+ });
155
+ }
156
+ return () => false;
157
+ };
158
+ const buildAlignmentOptions = (state, intl, widthPluginDependencyApi, analyticsApi, cardOptions) => {
159
+ return buildLayoutButtons(state, intl, state.schema.nodes.embedCard, widthPluginDependencyApi, analyticsApi, true, true, cardOptions === null || cardOptions === void 0 ? void 0 : cardOptions.allowWrapping, cardOptions === null || cardOptions === void 0 ? void 0 : cardOptions.allowAlignment);
160
+ };
161
+ const withToolbarMetadata = command => commandWithMetadata(command, {
162
+ inputMethod: INPUT_METHOD.FLOATING_TB
163
+ });
164
+ const generateToolbarItems = (state, featureFlags, intl, providerFactory, cardOptions, platform, linkPicker, pluginInjectionApi) => node => {
165
+ var _pluginInjectionApi$d, _pluginInjectionApi$d2, _pluginInjectionApi$d3, _pluginInjectionApi$d4, _pluginInjectionApi$d5, _node$attrs, _node$attrs2, _node$attrs2$datasour;
166
+ const {
167
+ url
168
+ } = titleUrlPairFromNode(node);
169
+ const {
170
+ actions: editorAnalyticsApi
171
+ } = (_pluginInjectionApi$d = pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$d2 = pluginInjectionApi.dependencies) === null || _pluginInjectionApi$d2 === void 0 ? void 0 : _pluginInjectionApi$d2.analytics) !== null && _pluginInjectionApi$d !== void 0 ? _pluginInjectionApi$d : {};
172
+ let metadata = {};
173
+ if (url && !isSafeUrl(url)) {
174
+ return [];
175
+ } else {
176
+ const {
177
+ title
178
+ } = displayInfoForCard(node, findCardInfo(state));
179
+ metadata = {
180
+ url: url,
181
+ title: title
182
+ };
183
+ }
184
+ const pluginState = pluginKey.getState(state);
185
+ const currentAppearance = appearanceForNodeType(node.type);
186
+ const {
187
+ hoverDecoration
188
+ } = (_pluginInjectionApi$d3 = pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$d4 = pluginInjectionApi.dependencies) === null || _pluginInjectionApi$d4 === void 0 ? void 0 : (_pluginInjectionApi$d5 = _pluginInjectionApi$d4.decorations) === null || _pluginInjectionApi$d5 === void 0 ? void 0 : _pluginInjectionApi$d5.actions) !== null && _pluginInjectionApi$d3 !== void 0 ? _pluginInjectionApi$d3 : {};
189
+ const isDatasource = currentAppearance === 'block' && (node === null || node === void 0 ? void 0 : (_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.datasource);
190
+ const shouldRenderDatasourceToolbar = isDatasource &&
191
+ // not showing toolbar in mobile for now since not sure what our plans are for it
192
+ platform !== 'mobile' && canRenderDatasource(node === null || node === void 0 ? void 0 : (_node$attrs2 = node.attrs) === null || _node$attrs2 === void 0 ? void 0 : (_node$attrs2$datasour = _node$attrs2.datasource) === null || _node$attrs2$datasour === void 0 ? void 0 : _node$attrs2$datasour.id);
193
+
194
+ /* mobile builds toolbar natively using toolbarItems */
195
+ if (pluginState !== null && pluginState !== void 0 && pluginState.showLinkingToolbar && platform !== 'mobile') {
196
+ return [buildEditLinkToolbar({
197
+ providerFactory,
198
+ linkPicker,
199
+ node,
200
+ featureFlags,
201
+ pluginInjectionApi
202
+ })];
203
+ } else if (shouldRenderDatasourceToolbar) {
204
+ return getDatasourceButtonGroup(state, metadata, intl, editorAnalyticsApi, node, hoverDecoration);
205
+ } else {
206
+ const {
207
+ inlineCard
208
+ } = state.schema.nodes;
209
+ const toolbarItems = [{
210
+ id: 'editor.link.edit',
211
+ type: 'button',
212
+ selected: false,
213
+ metadata: metadata,
214
+ title: intl.formatMessage(linkToolbarMessages.editLink),
215
+ showTitle: true,
216
+ testId: 'link-toolbar-edit-link-button',
217
+ onClick: editLink(editorAnalyticsApi)
218
+ }, {
219
+ type: 'separator'
220
+ }, {
221
+ id: 'editor.link.openLink',
222
+ type: 'button',
223
+ icon: OpenIcon,
224
+ metadata: metadata,
225
+ className: 'hyperlink-open-link',
226
+ title: intl.formatMessage(linkMessages.openLink),
227
+ onClick: visitCardLink(editorAnalyticsApi)
228
+ }, {
229
+ type: 'separator'
230
+ }, ...getUnlinkButtonGroup(state, intl, node, inlineCard, editorAnalyticsApi), {
231
+ type: 'copy-button',
232
+ items: [{
233
+ state,
234
+ formatMessage: intl.formatMessage,
235
+ nodeType: node.type
236
+ }, {
237
+ type: 'separator'
238
+ }]
239
+ }, ...getSettingsButtonGroup(state, featureFlags, intl, editorAnalyticsApi), {
240
+ id: 'editor.link.delete',
241
+ focusEditoronEnter: true,
242
+ type: 'button',
243
+ appearance: 'danger',
244
+ icon: RemoveIcon,
245
+ onMouseEnter: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(node.type, true),
246
+ onMouseLeave: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(node.type, false),
247
+ onFocus: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(node.type, true),
248
+ onBlur: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(node.type, false),
249
+ title: intl.formatMessage(commonMessages.remove),
250
+ onClick: withToolbarMetadata(removeCard(editorAnalyticsApi))
251
+ }];
252
+ if (currentAppearance === 'embed') {
253
+ var _pluginInjectionApi$d6, _pluginInjectionApi$d7, _pluginInjectionApi$d8;
254
+ const alignmentOptions = buildAlignmentOptions(state, intl, pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$d6 = pluginInjectionApi.dependencies) === null || _pluginInjectionApi$d6 === void 0 ? void 0 : _pluginInjectionApi$d6.width, pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$d7 = pluginInjectionApi.dependencies) === null || _pluginInjectionApi$d7 === void 0 ? void 0 : (_pluginInjectionApi$d8 = _pluginInjectionApi$d7.analytics) === null || _pluginInjectionApi$d8 === void 0 ? void 0 : _pluginInjectionApi$d8.actions, cardOptions);
255
+ if (alignmentOptions.length) {
256
+ alignmentOptions.push({
257
+ type: 'separator'
258
+ });
259
+ }
260
+ toolbarItems.unshift(...alignmentOptions);
261
+ }
262
+ const {
263
+ allowBlockCards,
264
+ allowEmbeds
265
+ } = cardOptions;
266
+
267
+ // This code will be executed only for appearances such as "inline", "block" & "embed"
268
+ // For url appearance, please see HyperlinkToolbarAppearanceProps
269
+ if (currentAppearance) {
270
+ toolbarItems.unshift({
271
+ type: 'custom',
272
+ fallback: [],
273
+ render: editorView => /*#__PURE__*/React.createElement(LinkToolbarAppearance, {
274
+ key: "link-appearance",
275
+ url: url,
276
+ intl: intl,
277
+ currentAppearance: currentAppearance,
278
+ editorView: editorView,
279
+ editorState: state,
280
+ allowEmbeds: allowEmbeds,
281
+ allowBlockCards: allowBlockCards,
282
+ platform: platform,
283
+ editorAnalyticsApi: editorAnalyticsApi,
284
+ cardActions: pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : pluginInjectionApi.dependencies.card.actions
285
+ })
286
+ }, {
287
+ type: 'separator'
288
+ });
289
+ }
290
+ return toolbarItems;
291
+ }
292
+ };
293
+ const getUnlinkButtonGroup = (state, intl, node, inlineCard, editorAnalyticsApi) => {
294
+ return node.type === inlineCard ? [{
295
+ id: 'editor.link.unlink',
296
+ focusEditoronEnter: true,
297
+ type: 'button',
298
+ title: intl.formatMessage(linkToolbarMessages.unlink),
299
+ icon: UnlinkIcon,
300
+ onClick: withToolbarMetadata(unlinkCard(node, state, editorAnalyticsApi))
301
+ }, {
302
+ type: 'separator'
303
+ }] : [];
304
+ };
305
+ const getSettingsButtonGroup = (state, featureFlags, intl, editorAnalyticsApi) => {
306
+ const {
307
+ floatingToolbarLinkSettingsButton
308
+ } = featureFlags;
309
+ return floatingToolbarLinkSettingsButton === 'true' ? [{
310
+ id: 'editor.link.settings',
311
+ type: 'button',
312
+ icon: CogIcon,
313
+ title: intl.formatMessage(linkToolbarMessages.settingsLink),
314
+ onClick: openLinkSettings(editorAnalyticsApi)
315
+ }, {
316
+ type: 'separator'
317
+ }] : [];
318
+ };
319
+ const getDatasourceButtonGroup = (state, metadata, intl, editorAnalyticsApi, node, hoverDecoration) => {
320
+ var _node$attrs3;
321
+ const toolbarItems = [{
322
+ id: 'editor.edit.datasource',
323
+ type: 'button',
324
+ icon: SmallerEditIcon,
325
+ metadata: metadata,
326
+ className: 'datasource-edit',
327
+ title: intl.formatMessage(linkToolbarMessages.editDatasource),
328
+ onClick: editDatasource(node, editorAnalyticsApi)
329
+ }];
330
+ if (node !== null && node !== void 0 && (_node$attrs3 = node.attrs) !== null && _node$attrs3 !== void 0 && _node$attrs3.url) {
331
+ toolbarItems.push({
332
+ type: 'separator'
333
+ }, {
334
+ id: 'editor.link.openLink',
335
+ type: 'button',
336
+ icon: OpenIcon,
337
+ metadata: metadata,
338
+ className: 'hyperlink-open-link',
339
+ title: intl.formatMessage(linkMessages.openLink),
340
+ onClick: visitCardLink(editorAnalyticsApi)
341
+ });
342
+ }
343
+ toolbarItems.push({
344
+ type: 'separator'
345
+ }, {
346
+ id: 'editor.link.delete',
347
+ focusEditoronEnter: true,
348
+ type: 'button',
349
+ appearance: 'danger',
350
+ icon: RemoveIcon,
351
+ onMouseEnter: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(node.type, true),
352
+ onMouseLeave: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(node.type, false),
353
+ onFocus: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(node.type, true),
354
+ onBlur: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(node.type, false),
355
+ title: intl.formatMessage(commonMessages.remove),
356
+ onClick: withToolbarMetadata(removeCard(editorAnalyticsApi))
357
+ });
358
+ return toolbarItems;
359
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
3
+ import { DatasourceModal } from './index';
4
+ const ModalWithState = ({
5
+ api,
6
+ editorView
7
+ }) => {
8
+ const {
9
+ cardState
10
+ } = useSharedPluginState(api, ['card']);
11
+ if (!(cardState !== null && cardState !== void 0 && cardState.showDatasourceModal)) {
12
+ return null;
13
+ }
14
+ return /*#__PURE__*/React.createElement(DatasourceModal, {
15
+ view: editorView,
16
+ modalType: cardState === null || cardState === void 0 ? void 0 : cardState.datasourceModalType
17
+ });
18
+ };
19
+ export default ModalWithState;
@@ -0,0 +1,48 @@
1
+ import React, { useCallback } from 'react';
2
+ import { NodeSelection } from 'prosemirror-state';
3
+ import { JIRA_LIST_OF_LINKS_DATASOURCE_ID, JiraIssuesConfigModal } from '@atlaskit/link-datasource';
4
+ import { hideDatasourceModal } from '../../pm-plugins/actions';
5
+ import { insertDatasource, updateExistingDatasource } from '../../pm-plugins/doc';
6
+ export const DatasourceModal = ({
7
+ view,
8
+ modalType
9
+ }) => {
10
+ const {
11
+ dispatch,
12
+ state
13
+ } = view;
14
+ const {
15
+ selection
16
+ } = state;
17
+ const existingNode = selection instanceof NodeSelection ? selection.node : undefined;
18
+ const onClose = useCallback(() => {
19
+ dispatch(hideDatasourceModal(state.tr));
20
+ }, [dispatch, state.tr]);
21
+ const onInsert = useCallback(newAdf => {
22
+ if (existingNode) {
23
+ updateExistingDatasource(state, existingNode, newAdf, view);
24
+ } else {
25
+ insertDatasource(state, newAdf, view);
26
+ }
27
+ }, [existingNode, state, view]);
28
+ if (modalType === 'jira') {
29
+ var _existingNode$attrs, _tableView$properties;
30
+ const {
31
+ id: datasourceId = JIRA_LIST_OF_LINKS_DATASOURCE_ID,
32
+ parameters,
33
+ views = []
34
+ } = (existingNode === null || existingNode === void 0 ? void 0 : (_existingNode$attrs = existingNode.attrs) === null || _existingNode$attrs === void 0 ? void 0 : _existingNode$attrs.datasource) || {};
35
+ const [tableView] = views;
36
+ const visibleColumnKeys = tableView === null || tableView === void 0 ? void 0 : (_tableView$properties = tableView.properties) === null || _tableView$properties === void 0 ? void 0 : _tableView$properties.columns.map(column => column.key);
37
+ return /*#__PURE__*/React.createElement("div", {
38
+ "data-testid": "jira-config-modal"
39
+ }, /*#__PURE__*/React.createElement(JiraIssuesConfigModal, {
40
+ datasourceId: datasourceId,
41
+ visibleColumnKeys: visibleColumnKeys,
42
+ parameters: parameters,
43
+ onCancel: onClose,
44
+ onInsert: onInsert
45
+ }));
46
+ }
47
+ return null; // null for now until we have modal component that handles other datasources
48
+ };
@@ -0,0 +1,226 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import React from 'react';
3
+ import { NodeSelection } from 'prosemirror-state';
4
+ import { ACTION, buildEditLinkPayload, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
5
+ import { commandWithMetadata } from '@atlaskit/editor-common/card';
6
+ import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
7
+ import { HyperlinkAddToolbar as HyperlinkToolbar } from '@atlaskit/editor-common/link';
8
+ import { linkToolbarMessages } from '@atlaskit/editor-common/messages';
9
+ import { LINKPICKER_HEIGHT_IN_PX, RECENT_SEARCH_HEIGHT_IN_PX, RECENT_SEARCH_WIDTH_IN_PX, withOuterListeners } from '@atlaskit/editor-common/ui';
10
+ import { JIRA_LIST_OF_LINKS_DATASOURCE_ID } from '@atlaskit/link-datasource';
11
+ import { hideLinkToolbar, showDatasourceModal, showLinkToolbar } from '../pm-plugins/actions';
12
+ import { changeSelectedCardToLink, updateCard } from '../pm-plugins/doc';
13
+ import { displayInfoForCard, findCardInfo } from '../utils';
14
+ const HyperLinkToolbarWithListeners = withOuterListeners(HyperlinkAddToolbarWithState);
15
+ export function HyperlinkAddToolbarWithState({
16
+ linkPickerOptions = {},
17
+ onSubmit,
18
+ displayText,
19
+ displayUrl,
20
+ providerFactory,
21
+ view,
22
+ onCancel,
23
+ invokeMethod,
24
+ featureFlags,
25
+ onClose,
26
+ onEscapeCallback,
27
+ onClickAwayCallback,
28
+ pluginInjectionApi
29
+ }) {
30
+ const {
31
+ hyperlinkState
32
+ } = useSharedPluginState(pluginInjectionApi, ['hyperlink']);
33
+ return /*#__PURE__*/React.createElement(HyperlinkToolbar, {
34
+ linkPickerOptions: linkPickerOptions,
35
+ onSubmit: onSubmit,
36
+ displayText: displayText,
37
+ displayUrl: displayUrl,
38
+ providerFactory: providerFactory,
39
+ view: view,
40
+ onCancel: onCancel,
41
+ invokeMethod: invokeMethod,
42
+ featureFlags: featureFlags,
43
+ onClose: onClose,
44
+ onEscapeCallback: onEscapeCallback,
45
+ onClickAwayCallback: onClickAwayCallback,
46
+ hyperlinkPluginState: hyperlinkState
47
+ });
48
+ }
49
+
50
+ // eslint-disable-next-line @repo/internal/react/no-class-components
51
+ export class EditLinkToolbar extends React.Component {
52
+ constructor(...args) {
53
+ super(...args);
54
+ /** Focus should move to the 'Edit link' button when the toolbar closes
55
+ * and not close the floating toolbar.
56
+ */
57
+ _defineProperty(this, "handleEsc", e => {
58
+ var _this$props$forceFocu, _this$props;
59
+ (_this$props$forceFocu = (_this$props = this.props).forceFocusSelector) === null || _this$props$forceFocu === void 0 ? void 0 : _this$props$forceFocu.call(_this$props, `[aria-label="${linkToolbarMessages.editLink.defaultMessage}"]`, this.props.view);
60
+ });
61
+ }
62
+ componentDidUpdate(prevProps) {
63
+ if (prevProps.node !== this.props.node) {
64
+ this.hideLinkToolbar();
65
+ }
66
+ }
67
+ componentWillUnmount() {
68
+ this.hideLinkToolbar();
69
+ }
70
+ hideLinkToolbar() {
71
+ const {
72
+ view
73
+ } = this.props;
74
+ view.dispatch(hideLinkToolbar(view.state.tr));
75
+ }
76
+ render() {
77
+ const {
78
+ linkPickerOptions,
79
+ providerFactory,
80
+ url,
81
+ text,
82
+ view,
83
+ featureFlags,
84
+ onSubmit,
85
+ pluginInjectionApi
86
+ } = this.props;
87
+ return /*#__PURE__*/React.createElement(HyperLinkToolbarWithListeners, {
88
+ pluginInjectionApi: pluginInjectionApi,
89
+ view: view,
90
+ linkPickerOptions: linkPickerOptions,
91
+ providerFactory: providerFactory,
92
+ displayUrl: url,
93
+ displayText: text,
94
+ handleEscapeKeydown: this.handleEsc
95
+ // Assumes that the smart card link picker can only ever be invoked by clicking "edit"
96
+ // via the floating toolbar
97
+ ,
98
+ invokeMethod: INPUT_METHOD.FLOATING_TB,
99
+ featureFlags: featureFlags,
100
+ onSubmit: (href, title, displayText, inputMethod, analytic) => {
101
+ this.hideLinkToolbar();
102
+ if (onSubmit) {
103
+ onSubmit(href, displayText || title, inputMethod, analytic);
104
+ }
105
+ },
106
+ onEscapeCallback: (state, dispatch) => {
107
+ const {
108
+ tr
109
+ } = state;
110
+ pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : pluginInjectionApi.dependencies.hyperlink.actions.hideLinkToolbar(tr);
111
+ hideLinkToolbar(tr);
112
+ if (dispatch) {
113
+ dispatch(tr);
114
+ return true;
115
+ }
116
+ return false;
117
+ },
118
+ onClickAwayCallback: (state, dispatch) => {
119
+ const {
120
+ tr
121
+ } = state;
122
+ pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : pluginInjectionApi.dependencies.hyperlink.actions.hideLinkToolbar(tr);
123
+ if (dispatch) {
124
+ dispatch(tr);
125
+ return true;
126
+ }
127
+ return false;
128
+ }
129
+ });
130
+ }
131
+ }
132
+ export const editLink = editorAnalyticsApi => (state, dispatch) => {
133
+ let type = 'hyperlink';
134
+ if (state.selection instanceof NodeSelection) {
135
+ type = state.selection.node.type.name;
136
+ }
137
+ if (dispatch) {
138
+ const {
139
+ tr
140
+ } = state;
141
+ showLinkToolbar(tr);
142
+ editorAnalyticsApi === null || editorAnalyticsApi === void 0 ? void 0 : editorAnalyticsApi.attachAnalyticsEvent(buildEditLinkPayload(type))(tr);
143
+ dispatch(tr);
144
+ return true;
145
+ }
146
+ return false;
147
+ };
148
+ export const buildEditLinkToolbar = ({
149
+ providerFactory,
150
+ node,
151
+ linkPicker,
152
+ featureFlags,
153
+ pluginInjectionApi
154
+ }) => {
155
+ return {
156
+ type: 'custom',
157
+ disableArrowNavigation: true,
158
+ fallback: [],
159
+ render: (view, idx) => {
160
+ var _pluginInjectionApi$d;
161
+ if (!view || !providerFactory) {
162
+ return null;
163
+ }
164
+ const displayInfo = displayInfoForCard(node, findCardInfo(view.state));
165
+ return /*#__PURE__*/React.createElement(EditLinkToolbar, {
166
+ pluginInjectionApi: pluginInjectionApi,
167
+ key: idx,
168
+ view: view,
169
+ linkPickerOptions: linkPicker,
170
+ providerFactory: providerFactory,
171
+ url: displayInfo.url,
172
+ text: displayInfo.title || '',
173
+ node: node,
174
+ featureFlags: featureFlags,
175
+ forceFocusSelector: pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$d = pluginInjectionApi.dependencies.floatingToolbar.actions) === null || _pluginInjectionApi$d === void 0 ? void 0 : _pluginInjectionApi$d.forceFocusSelector,
176
+ onSubmit: (newHref, newText, inputMethod, analytic) => {
177
+ const urlChanged = newHref !== displayInfo.url;
178
+ const titleChanged = newText !== displayInfo.title;
179
+
180
+ // If the title is changed in a smartlink, convert to standard blue hyperlink
181
+ // (even if the url was also changed) - we don't want to lose the custom title.
182
+ if (titleChanged) {
183
+ var _pluginInjectionApi$d2;
184
+ return commandWithMetadata(changeSelectedCardToLink(newText, newHref, undefined, undefined, undefined, pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$d2 = pluginInjectionApi.dependencies.analytics) === null || _pluginInjectionApi$d2 === void 0 ? void 0 : _pluginInjectionApi$d2.actions), {
185
+ action: ACTION.UPDATED,
186
+ inputMethod,
187
+ sourceEvent: analytic
188
+ })(view.state, view.dispatch);
189
+ }
190
+ if (urlChanged) {
191
+ // If *only* the url is changed in a smart link, reresolve
192
+ return updateCard(newHref, analytic)(view.state, view.dispatch);
193
+ }
194
+ }
195
+ });
196
+ }
197
+ };
198
+ };
199
+ export const editLinkToolbarConfig = (showLinkingToolbar, lpLinkPicker) => {
200
+ return showLinkingToolbar ? {
201
+ height: lpLinkPicker ? LINKPICKER_HEIGHT_IN_PX : RECENT_SEARCH_HEIGHT_IN_PX,
202
+ width: RECENT_SEARCH_WIDTH_IN_PX,
203
+ forcePlacement: true
204
+ } : {};
205
+ };
206
+ export const editDatasource = (node, editorAnalyticsApi) => (state, dispatch) => {
207
+ var _node$attrs;
208
+ const modalType = ((_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.datasource.id) === JIRA_LIST_OF_LINKS_DATASOURCE_ID ? 'jira' : undefined;
209
+ if (dispatch && modalType) {
210
+ const {
211
+ tr
212
+ } = state;
213
+ showDatasourceModal(modalType)(tr);
214
+ // editorAnalyticsApi?.attachAnalyticsEvent(
215
+ // buildEditLinkPayload(
216
+ // type as
217
+ // | ACTION_SUBJECT_ID.CARD_INLINE
218
+ // | ACTION_SUBJECT_ID.CARD_BLOCK
219
+ // | ACTION_SUBJECT_ID.EMBEDS,
220
+ // ),
221
+ // )(tr);
222
+ dispatch(tr);
223
+ return true;
224
+ }
225
+ return false;
226
+ };
@@ -0,0 +1,15 @@
1
+ import { useEffect } from 'react';
2
+ import { useSmartLinkEvents } from '@atlaskit/smart-card';
3
+ import { registerSmartCardEvents } from '../pm-plugins/actions';
4
+ export const EditorSmartCardEvents = ({
5
+ editorView
6
+ }) => {
7
+ const events = useSmartLinkEvents();
8
+ useEffect(() => {
9
+ if (!events) {
10
+ return;
11
+ }
12
+ editorView.dispatch(registerSmartCardEvents(events)(editorView.state.tr));
13
+ }, [events, editorView]);
14
+ return null;
15
+ };