@atlaskit/editor-common 75.3.0 → 75.3.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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @atlaskit/editor-common
2
2
 
3
+ ## 75.3.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`32e751116bb`](https://bitbucket.org/atlassian/atlassian-frontend/commits/32e751116bb) - [ED-20088] Debounce updates into the useSharedPluginState to avoid blocking the main thread with unnecessary UI updates
8
+
3
9
  ## 75.3.0
4
10
 
5
11
  ### Minor Changes
@@ -8,6 +8,7 @@ exports.useSharedPluginState = useSharedPluginState;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
10
  var _react = require("react");
11
+ var _debounce = _interopRequireDefault(require("lodash/debounce"));
11
12
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
12
13
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
13
14
  /**
@@ -39,6 +40,35 @@ function useStaticPlugins(plugins) {
39
40
  }
40
41
 
41
42
  /**
43
+ *
44
+ * ⚠️⚠️⚠️ This is a debounced hook ⚠️⚠️⚠️
45
+ * If the plugins you are listening to generate multiple shared states while the user is typing,
46
+ * your React Component will get only the last one.
47
+ *
48
+ * Usually, for UI updates, you may need only the last state. But, if you have a specific scenario requiring you to access all states,
49
+ * do not use this hook. Instead, you can subscribe directly to the plugin sharedState API:
50
+ *
51
+ * ```typescript
52
+ *
53
+ * function ExampleSpecialCase({ api }: Props) {
54
+ * const [dogState, setDogState] = React.useState(null);
55
+ * useEffect(() => {
56
+ * const unsub = api.dog.sharedState.onChange(({ nextSharedState, prevSharedState }) => {
57
+ * setDogState(nextSharedState);
58
+ * });
59
+ *
60
+ * return unsub;
61
+ * }, [api]);
62
+ *
63
+ * useEffect(() => {
64
+ * someCriticalAndWeirdUseCase(dogState);
65
+ *
66
+ * }, [dogState]);
67
+ *
68
+ * return null;
69
+ * }
70
+ *
71
+ * ```
42
72
  *
43
73
  * Used to return the current plugin state of
44
74
  * input dependencies
@@ -88,7 +118,13 @@ function useSharedPluginStateInternal(externalPlugins) {
88
118
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
89
119
  pluginStates = _useState2[0],
90
120
  setPluginState = _useState2[1];
121
+ var refStates = (0, _react.useRef)({});
91
122
  (0, _react.useLayoutEffect)(function () {
123
+ var debouncedPluginStateUpdate = (0, _debounce.default)(function () {
124
+ setPluginState(function (currentPluginStates) {
125
+ return _objectSpread(_objectSpread({}, currentPluginStates), refStates.current);
126
+ });
127
+ });
92
128
  var unsubs = Object.entries(externalPlugins).map(function (_ref3) {
93
129
  var _ref4 = (0, _slicedToArray2.default)(_ref3, 2),
94
130
  pluginKey = _ref4[0],
@@ -99,12 +135,12 @@ function useSharedPluginStateInternal(externalPlugins) {
99
135
  if (prevSharedState === nextSharedState) {
100
136
  return;
101
137
  }
102
- setPluginState(function (currentPluginStates) {
103
- return _objectSpread(_objectSpread({}, currentPluginStates), {}, (0, _defineProperty2.default)({}, pluginKey, nextSharedState));
104
- });
138
+ refStates.current[pluginKey] = nextSharedState;
139
+ debouncedPluginStateUpdate();
105
140
  });
106
141
  });
107
142
  return function () {
143
+ refStates.current = {};
108
144
  unsubs.forEach(function (cb) {
109
145
  return cb === null || cb === void 0 ? void 0 : cb();
110
146
  });
@@ -16,7 +16,7 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
16
16
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
17
17
  var SENTRY_DSN = 'https://0b10c8e02fb44d8796c047b102c9bee8@o55978.ingest.sentry.io/4505129224110080';
18
18
  var packageName = 'editor-common'; // Sentry doesn't accept '/' in its releases https://docs.sentry.io/platforms/javascript/configuration/releases/
19
- var packageVersion = "75.3.0";
19
+ var packageVersion = "75.3.1";
20
20
  var sanitiseSentryEvents = function sanitiseSentryEvents(data, _hint) {
21
21
  // Remove URL as it has UGC
22
22
  // TODO: Sanitise the URL instead of just removing it
@@ -24,7 +24,7 @@ var _templateObject, _templateObject2, _templateObject3;
24
24
  function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2.default)(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2.default)(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2.default)(this, result); }; }
25
25
  function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } /** @jsx jsx */
