@atlaskit/editor-common 72.6.0 → 72.7.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 (70) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/cjs/analytics/types/enums.js +3 -0
  3. package/dist/cjs/hooks/index.js +8 -1
  4. package/dist/cjs/hooks/useSharedPluginState.js +102 -0
  5. package/dist/cjs/messages/{codeBlockCopyButton.js → codeBlockButton.js} +13 -3
  6. package/dist/cjs/messages/index.js +3 -3
  7. package/dist/cjs/normalize-feature-flags.js +12 -0
  8. package/dist/cjs/preset/plugin-injection-api.js +115 -53
  9. package/dist/cjs/styles/shared/table.js +2 -0
  10. package/dist/cjs/ui/DropList/index.js +1 -1
  11. package/dist/cjs/ui-color/ColorPalette/Palettes/borderColorPalette.js +24 -0
  12. package/dist/cjs/ui-color/ColorPalette/Palettes/index.js +6 -0
  13. package/dist/cjs/ui-color/ColorPalette/Palettes/paletteMessagesTokenModeNames.js +25 -2
  14. package/dist/cjs/ui-color/index.js +14 -1
  15. package/dist/cjs/utils/validator.js +7 -0
  16. package/dist/cjs/version.json +1 -1
  17. package/dist/es2019/analytics/types/enums.js +3 -0
  18. package/dist/es2019/hooks/index.js +2 -1
  19. package/dist/es2019/hooks/useSharedPluginState.js +78 -0
  20. package/dist/{esm/messages/codeBlockCopyButton.js → es2019/messages/codeBlockButton.js} +11 -1
  21. package/dist/es2019/messages/index.js +1 -1
  22. package/dist/es2019/normalize-feature-flags.js +9 -0
  23. package/dist/es2019/preset/plugin-injection-api.js +64 -33
  24. package/dist/es2019/styles/shared/table.js +2 -0
  25. package/dist/es2019/ui/DropList/index.js +1 -1
  26. package/dist/es2019/ui-color/ColorPalette/Palettes/borderColorPalette.js +16 -0
  27. package/dist/es2019/ui-color/ColorPalette/Palettes/index.js +1 -1
  28. package/dist/es2019/ui-color/ColorPalette/Palettes/paletteMessagesTokenModeNames.js +24 -0
  29. package/dist/es2019/ui-color/index.js +3 -2
  30. package/dist/es2019/utils/validator.js +7 -0
  31. package/dist/es2019/version.json +1 -1
  32. package/dist/esm/analytics/types/enums.js +3 -0
  33. package/dist/esm/hooks/index.js +2 -1
  34. package/dist/esm/hooks/useSharedPluginState.js +95 -0
  35. package/dist/{es2019/messages/codeBlockCopyButton.js → esm/messages/codeBlockButton.js} +11 -1
  36. package/dist/esm/messages/index.js +1 -1
  37. package/dist/esm/normalize-feature-flags.js +11 -0
  38. package/dist/esm/preset/plugin-injection-api.js +115 -53
  39. package/dist/esm/styles/shared/table.js +2 -0
  40. package/dist/esm/ui/DropList/index.js +1 -1
  41. package/dist/esm/ui-color/ColorPalette/Palettes/borderColorPalette.js +16 -0
  42. package/dist/esm/ui-color/ColorPalette/Palettes/index.js +1 -1
  43. package/dist/esm/ui-color/ColorPalette/Palettes/paletteMessagesTokenModeNames.js +22 -0
  44. package/dist/esm/ui-color/index.js +3 -2
  45. package/dist/esm/utils/validator.js +7 -0
  46. package/dist/esm/version.json +1 -1
  47. package/dist/types/analytics/types/enums.d.ts +3 -0
  48. package/dist/types/analytics/types/media-events.d.ts +3 -1
  49. package/dist/types/collab/types.d.ts +15 -0
  50. package/dist/types/collab.d.ts +1 -1
  51. package/dist/types/extensions/types/extension-handler.d.ts +1 -1
  52. package/dist/types/hooks/index.d.ts +1 -0
  53. package/dist/types/hooks/useSharedPluginState.d.ts +39 -0
  54. package/dist/types/messages/codeBlockButton.d.ts +22 -0
  55. package/dist/types/messages/index.d.ts +1 -1
  56. package/dist/types/normalize-feature-flags.d.ts +7 -0
  57. package/dist/types/preset/plugin-injection-api.d.ts +3 -1
  58. package/dist/types/styles/shared/table.d.ts +2 -0
  59. package/dist/types/types/feature-flags.d.ts +10 -0
  60. package/dist/types/types/floating-toolbar.d.ts +5 -0
  61. package/dist/types/types/index.d.ts +1 -1
  62. package/dist/types/types/next-editor-plugin.d.ts +5 -4
  63. package/dist/types/ui/EventHandlers/index.d.ts +2 -2
  64. package/dist/types/ui-color/ColorPalette/Palettes/borderColorPalette.d.ts +3 -0
  65. package/dist/types/ui-color/ColorPalette/Palettes/index.d.ts +1 -1
  66. package/dist/types/ui-color/ColorPalette/Palettes/paletteMessagesTokenModeNames.d.ts +36 -0
  67. package/dist/types/ui-color/index.d.ts +2 -1
  68. package/package.json +10 -9
  69. package/report.api.md +1 -1
  70. package/dist/types/messages/codeBlockCopyButton.d.ts +0 -12