26
26
  var packageName = "@atlaskit/editor-common";
27
- var packageVersion = "75.3.0";
27
+ var packageVersion = "75.3.1";
28
28
  var halfFocusRing = 1;
29
29
  var dropOffset = '0, 8';
30
30
  var DropList = /*#__PURE__*/function (_Component) {
@@ -1,4 +1,5 @@
1
- import { useLayoutEffect, useMemo, useState } from 'react';
1
+ import { useLayoutEffect, useMemo, useRef, useState } from 'react';
2
+ import debounce from 'lodash/debounce';
2
3
  /**
3
4
  *
4
5
  * Directly map object values
@@ -24,6 +25,35 @@ function useStaticPlugins(plugins) {
24
25
  }
25
26
 
26
27
  /**
28
+ *
29
+ * ⚠️⚠️⚠️ This is a debounced hook ⚠️⚠️⚠️
30
+ * If the plugins you are listening to generate multiple shared states while the user is typing,
31
+ * your React Component will get only the last one.
32
+ *
33
+ * Usually, for UI updates, you may need only the last state. But, if you have a specific scenario requiring you to access all states,
34
+ * do not use this hook. Instead, you can subscribe directly to the plugin sharedState API:
35
+ *
36
+ * ```typescript
37
+ *
38
+ * function ExampleSpecialCase({ api }: Props) {
39
+ * const [dogState, setDogState] = React.useState(null);
40
+ * useEffect(() => {
41
+ * const unsub = api.dog.sharedState.onChange(({ nextSharedState, prevSharedState }) => {
42
+ * setDogState(nextSharedState);
43
+ * });
44
+ *
45
+ * return unsub;
46
+ * }, [api]);
47
+ *
48
+ * useEffect(() => {
49
+ * someCriticalAndWeirdUseCase(dogState);
50
+ *
51
+ * }, [dogState]);
52
+ *
53
+ * return null;
54
+ * }
55
+ *
56
+ * ```
27
57
  *
28
58
  * Used to return the current plugin state of
29
59
  * input dependencies
@@ -67,7 +97,14 @@ export function useSharedPluginState(injectionApi, plugins) {
67
97
  }
68
98
  function useSharedPluginStateInternal(externalPlugins) {
69
99
  const [pluginStates, setPluginState] = useState(mapValues(externalPlugins, value => value === null || value === void 0 ? void 0 : value.sharedState.currentState()));
100
+ const refStates = useRef({});
70
101
  useLayoutEffect(() => {
102
+ const debouncedPluginStateUpdate = debounce(() => {
103
+ setPluginState(currentPluginStates => ({
104
+ ...currentPluginStates,
105
+ ...refStates.current
106
+ }));
107
+ });
71
108
  const unsubs = Object.entries(externalPlugins).map(([pluginKey, externalPlugin]) => {
72
109
  return externalPlugin === null || externalPlugin === void 0 ? void 0 : externalPlugin.sharedState.onChange(({
73
110
  nextSharedState,
@@ -76,13 +113,12 @@ function useSharedPluginStateInternal(externalPlugins) {
76
113
  if (prevSharedState === nextSharedState) {
77
114
  return;
78
115
  }
79
- setPluginState(currentPluginStates => ({
80
- ...currentPluginStates,
81
- [pluginKey]: nextSharedState
82
- }));
116
+ refStates.current[pluginKey] = nextSharedState;
117
+ debouncedPluginStateUpdate();
83
118
  });
84
119
  });
85
120
  return () => {
121
+ refStates.current = {};
86
122
  unsubs.forEach(cb => cb === null || cb === void 0 ? void 0 : cb());
87
123
  };
88
124
  // Do not re-render due to state changes, we only need to check this when
@@ -1,6 +1,6 @@
1
1
  const SENTRY_DSN = 'https://0b10c8e02fb44d8796c047b102c9bee8@o55978.ingest.sentry.io/4505129224110080';
2
2
  const packageName = 'editor-common'; // Sentry doesn't accept '/' in its releases https://docs.sentry.io/platforms/javascript/configuration/releases/
3
- const packageVersion = "75.3.0";
3
+ const packageVersion = "75.3.1";
4
4
  const sanitiseSentryEvents = (data, _hint) => {
5
5
  // Remove URL as it has UGC
6
6
  // TODO: Sanitise the URL instead of just removing it
@@ -9,7 +9,7 @@ import { themed } from '@atlaskit/theme/components';
9
9
  import { borderRadius } from '@atlaskit/theme/constants';
10
10
  import Layer from '../Layer';
11
11
  const packageName = "@atlaskit/editor-common";
12
- const packageVersion = "75.3.0";
12
+ const packageVersion = "75.3.1";
13
13
  const halfFocusRing = 1;
14
14
  const dropOffset = '0, 8';
15
15
  class DropList extends Component {
@@ -2,7 +2,8 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
3
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
4
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
5
- import { useLayoutEffect, useMemo, useState } from 'react';
5
+ import { useLayoutEffect, useMemo, useRef, useState } from 'react';
6
+ import debounce from 'lodash/debounce';
6
7
  /**
7
8
  *
8
9
  * Directly map object values
@@ -32,6 +33,35 @@ function useStaticPlugins(plugins) {
32
33
  }
33
34
 
34
35
  /**
36
+ *
37
+ * ⚠️⚠️⚠️ This is a debounced hook ⚠️⚠️⚠️
38
+ * If the plugins you are listening to generate multiple shared states while the user is typing,
39
+ * your React Component will get only the last one.
40
+ *
41
+ * Usually, for UI updates, you may need only the last state. But, if you have a specific scenario requiring you to access all states,
42
+ * do not use this hook. Instead, you can subscribe directly to the plugin sharedState API:
43
+ *
44
+ * ```typescript
45
+ *
46
+ * function ExampleSpecialCase({ api }: Props) {
47
+ * const [dogState, setDogState] = React.useState(null);
48
+ * useEffect(() => {
49
+ * const unsub = api.dog.sharedState.onChange(({ nextSharedState, prevSharedState }) => {
50
+ * setDogState(nextSharedState);
51
+ * });
52
+ *
53
+ * return unsub;
54
+ * }, [api]);
55
+ *
56
+ * useEffect(() => {
57
+ * someCriticalAndWeirdUseCase(dogState);
58
+ *
59
+ * }, [dogState]);
60
+ *
61
+ * return null;
62
+ * }
63
+ *
64
+ * ```
35
65
  *
36
66
  * Used to return the current plugin state of
37
67
  * input dependencies
@@ -81,7 +111,13 @@ function useSharedPluginStateInternal(externalPlugins) {
81
111
  _useState2 = _slicedToArray(_useState, 2),
82
112
  pluginStates = _useState2[0],
83
113
  setPluginState = _useState2[1];
114
+ var refStates = useRef({});
84
115
  useLayoutEffect(function () {
116
+ var debouncedPluginStateUpdate = debounce(function () {
117
+ setPluginState(function (currentPluginStates) {
118
+ return _objectSpread(_objectSpread({}, currentPluginStates), refStates.current);
119
+ });
120
+ });
85
121
  var unsubs = Object.entries(externalPlugins).map(function (_ref3) {
86
122
  var _ref4 = _slicedToArray(_ref3, 2),
87
123
  pluginKey = _ref4[0],
@@ -92,12 +128,12 @@ function useSharedPluginStateInternal(externalPlugins) {
92
128
  if (prevSharedState === nextSharedState) {
93
129
  return;
94
130
  }
95
- setPluginState(function (currentPluginStates) {
96
- return _objectSpread(_objectSpread({}, currentPluginStates), {}, _defineProperty({}, pluginKey, nextSharedState));
97
- });
131
+ refStates.current[pluginKey] = nextSharedState;
132
+ debouncedPluginStateUpdate();
98
133
  });
99
134
  });
100
135
  return function () {
136
+ refStates.current = {};
101
137
  unsubs.forEach(function (cb) {
102
138
  return cb === null || cb === void 0 ? void 0 : cb();
103
139
  });
@@ -6,7 +6,7 @@ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbol
6
6
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
7
7
  var SENTRY_DSN = 'https://0b10c8e02fb44d8796c047b102c9bee8@o55978.ingest.sentry.io/4505129224110080';
8
8
  var packageName = 'editor-common'; // Sentry doesn't accept '/' in its releases https://docs.sentry.io/platforms/javascript/configuration/releases/
9
- var packageVersion = "75.3.0";
9
+ var packageVersion = "75.3.1";
10
10
  var sanitiseSentryEvents = function sanitiseSentryEvents(data, _hint) {
11
11
  // Remove URL as it has UGC
12
12
  // TODO: Sanitise the URL instead of just removing it
@@ -19,7 +19,7 @@ import { themed } from '@atlaskit/theme/components';
19
19
  import { borderRadius } from '@atlaskit/theme/constants';
20
20
  import Layer from '../Layer';
21
21
  var packageName = "@atlaskit/editor-common";
22
- var packageVersion = "75.3.0";
22
+ var packageVersion = "75.3.1";
23
23
  var halfFocusRing = 1;
24
24
  var dropOffset = '0, 8';
25
25
  var DropList = /*#__PURE__*/function (_Component) {
@@ -4,6 +4,35 @@ type NamedPluginStatesFromInjectionAPI<API extends PublicPluginAPI<any> | undefi
4
4
  }>;
5
5
  type ExtractPluginNames<API extends PublicPluginAPI<any>> = API extends PublicPluginAPI<any> ? keyof API : never;
6
6
  /**
7
+ *
8
+ * ⚠️⚠️⚠️ This is a debounced hook ⚠️⚠️⚠️
9
+ * If the plugins you are listening to generate multiple shared states while the user is typing,
10
+ * your React Component will get only the last one.
11
+ *
12
+ * Usually, for UI updates, you may need only the last state. But, if you have a specific scenario requiring you to access all states,
13
+ * do not use this hook. Instead, you can subscribe directly to the plugin sharedState API:
14
+ *
15
+ * ```typescript
16
+ *
17
+ * function ExampleSpecialCase({ api }: Props) {
18
+ * const [dogState, setDogState] = React.useState(null);
19
+ * useEffect(() => {
20
+ * const unsub = api.dog.sharedState.onChange(({ nextSharedState, prevSharedState }) => {
21
+ * setDogState(nextSharedState);
22
+ * });
23
+ *
24
+ * return unsub;
25
+ * }, [api]);
26
+ *
27
+ * useEffect(() => {
28
+ * someCriticalAndWeirdUseCase(dogState);
29
+ *
30
+ * }, [dogState]);
31
+ *
32
+ * return null;
33
+ * }
34
+ *
35
+ * ```
7
36
  *
8
37
  * Used to return the current plugin state of
9
38
  * input dependencies
@@ -4,6 +4,35 @@ type NamedPluginStatesFromInjectionAPI<API extends PublicPluginAPI<any> | undefi
4
4
  }>;
5
5
  type ExtractPluginNames<API extends PublicPluginAPI<any>> = API extends PublicPluginAPI<any> ? keyof API : never;
6
6
  /**
7
+ *
8
+ * ⚠️⚠️⚠️ This is a debounced hook ⚠️⚠️⚠️
9
+ * If the plugins you are listening to generate multiple shared states while the user is typing,
10
+ * your React Component will get only the last one.
11
+ *
12
+ * Usually, for UI updates, you may need only the last state. But, if you have a specific scenario requiring you to access all states,
13
+ * do not use this hook. Instead, you can subscribe directly to the plugin sharedState API:
14
+ *
15
+ * ```typescript
16
+ *
17
+ * function ExampleSpecialCase({ api }: Props) {
18
+ * const [dogState, setDogState] = React.useState(null);
19
+ * useEffect(() => {
20
+ * const unsub = api.dog.sharedState.onChange(({ nextSharedState, prevSharedState }) => {
21
+ * setDogState(nextSharedState);
22
+ * });
23
+ *
24
+ * return unsub;
25
+ * }, [api]);
26
+ *
27
+ * useEffect(() => {
28
+ * someCriticalAndWeirdUseCase(dogState);
29
+ *
30
+ * }, [dogState]);
31
+ *
32
+ * return null;
33
+ * }
34
+ *
35
+ * ```
7
36
  *
8
37
  * Used to return the current plugin state of
9
38
  * input dependencies
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-common",
3
- "version": "75.3.0",
3
+ "version": "75.3.1",
4
4
  "description": "A package that contains common classes and components for editor and renderer",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"