@@ -220,6 +220,7 @@ export let ACTION_SUBJECT_ID;
220
220
  ACTION_SUBJECT_ID["ANNOTATE_BUTTON"] = "annotateButton";
221
221
  ACTION_SUBJECT_ID["AVATAR_GROUP_PLUGIN"] = "AvatarGroupInPlugin";
222
222
  ACTION_SUBJECT_ID["BLOCK_QUOTE"] = "blockQuote";
223
+ ACTION_SUBJECT_ID["BORDER"] = "border";
223
224
  ACTION_SUBJECT_ID["BUTTON_CATEGORY"] = "categoryButton";
224
225
  ACTION_SUBJECT_ID["BUTTON_FEEDBACK"] = "feedbackButton";
225
226
  ACTION_SUBJECT_ID["BUTTON_HELP"] = "helpButton";
@@ -229,6 +230,8 @@ export let ACTION_SUBJECT_ID;
229
230
  ACTION_SUBJECT_ID["CARD_INLINE"] = "inlineCard";
230
231
  ACTION_SUBJECT_ID["CELL"] = "cell";
231
232
  ACTION_SUBJECT_ID["CODE_BLOCK"] = "codeBlock";
233
+ ACTION_SUBJECT_ID["CODEBLOCK_COPY"] = "codeBlockCopy";
234
+ ACTION_SUBJECT_ID["CODEBLOCK_WRAP"] = "codeBlockWrap";
232
235
  ACTION_SUBJECT_ID["DATE"] = "date";
233
236
  ACTION_SUBJECT_ID["DATE_DAY"] = "day";
234
237
  ACTION_SUBJECT_ID["DATE_MONTH"] = "month";
@@ -1,2 +1,3 @@
1
1
  export { default as usePreviousState } from './usePreviousState';
2
- export { default as useConstructor } from './useConstructor';
2
+ export { default as useConstructor } from './useConstructor';
3
+ export { useSharedPluginState } from './useSharedPluginState';
@@ -0,0 +1,78 @@
1
+ import { useEffect, useMemo, useState } from 'react';
2
+ /**
3
+ *
4
+ * Directly map object values
5
+ *
6
+ * @param object The object to transform
7
+ * @param mapFunction The function to map an old value to new one
8
+ * @returns Object with the same key but transformed values
9
+ *
10
+ */
11
+ function mapValues(object, mapFunction) {
12
+ return Object.entries(object).reduce((acc, [key, value]) => ({
13
+ ...acc,
14
+ [key]: mapFunction(value)
15
+ }), {});
16
+ }
17
+
18
+ /**
19
+ *
20
+ * Used to return the current plugin state of
21
+ * input dependencies
22
+ *
23
+ * Example in plugin:
24
+ *
25
+ * ```typescript
26
+ * function ExampleContent({ api }: Props) {
27
+ * const { dogState, exampleState } = useSharedPluginState(
28
+ * api,
29
+ * ['dog', 'example']
30
+ * )
31
+ * return <p>{ dogState.title } { exampleState.description }</p>
32
+ * }
33
+ *
34
+ * const examplePlugin: NextEditorPlugin<'example', { dependencies: [typeof pluginDog] }> = (_, api) => {
35
+ * return {
36
+ * name: 'example',
37
+ * contentComponent: () =>
38
+ * <ExampleContent
39
+ * api={api}
40
+ * />
41
+ * }
42
+ * }
43
+ * ```
44
+ *
45
+ * @param injectionApi Plugin injection API from `NextEditorPlugin`
46
+ * @param plugins Plugin names to get the shared plugin state for
47
+ * @returns A corresponding object, the keys are names of the plugin with `State` appended,
48
+ * the values are the shared state exposed by that plugin.
49
+ */
50
+ export function useSharedPluginState(injectionApi, plugins) {
51
+ // Create a memoized object containing the named plugins
52
+ const namedExternalPlugins = useMemo(() => plugins.reduce((acc, pluginName) => ({
53
+ ...acc,
54
+ [`${pluginName}State`]: injectionApi === null || injectionApi === void 0 ? void 0 : injectionApi.dependencies[pluginName]
55
+ }), {}), [injectionApi === null || injectionApi === void 0 ? void 0 : injectionApi.dependencies, plugins]);
56
+ return useSharedPluginStateInternal(namedExternalPlugins);
57
+ }
58
+ function useSharedPluginStateInternal(externalPlugins) {
59
+ const [state, setState] = useState(mapValues(externalPlugins, value => value === null || value === void 0 ? void 0 : value.sharedState.currentState()));
60
+ useEffect(() => {
61
+ const unsubscribeListeners = Object.entries(externalPlugins).map(([pluginKey, externalPlugin]) => externalPlugin === null || externalPlugin === void 0 ? void 0 : externalPlugin.sharedState.onChange(({
62
+ nextSharedState,
63
+ prevSharedState
64
+ }) => {
65
+ if (prevSharedState === nextSharedState) {
66
+ return;
67
+ }
68
+ setState(state => ({
69
+ ...state,
70
+ [pluginKey]: nextSharedState
71
+ }));
72
+ }));
73
+ return () => {
74
+ unsubscribeListeners.forEach(cb => cb === null || cb === void 0 ? void 0 : cb());
75
+ };
76
+ }, [externalPlugins]);
77
+ return state;
78
+ }
@@ -1,5 +1,5 @@
1
1
  import { defineMessages } from 'react-intl-next';
2
- export var codeBlockCopyButtonMessages = defineMessages({
2
+ export const codeBlockButtonMessages = defineMessages({
3
3
  copyCodeToClipboard: {
4
4
  id: 'fabric.editor.codeBlockCopyButton.copyToClipboard',
5
5
  defaultMessage: 'Copy as text',
@@ -9,5 +9,15 @@ export var codeBlockCopyButtonMessages = defineMessages({
9
9
  id: 'fabric.editor.codeBlockCopyButton.copiedToClipboard',
10
10
  defaultMessage: 'Copied!',
11
11
  description: 'Copied the content of the code block as text to clipboard'
12
+ },
13
+ wrapCode: {
14
+ id: 'fabric.editor.codeBlockWrapButton.wrapCodeBlock',
15
+ defaultMessage: 'Turn on wrap',
16
+ description: 'Wrap the content of the code block'
17
+ },
18
+ unwrapCode: {
19
+ id: 'fabric.editor.codeBlockWrapButton.unwrapCodeBlock',
20
+ defaultMessage: 'Turn off wrap',
21
+ description: 'Wrap the content of the code block'
12
22
  }
13
23
  });
@@ -2,7 +2,7 @@ import { defineMessages } from 'react-intl-next';
2
2
  export { codeBidiWarningMessages } from './codeBidiWarning';
3
3
  export { linkMessages } from './link';
4
4
  export { unsupportedContentMessages } from './unsupportedContent';
5
- export { codeBlockCopyButtonMessages } from './codeBlockCopyButton';
5
+ export { codeBlockButtonMessages } from './codeBlockButton';
6
6
  export { toolbarInsertBlockMessages } from './insert-block';
7
7
  export default defineMessages({
8
8
  layoutFixedWidth: {
@@ -51,4 +51,13 @@ export function normalizeFeatureFlags(rawFeatureFlags, options) {
51
51
  }
52
52
  return flags;
53
53
  }, {});
54
+ }
55
+
56
+ /**
57
+ * Transforms FeatureFlags to a type safe string array of the enabled feature flags.
58
+ *
59
+ * Useful for analytics and analysis purposes.
60
+ */
61
+ export function getEnabledFeatureFlagKeys(featureFlags) {
62
+ return Object.keys(featureFlags).filter(key => featureFlags[key] === true);
54
63
  }
@@ -7,25 +7,18 @@ function hasGetSharedState(plugin) {
7
7
  function hasActions(plugin) {
8
8
  return typeof plugin.actions === 'object';
9
9
  }
10
- const DREAM_TARGET_60_FPS = 16;
11
- /*
12
- *
13
- * After some investigations, we discovered this is the best ratio for our current Editor: 80ms. That means is five times bigger than the 60fps dream target.
14
- *
15
- * In the future, once we remove the entire WithPluginState, We may decide to reduce this value.
16
- *
17
- */
18
- const THROTTLE_CALLS_FOR_MILLISECONDS = DREAM_TARGET_60_FPS * 5;
19
- const notifyListenersThrottled = throttle(({
20
- newEditorState,
21
- oldEditorState,
10
+ const filterPluginsWithListeners = ({
22
11
  listeners,
23
12
  plugins
13
+ }) => Array.from(listeners.keys()).map(pluginName => plugins.get(pluginName)).filter(plugin => plugin !== undefined && hasGetSharedState(plugin));
14
+ const extractSharedStateFromPlugins = ({
15
+ oldEditorState,
16
+ newEditorState,
17
+ plugins
24
18
  }) => {
25
19
  const isInitialization = !oldEditorState && newEditorState;
26
- const callbacks = [];
27
- for (let pluginName of listeners.keys()) {
28
- const plugin = plugins.get(pluginName);
20
+ const result = new Map();
21
+ for (let plugin of plugins) {
29
22
  if (!plugin || !hasGetSharedState(plugin)) {
30
23
  continue;
31
24
  }
@@ -33,18 +26,33 @@ const notifyListenersThrottled = throttle(({
33
26
  const prevSharedState = !isInitialization && oldEditorState ? plugin.getSharedState(oldEditorState) : undefined;
34
27
  const isSamePluginState = isEqual(prevSharedState, nextSharedState);
35
28
  if (isInitialization || !isSamePluginState) {
36
- (listeners.get(pluginName) || new Set()).forEach(callback => {
37
- callbacks.push(callback.bind(callback, {
38
- nextSharedState,
39
- prevSharedState
40
- }));
29
+ result.set(plugin.name, {
30
+ nextSharedState,
31
+ prevSharedState
41
32
  });
42
33
  }
43
34
  }
35
+ return result;
36
+ };
37
+ const THROTTLE_CALLS_FOR_MILLISECONDS = 0;
38
+ const notifyListenersThrottled = throttle(({
39
+ listeners,
40
+ updatesToNotifyQueue
41
+ }) => {
42
+ const callbacks = [];
43
+ for (let [pluginName, diffs] of updatesToNotifyQueue.entries()) {
44
+ const pluginListeners = listeners.get(pluginName) || [];
45
+ pluginListeners.forEach(callback => {
46
+ diffs.forEach(diff => {
47
+ callbacks.push(callback.bind(callback, diff));
48
+ });
49
+ });
50
+ }
51
+ updatesToNotifyQueue.clear();
44
52
  if (callbacks.length === 0) {
45
53
  return;
46
54
  }
47
- callbacks.forEach(cb => {
55
+ callbacks.reverse().forEach(cb => {
48
56
  cb();
49
57
  });
50
58
  }, THROTTLE_CALLS_FOR_MILLISECONDS);
@@ -66,6 +74,7 @@ export class SharedStateAPI {
66
74
  constructor({
67
75
  getEditorState
68
76
  }) {
77
+ _defineProperty(this, "updatesToNotifyQueue", new Map());
69
78
  this.getEditorState = getEditorState;
70
79
  this.listeners = new Map();
71
80
  }
@@ -81,39 +90,56 @@ export class SharedStateAPI {
81
90
  const pluginName = plugin.name;
82
91
  return {
83
92
  currentState: () => {
84
- const state = this.getEditorState();
85
- if (!state || !hasGetSharedState(plugin)) {
93
+ if (!hasGetSharedState(plugin)) {
86
94
  return undefined;
87
95
  }
96
+ const state = this.getEditorState();
88
97
  return plugin.getSharedState(state);
89
98
  },
90
99
  onChange: sub => {
91
100
  const pluginListeners = this.listeners.get(pluginName) || new Set();
92
101
  pluginListeners.add(sub);
93
102
  this.listeners.set(pluginName, pluginListeners);
94
- return () => {
95
- (this.listeners.get(pluginName) || new Set()).delete(sub);
96
- };
103
+ return () => this.cleanupSubscription(pluginName, sub);
97
104
  }
98
105
  };
99
106
  }
107
+ cleanupSubscription(pluginName, sub) {
108
+ (this.listeners.get(pluginName) || new Set()).delete(sub);
109
+ }
100
110
  notifyListeners({
101
111
  newEditorState,
102
112
  oldEditorState,
103
113
  plugins
104
114
  }) {
105
115
  const {
106
- listeners
116
+ listeners,
117
+ updatesToNotifyQueue
107
118
  } = this;
108
- notifyListenersThrottled({
109
- newEditorState,
119
+ const pluginsFiltered = filterPluginsWithListeners({
120
+ plugins,
121
+ listeners
122
+ });
123
+ const sharedStateDiffs = extractSharedStateFromPlugins({
110
124
  oldEditorState,
111
- listeners,
112
- plugins
125
+ newEditorState,
126
+ plugins: pluginsFiltered
127
+ });
128
+ if (sharedStateDiffs.size === 0) {
129
+ return;
130
+ }
131
+ for (let [pluginName, nextDiff] of sharedStateDiffs) {
132
+ const currentDiffQueue = updatesToNotifyQueue.get(pluginName) || [];
133
+ updatesToNotifyQueue.set(pluginName, [...currentDiffQueue, nextDiff]);
134
+ }
135
+ notifyListenersThrottled({
136
+ updatesToNotifyQueue,
137
+ listeners
113
138
  });
114
139
  }
115
140
  destroy() {
116
141
  this.listeners.clear();
142
+ this.updatesToNotifyQueue.clear();
117
143
  }
118
144
  }
119
145
  export class EditorPluginInjectionAPI {
@@ -152,8 +178,13 @@ export class EditorPluginInjectionAPI {
152
178
  actionsAPI,
153
179
  getPluginByName
154
180
  } = this;
155
- const externalPlugins = new Proxy({}, {
181
+ const dependencies = new Proxy({}, {
156
182
  get: function (target, prop, receiver) {
183
+ // If we pass this as a prop React hates us
184
+ // Let's just reflect the result and ignore these
185
+ if (prop === 'toJSON') {
186
+ return Reflect.get(target, prop);
187
+ }
157
188
  const plugin = getPluginByName(prop);
158
189
  if (!plugin) {
159
190
  // eslint-disable-next-line
@@ -170,7 +201,7 @@ export class EditorPluginInjectionAPI {
170
201
  }
171
202
  });
172
203
  return {
173
- externalPlugins
204
+ dependencies
174
205
  };
175
206
  }
176
207
  }
@@ -27,6 +27,8 @@ export const TableSharedCssClassName = {
27
27
  TABLE_STICKY_WRAPPER: `${tablePrefixSelector}-sticky-wrapper`,
28
28
  TABLE_STICKY_SENTINEL_TOP: `${tablePrefixSelector}-sticky-sentinel-top`,
29
29
  TABLE_STICKY_SENTINEL_BOTTOM: `${tablePrefixSelector}-sticky-sentinel-bottom`,
30
+ TABLE_SHADOW_SENTINEL_LEFT: `${tablePrefixSelector}-shadow-sentinel-left`,
31
+ TABLE_SHADOW_SENTINEL_RIGHT: `${tablePrefixSelector}-shadow-sentinel-right`,
30
32
  TABLE_CELL_NODEVIEW_CONTENT_DOM: tableCellContentDomSelector,
31
33
  TABLE_CELL_WRAPPER: tableCellSelector,
32
34
  TABLE_HEADER_CELL_WRAPPER: tableHeaderSelector,
@@ -8,7 +8,7 @@ import { themed } from '@atlaskit/theme/components';
8
8
  import { borderRadius, gridSize } from '@atlaskit/theme/constants';
9
9
  import Layer from '../Layer';
10
10
  const packageName = "@atlaskit/editor-common";
11
- const packageVersion = "72.6.0";
11
+ const packageVersion = "72.7.0";
12
12
  const halfFocusRing = 1;
13
13
  const dropOffset = `0, ${gridSize()}px`;
14
14
  class DropList extends Component {
@@ -0,0 +1,16 @@
1
+ import { borderColorPalette as colorPalette } from '@atlaskit/adf-schema';
2
+ import { DEFAULT_BORDER_COLOR } from './common';
3
+ import getColorMessage from './getColorMessage';
4
+ import paletteMessages from './paletteMessages';
5
+ const borderColorPalette = [];
6
+ colorPalette.forEach((label, color) => {
7
+ const key = label.toLowerCase().replace(' ', '-');
8
+ const message = getColorMessage(paletteMessages, key);
9
+ borderColorPalette.push({
10
+ value: color,
11
+ label,
12
+ border: DEFAULT_BORDER_COLOR,
13
+ message
14
+ });
15
+ });
16
+ export default borderColorPalette;
@@ -1,2 +1,2 @@
1
1
  export { DEFAULT_BORDER_COLOR } from './common';
2
- export { textPaletteTooltipMessages, backgroundPaletteTooltipMessages } from './paletteMessagesTokenModeNames';
2
+ export { textPaletteTooltipMessages, backgroundPaletteTooltipMessages, borderPaletteTooltipMessages } from './paletteMessagesTokenModeNames';
@@ -249,4 +249,28 @@ export const darkBackgroundPaletteTooltipMessages = {
249
249
  export const backgroundPaletteTooltipMessages = {
250
250
  light: lightBackgroundPaletteTooltipMessages,
251
251
  dark: darkBackgroundPaletteTooltipMessages
252
+ };
253
+ const lightBorderPaletteTooltipMessages = defineMessages({
254
+ '#091E4224': {
255
+ id: 'fabric.theme.subtle-gray',
256
+ defaultMessage: 'Subtle gray',
257
+ description: 'Name of a color'
258
+ },
259
+ '#758195': {
260
+ id: 'fabric.theme.gray',
261
+ defaultMessage: 'Gray',
262
+ description: 'Name of a color'
263
+ },
264
+ '#172B4D': {
265
+ id: 'fabric.theme.bold-gray',
266
+ defaultMessage: 'Bold gray',
267
+ description: 'Name of a color'
268
+ }
269
+ });
270
+ const darkBorderPaletteTooltipMessages = {
271
+ ...lightBorderPaletteTooltipMessages
272
+ };
273
+ export const borderPaletteTooltipMessages = {
274
+ light: lightBorderPaletteTooltipMessages,
275
+ dark: darkBorderPaletteTooltipMessages
252
276
  };
@@ -6,5 +6,6 @@ export { default as colorPaletteMessages } from './ColorPalette/Palettes/palette
6
6
  export { panelBackgroundPalette, panelDarkModeBackgroundPalette } from './ColorPalette/Palettes/panelBackgroundPalette';
7
7
  export { lightModeStatusColorPalette, darkModeStatusColorPalette } from './ColorPalette/Palettes/statusColorPalette';
8
8
  export { textColorPalette } from './ColorPalette/Palettes/textColorPalette';
9
- export { backgroundPaletteTooltipMessages, textPaletteTooltipMessages } from './ColorPalette/Palettes';
10
- export { DEFAULT_BORDER_COLOR } from './ColorPalette/Palettes/common';
9
+ export { backgroundPaletteTooltipMessages, borderPaletteTooltipMessages, textPaletteTooltipMessages } from './ColorPalette/Palettes';
10
+ export { DEFAULT_BORDER_COLOR } from './ColorPalette/Palettes/common';
11
+ export { default as borderColorPalette } from './ColorPalette/Palettes/borderColorPalette';
@@ -842,6 +842,13 @@ export const getValidMark = (mark, adfStage = 'final') => {
842
842
  attrs
843
843
  };
844
844
  }
845
+ case 'border':
846
+ {
847
+ return {
848
+ type,
849
+ attrs
850
+ };
851
+ }
845
852
  }
846
853
  }
847
854
  return null;
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-common",
3
- "version": "72.6.0",
3
+ "version": "72.7.0",
4
4
  "sideEffects": false
5
5
  }
@@ -220,6 +220,7 @@ export var ACTION_SUBJECT_ID;
220
220
  ACTION_SUBJECT_ID["ANNOTATE_BUTTON"] = "annotateButton";
221
221
  ACTION_SUBJECT_ID["AVATAR_GROUP_PLUGIN"] = "AvatarGroupInPlugin";
222
222
  ACTION_SUBJECT_ID["BLOCK_QUOTE"] = "blockQuote";
223
+ ACTION_SUBJECT_ID["BORDER"] = "border";
223
224
  ACTION_SUBJECT_ID["BUTTON_CATEGORY"] = "categoryButton";
224
225
  ACTION_SUBJECT_ID["BUTTON_FEEDBACK"] = "feedbackButton";
225
226
  ACTION_SUBJECT_ID["BUTTON_HELP"] = "helpButton";
@@ -229,6 +230,8 @@ export var ACTION_SUBJECT_ID;
229
230
  ACTION_SUBJECT_ID["CARD_INLINE"] = "inlineCard";
230
231
  ACTION_SUBJECT_ID["CELL"] = "cell";
231
232
  ACTION_SUBJECT_ID["CODE_BLOCK"] = "codeBlock";
233
+ ACTION_SUBJECT_ID["CODEBLOCK_COPY"] = "codeBlockCopy";
234
+ ACTION_SUBJECT_ID["CODEBLOCK_WRAP"] = "codeBlockWrap";
232
235
  ACTION_SUBJECT_ID["DATE"] = "date";
233
236
  ACTION_SUBJECT_ID["DATE_DAY"] = "day";
234
237
  ACTION_SUBJECT_ID["DATE_MONTH"] = "month";
@@ -1,2 +1,3 @@
1
1
  export { default as usePreviousState } from './usePreviousState';
2
- export { default as useConstructor } from './useConstructor';
2
+ export { default as useConstructor } from './useConstructor';
3
+ export { useSharedPluginState } from './useSharedPluginState';
@@ -0,0 +1,95 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
4
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
5
+ import { useEffect, useMemo, useState } from 'react';
6
+ /**
7
+ *
8
+ * Directly map object values
9
+ *
10
+ * @param object The object to transform
11
+ * @param mapFunction The function to map an old value to new one
12
+ * @returns Object with the same key but transformed values
13
+ *
14
+ */
15
+ function mapValues(object, mapFunction) {
16
+ return Object.entries(object).reduce(function (acc, _ref) {
17
+ var _ref2 = _slicedToArray(_ref, 2),
18
+ key = _ref2[0],
19
+ value = _ref2[1];
20
+ return _objectSpread(_objectSpread({}, acc), {}, _defineProperty({}, key, mapFunction(value)));
21
+ }, {});
22
+ }
23
+
24
+ /**
25
+ *
26
+ * Used to return the current plugin state of
27
+ * input dependencies
28
+ *
29
+ * Example in plugin:
30
+ *
31
+ * ```typescript
32
+ * function ExampleContent({ api }: Props) {
33
+ * const { dogState, exampleState } = useSharedPluginState(
34
+ * api,
35
+ * ['dog', 'example']
36
+ * )
37
+ * return <p>{ dogState.title } { exampleState.description }</p>
38
+ * }
39
+ *
40
+ * const examplePlugin: NextEditorPlugin<'example', { dependencies: [typeof pluginDog] }> = (_, api) => {
41
+ * return {
42
+ * name: 'example',
43
+ * contentComponent: () =>
44
+ * <ExampleContent
45
+ * api={api}
46
+ * />
47
+ * }
48
+ * }
49
+ * ```
50
+ *
51
+ * @param injectionApi Plugin injection API from `NextEditorPlugin`
52
+ * @param plugins Plugin names to get the shared plugin state for
53
+ * @returns A corresponding object, the keys are names of the plugin with `State` appended,
54
+ * the values are the shared state exposed by that plugin.
55
+ */
56
+ export function useSharedPluginState(injectionApi, plugins) {
57
+ // Create a memoized object containing the named plugins
58
+ var namedExternalPlugins = useMemo(function () {
59
+ return plugins.reduce(function (acc, pluginName) {
60
+ return _objectSpread(_objectSpread({}, acc), {}, _defineProperty({}, "".concat(pluginName, "State"), injectionApi === null || injectionApi === void 0 ? void 0 : injectionApi.dependencies[pluginName]));
61
+ }, {});
62
+ }, [injectionApi === null || injectionApi === void 0 ? void 0 : injectionApi.dependencies, plugins]);
63
+ return useSharedPluginStateInternal(namedExternalPlugins);
64
+ }
65
+ function useSharedPluginStateInternal(externalPlugins) {
66
+ var _useState = useState(mapValues(externalPlugins, function (value) {
67
+ return value === null || value === void 0 ? void 0 : value.sharedState.currentState();
68
+ })),
69
+ _useState2 = _slicedToArray(_useState, 2),
70
+ state = _useState2[0],
71
+ setState = _useState2[1];
72
+ useEffect(function () {
73
+ var unsubscribeListeners = Object.entries(externalPlugins).map(function (_ref3) {
74
+ var _ref4 = _slicedToArray(_ref3, 2),
75
+ pluginKey = _ref4[0],
76
+ externalPlugin = _ref4[1];
77
+ return externalPlugin === null || externalPlugin === void 0 ? void 0 : externalPlugin.sharedState.onChange(function (_ref5) {
78
+ var nextSharedState = _ref5.nextSharedState,
79
+ prevSharedState = _ref5.prevSharedState;
80
+ if (prevSharedState === nextSharedState) {
81
+ return;
82
+ }
83
+ setState(function (state) {
84
+ return _objectSpread(_objectSpread({}, state), {}, _defineProperty({}, pluginKey, nextSharedState));
85
+ });
86
+ });
87
+ });
88
+ return function () {
89
+ unsubscribeListeners.forEach(function (cb) {
90
+ return cb === null || cb === void 0 ? void 0 : cb();
91
+ });
92
+ };
93
+ }, [externalPlugins]);
94
+ return state;
95
+ }
@@ -1,5 +1,5 @@
1
1
  import { defineMessages } from 'react-intl-next';
2
- export const codeBlockCopyButtonMessages = defineMessages({
2
+ export var codeBlockButtonMessages = defineMessages({
3
3
  copyCodeToClipboard: {
4
4
  id: 'fabric.editor.codeBlockCopyButton.copyToClipboard',
5
5
  defaultMessage: 'Copy as text',
@@ -9,5 +9,15 @@ export const codeBlockCopyButtonMessages = defineMessages({
9
9
  id: 'fabric.editor.codeBlockCopyButton.copiedToClipboard',
10
10
  defaultMessage: 'Copied!',
11
11
  description: 'Copied the content of the code block as text to clipboard'
12
+ },
13
+ wrapCode: {
14
+ id: 'fabric.editor.codeBlockWrapButton.wrapCodeBlock',
15
+ defaultMessage: 'Turn on wrap',
16
+ description: 'Wrap the content of the code block'
17
+ },
18
+ unwrapCode: {
19
+ id: 'fabric.editor.codeBlockWrapButton.unwrapCodeBlock',
20
+ defaultMessage: 'Turn off wrap',
21
+ description: 'Wrap the content of the code block'
12
22
  }
13
23
  });
@@ -2,7 +2,7 @@ import { defineMessages } from 'react-intl-next';
2
2
  export { codeBidiWarningMessages } from './codeBidiWarning';
3
3
  export { linkMessages } from './link';
4
4
  export { unsupportedContentMessages } from './unsupportedContent';
5
- export { codeBlockCopyButtonMessages } from './codeBlockCopyButton';
5
+ export { codeBlockButtonMessages } from './codeBlockButton';
6
6
  export { toolbarInsertBlockMessages } from './insert-block';
7
7
  export default defineMessages({
8
8
  layoutFixedWidth: {
@@ -65,4 +65,15 @@ export function normalizeFeatureFlags(rawFeatureFlags, options) {
65
65
  }
66
66
  return flags;
67
67
  }, {});
68
+ }
69
+
70
+ /**
71
+ * Transforms FeatureFlags to a type safe string array of the enabled feature flags.
72
+ *
73
+ * Useful for analytics and analysis purposes.
74
+ */
75
+ export function getEnabledFeatureFlagKeys(featureFlags) {
76
+ return Object.keys(featureFlags).filter(function (key) {
77
+ return featureFlags[key] === true;
78
+ });
68
79
  }