@atlaskit/editor-plugin-track-changes 2.2.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +88 -0
  3. package/afm-cc/tsconfig.json +9 -1
  4. package/afm-jira/tsconfig.json +6 -1
  5. package/afm-post-office/tsconfig.json +6 -1
  6. package/afm-rovo-extension/tsconfig.json +6 -1
  7. package/afm-townsquare/tsconfig.json +6 -1
  8. package/build/tsconfig.json +20 -15
  9. package/dist/cjs/pm-plugins/filterSteps.js +49 -0
  10. package/dist/cjs/pm-plugins/invertableStep.js +15 -0
  11. package/dist/cjs/pm-plugins/main.js +28 -14
  12. package/dist/cjs/pm-plugins/maxSteps.js +9 -0
  13. package/dist/cjs/pm-plugins/types.js +1 -0
  14. package/dist/cjs/trackChangesPlugin.js +19 -6
  15. package/dist/cjs/ui/TrackChangesToolbarButton.js +5 -1
  16. package/dist/es2019/pm-plugins/filterSteps.js +32 -0
  17. package/dist/es2019/pm-plugins/invertableStep.js +7 -0
  18. package/dist/es2019/pm-plugins/main.js +27 -10
  19. package/dist/es2019/pm-plugins/maxSteps.js +3 -0
  20. package/dist/es2019/pm-plugins/types.js +1 -0
  21. package/dist/es2019/trackChangesPlugin.js +20 -6
  22. package/dist/es2019/ui/TrackChangesToolbarButton.js +6 -1
  23. package/dist/esm/pm-plugins/filterSteps.js +44 -0
  24. package/dist/esm/pm-plugins/invertableStep.js +8 -0
  25. package/dist/esm/pm-plugins/main.js +27 -13
  26. package/dist/esm/pm-plugins/maxSteps.js +3 -0
  27. package/dist/esm/pm-plugins/types.js +1 -0
  28. package/dist/esm/trackChangesPlugin.js +19 -6
  29. package/dist/esm/ui/TrackChangesToolbarButton.js +5 -1
  30. package/dist/types/pm-plugins/filterSteps.d.ts +8 -0
  31. package/dist/types/pm-plugins/invertableStep.d.ts +7 -0
  32. package/dist/types/pm-plugins/main.d.ts +4 -6
  33. package/dist/types/pm-plugins/maxSteps.d.ts +1 -0
  34. package/dist/types/pm-plugins/types.d.ts +2 -1
  35. package/dist/types/trackChangesPluginType.d.ts +26 -1
  36. package/dist/types-ts4.5/pm-plugins/filterSteps.d.ts +8 -0
  37. package/dist/types-ts4.5/pm-plugins/invertableStep.d.ts +7 -0
  38. package/dist/types-ts4.5/pm-plugins/main.d.ts +4 -6
  39. package/dist/types-ts4.5/pm-plugins/maxSteps.d.ts +1 -0
  40. package/dist/types-ts4.5/pm-plugins/types.d.ts +2 -1
  41. package/dist/types-ts4.5/trackChangesPluginType.d.ts +22 -0
  42. package/docs/0-intro.tsx +44 -7
  43. package/package.json +5 -3
  44. package/tsconfig.json +16 -10
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # @atlaskit/editor-plugin-track-changes
2
2
 
3
+ ## 2.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#193925](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/193925)
8
+ [`696d65f882441`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/696d65f882441) -
9
+ Implement `resetBaseline` command for track changes plugin which can be called to reset the diff
10
+ history.
11
+
12
+ ## 2.3.0
13
+
14
+ ### Minor Changes
15
+
16
+ - [#193889](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/193889)
17
+ [`6d4374ce318fd`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/6d4374ce318fd) -
18
+ [EDITOR-1073] Add i18n for Track Changes button & toggle button on toolbar with plugin option
19
+
20
+ ### Patch Changes
21
+
22
+ - Updated dependencies
23
+
3
24
  ## 2.2.0
4
25
 
5
26
  ### Minor Changes
package/README.md CHANGED
@@ -1 +1,89 @@
1
1
  # Editor plugin track changes
2
+
3
+ Track changes plugin for @atlaskit/editor-core
4
+
5
+ ## Usage
6
+
7
+ `import { trackChangesPlugin } from '@atlaskit/editor-plugin-track-changes';`
8
+
9
+ ### Dependencies
10
+
11
+ **Required:**
12
+ - `ShowDiffPlugin` - Required for displaying track changes diff view
13
+
14
+ **Optional:**
15
+ - `PrimaryToolbarPlugin` - Required if using `showOnToolbar: true`
16
+
17
+ ### Configuration
18
+
19
+ The plugin accepts an optional configuration object:
20
+
21
+ ```typescript
22
+ trackChangesPlugin({
23
+ showOnToolbar: true // Shows track changes button in the toolbar (default: false)
24
+ })
25
+ ```
26
+
27
+ ### Example
28
+
29
+ ```typescript
30
+ import React from 'react';
31
+
32
+ import Button from '@atlaskit/button/new';
33
+ import { cssMap } from '@atlaskit/css';
34
+ import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector';
35
+ import { ComposableEditor } from '@atlaskit/editor-core/composable-editor';
36
+ import { usePreset } from '@atlaskit/editor-core/use-preset';
37
+ import { basePlugin } from '@atlaskit/editor-plugins/base';
38
+ import { Box } from '@atlaskit/primitives/compiled';
39
+ import { token } from '@atlaskit/tokens';
40
+
41
+ import { showDiffPlugin } from '@atlaskit/editor-plugin-show-diff';
42
+ import { trackChangesPlugin } from '@atlaskit/editor-plugin-track-changes';
43
+
44
+ const styles = cssMap({
45
+ aboveEditor: {
46
+ paddingTop: token('space.100'),
47
+ paddingBottom: token('space.100'),
48
+ },
49
+ everythingContainer: {
50
+ paddingTop: token('space.200'),
51
+ paddingBottom: token('space.200'),
52
+ paddingLeft: token('space.200'),
53
+ paddingRight: token('space.200'),
54
+ },
55
+ });
56
+
57
+ function Editor() {
58
+ const { preset, editorApi } = usePreset(
59
+ (builder) =>
60
+ builder.add(basePlugin).add(showDiffPlugin).add(trackChangesPlugin),
61
+ [],
62
+ );
63
+
64
+ const isSelected = useSharedPluginStateSelector(editorApi, 'trackChanges.isDisplayingChanges');
65
+
66
+ return (
67
+ <Box xcss={styles.everythingContainer}>
68
+ <Box xcss={styles.aboveEditor}>
69
+ <Button
70
+ appearance="primary"
71
+ onClick={() => {
72
+ editorApi?.core.actions.execute(
73
+ editorApi?.trackChanges.commands.toggleChanges,
74
+ );
75
+ }}
76
+ isSelected={isSelected}
77
+ >
78
+ Show Diff
79
+ </Button>
80
+ </Box>
81
+ <ComposableEditor preset={preset} />
82
+ </Box>
83
+ );
84
+ }
85
+
86
+ export default Editor;
87
+ ```
88
+
89
+ Detailed docs and example usage can be found [here](https://atlaskit.atlassian.com/packages/editor/editor-plugin-track-changes).
@@ -14,12 +14,20 @@
14
14
  "../src/**/__tests__/*",
15
15
  "../src/**/*.test.*",
16
16
  "../src/**/test.*",
17
- "../src/**/examples.*"
17
+ "../src/**/examples.*",
18
+ "../src/**/examples/*",
19
+ "../src/**/examples/**/*",
20
+ "../src/**/*.stories.*",
21
+ "../src/**/stories/*",
22
+ "../src/**/stories/**/*"
18
23
  ],
19
24
  "references": [
20
25
  {
21
26
  "path": "../../../design-system/button/afm-cc/tsconfig.json"
22
27
  },
28
+ {
29
+ "path": "../../editor-plugin-history/afm-cc/tsconfig.json"
30
+ },
23
31
  {
24
32
  "path": "../../editor-plugin-primary-toolbar/afm-cc/tsconfig.json"
25
33
  },
@@ -14,7 +14,12 @@
14
14
  "../src/**/__tests__/*",
15
15
  "../src/**/*.test.*",
16
16
  "../src/**/test.*",
17
- "../src/**/examples.*"
17
+ "../src/**/examples.*",
18
+ "../src/**/examples/*",
19
+ "../src/**/examples/**/*",
20
+ "../src/**/*.stories.*",
21
+ "../src/**/stories/*",
22
+ "../src/**/stories/**/*"
18
23
  ],
19
24
  "references": [
20
25
  {
@@ -14,7 +14,12 @@
14
14
  "../src/**/__tests__/*",
15
15
  "../src/**/*.test.*",
16
16
  "../src/**/test.*",
17
- "../src/**/examples.*"
17
+ "../src/**/examples.*",
18
+ "../src/**/examples/*",
19
+ "../src/**/examples/**/*",
20
+ "../src/**/*.stories.*",
21
+ "../src/**/stories/*",
22
+ "../src/**/stories/**/*"
18
23
  ],
19
24
  "references": [
20
25
  {
@@ -14,7 +14,12 @@
14
14
  "../src/**/__tests__/*",
15
15
  "../src/**/*.test.*",
16
16
  "../src/**/test.*",
17
- "../src/**/examples.*"
17
+ "../src/**/examples.*",
18
+ "../src/**/examples/*",
19
+ "../src/**/examples/**/*",
20
+ "../src/**/*.stories.*",
21
+ "../src/**/stories/*",
22
+ "../src/**/stories/**/*"
18
23
  ],
19
24
  "references": [
20
25
  {
@@ -14,7 +14,12 @@
14
14
  "../src/**/__tests__/*",
15
15
  "../src/**/*.test.*",
16
16
  "../src/**/test.*",
17
- "../src/**/examples.*"
17
+ "../src/**/examples.*",
18
+ "../src/**/examples/*",
19
+ "../src/**/examples/**/*",
20
+ "../src/**/*.stories.*",
21
+ "../src/**/stories/*",
22
+ "../src/**/stories/**/*"
18
23
  ],
19
24
  "references": [
20
25
  {
@@ -1,17 +1,22 @@
1
1
  {
2
- "extends": "../tsconfig",
3
- "compilerOptions": {
4
- "target": "es5",
5
- "paths": {}
6
- },
7
- "include": [
8
- "../src/**/*.ts",
9
- "../src/**/*.tsx"
10
- ],
11
- "exclude": [
12
- "../src/**/__tests__/*",
13
- "../src/**/*.test.*",
14
- "../src/**/test.*",
15
- "../src/**/examples.*"
16
- ]
2
+ "extends": "../tsconfig",
3
+ "compilerOptions": {
4
+ "target": "es5",
5
+ "paths": {}
6
+ },
7
+ "include": [
8
+ "../src/**/*.ts",
9
+ "../src/**/*.tsx"
10
+ ],
11
+ "exclude": [
12
+ "../src/**/__tests__/*",
13
+ "../src/**/*.test.*",
14
+ "../src/**/test.*",
15
+ "../src/**/examples.*",
16
+ "../src/**/examples/*",
17
+ "../src/**/examples/**/*",
18
+ "../src/**/*.stories.*",
19
+ "../src/**/stories/*",
20
+ "../src/**/stories/**/*"
21
+ ]
17
22
  }
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.filterSteps = filterSteps;
7
+ var _maxSteps = require("./maxSteps");
8
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
9
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
10
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
11
+ /**
12
+ * Returns the filtered steps to ensure we don't track an entire document worth of changes
13
+ */
14
+ function filterSteps(steps, allocations) {
15
+ if (allocations.size <= _maxSteps.MAX_STEPS_FROM_BASELINE) {
16
+ return {
17
+ steps: steps,
18
+ allocations: allocations
19
+ };
20
+ }
21
+
22
+ // Create a new allocation, retaining only the most recent values
23
+ var elements = Array.from(allocations);
24
+ var newAllocation = new Set(elements.slice(-_maxSteps.MAX_STEPS_FROM_BASELINE));
25
+ var finalSteps = [];
26
+ var cutoffFound = false;
27
+ var _iterator = _createForOfIteratorHelper(steps),
28
+ _step;
29
+ try {
30
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
31
+ var step = _step.value;
32
+ if (newAllocation.has(step.allocation)) {
33
+ cutoffFound = true;
34
+ }
35
+ // Accept everything after this point otherwise we could have mis-ordered steps
36
+ if (cutoffFound) {
37
+ finalSteps.push(step);
38
+ }
39
+ }
40
+ } catch (err) {
41
+ _iterator.e(err);
42
+ } finally {
43
+ _iterator.f();
44
+ }
45
+ return {
46
+ steps: finalSteps,
47
+ allocations: newAllocation
48
+ };
49
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.InvertableStep = void 0;
8
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
9
+ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
10
+ var InvertableStep = exports.InvertableStep = /*#__PURE__*/(0, _createClass2.default)(function InvertableStep(step, inverted, allocation) {
11
+ (0, _classCallCheck2.default)(this, InvertableStep);
12
+ this.step = step;
13
+ this.inverted = inverted;
14
+ this.allocation = allocation;
15
+ });
@@ -4,14 +4,14 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.trackChangesPluginKey = exports.createTrackChangesPlugin = exports.InvertableStep = void 0;
7
+ exports.trackChangesPluginKey = exports.getBaselineFromSteps = exports.createTrackChangesPlugin = void 0;
8
8
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
9
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
10
- var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
11
- var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
12
10
  var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
13
11
  var _state = require("@atlaskit/editor-prosemirror/state");
14
12
  var _transform = require("@atlaskit/editor-prosemirror/transform");
13
+ var _filterSteps2 = require("./filterSteps");
14
+ var _invertableStep = require("./invertableStep");
15
15
  var _types = require("./types");
16
16
  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; }
17
17
  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; }
@@ -19,18 +19,14 @@ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol
19
19
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
20
20
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
21
21
  var trackChangesPluginKey = exports.trackChangesPluginKey = new _state.PluginKey('trackChangesPlugin');
22
- var InvertableStep = exports.InvertableStep = /*#__PURE__*/(0, _createClass2.default)(function InvertableStep(step, inverted) {
23
- (0, _classCallCheck2.default)(this, InvertableStep);
24
- this.step = step;
25
- this.inverted = inverted;
26
- });
27
- var getBaselineFromSteps = function getBaselineFromSteps(doc, steps) {
22
+ // Exported for test purposes
23
+ var getBaselineFromSteps = exports.getBaselineFromSteps = function getBaselineFromSteps(doc, steps) {
28
24
  var _iterator = _createForOfIteratorHelper(steps.slice().reverse()),
29
25
  _step;
30
26
  try {
31
27
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
32
- var _step2 = _step.value;
33
- var result = _step2.inverted.apply(doc);
28
+ var step = _step.value;
29
+ var result = step.inverted.apply(doc);
34
30
  if (result.failed === null && result.doc) {
35
31
  doc = result.doc;
36
32
  }
@@ -52,11 +48,19 @@ var createTrackChangesPlugin = exports.createTrackChangesPlugin = function creat
52
48
  return {
53
49
  steps: [],
54
50
  shouldChangesBeDisplayed: false,
55
- isShowDiffAvailable: false
51
+ isShowDiffAvailable: false,
52
+ allocations: new Set()
56
53
  };
57
54
  },
58
55
  apply: function apply(tr, state) {
56
+ var _api$history, _state$steps$at$alloc, _state$steps$at;
59
57
  var metadata = tr.getMeta(trackChangesPluginKey);
58
+ if (metadata && metadata.action === _types.TOGGLE_TRACK_CHANGES_ACTION.RESET_BASELINE) {
59
+ return _objectSpread(_objectSpread({}, state), {}, {
60
+ steps: [],
61
+ isShowDiffAvailable: false
62
+ });
63
+ }
60
64
  if (metadata && metadata.action === _types.TOGGLE_TRACK_CHANGES_ACTION.TOGGLE_TRACK_CHANGES) {
61
65
  resetBaseline = true;
62
66
  return _objectSpread(_objectSpread({}, state), {}, {
@@ -70,14 +74,24 @@ var createTrackChangesPlugin = exports.createTrackChangesPlugin = function creat
70
74
  // If no document changes, return the old changeSet
71
75
  return state;
72
76
  }
77
+
78
+ // If we don't have the history plugin don't limit the change tracking
79
+ var historyState = api === null || api === void 0 || (_api$history = api.history) === null || _api$history === void 0 ? void 0 : _api$history.sharedState.currentState();
80
+ var currentAllocation = historyState ?
81
+ // Combine both done + undone so we have the total "distance".
82
+ historyState.done.eventCount + historyState.undone.eventCount : ((_state$steps$at$alloc = (_state$steps$at = state.steps.at(-1)) === null || _state$steps$at === void 0 ? void 0 : _state$steps$at.allocation) !== null && _state$steps$at$alloc !== void 0 ? _state$steps$at$alloc : 0) + 1;
73
83
  var newSteps = tr.steps.map(function (step, idx) {
74
- return new InvertableStep(step, step.invert(tr.docs[idx]));
84
+ return new _invertableStep.InvertableStep(step, step.invert(tr.docs[idx]), currentAllocation);
75
85
  });
76
- var steps = resetBaseline ? newSteps : [].concat((0, _toConsumableArray2.default)(state.steps), (0, _toConsumableArray2.default)(newSteps));
86
+ var concatSteps = resetBaseline ? newSteps : [].concat((0, _toConsumableArray2.default)(state.steps), (0, _toConsumableArray2.default)(newSteps));
77
87
  resetBaseline = false;
88
+ var _filterSteps = (0, _filterSteps2.filterSteps)(concatSteps, state.allocations.add(currentAllocation)),
89
+ allocations = _filterSteps.allocations,
90
+ steps = _filterSteps.steps;
78
91
 
79
92
  // Create a new ChangeSet based on document changes
80
93
  return _objectSpread(_objectSpread({}, state), {}, {
94
+ allocations: allocations,
81
95
  steps: steps,
82
96
  shouldChangesBeDisplayed: false,
83
97
  isShowDiffAvailable: true
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.MAX_STEPS_FROM_BASELINE = void 0;
7
+ // To be determined a suitable threshold
8
+ // Exported for testing
9
+ var MAX_STEPS_FROM_BASELINE = exports.MAX_STEPS_FROM_BASELINE = 10;
@@ -6,5 +6,6 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.TOGGLE_TRACK_CHANGES_ACTION = void 0;
7
7
  var TOGGLE_TRACK_CHANGES_ACTION = exports.TOGGLE_TRACK_CHANGES_ACTION = /*#__PURE__*/function (TOGGLE_TRACK_CHANGES_ACTION) {
8
8
  TOGGLE_TRACK_CHANGES_ACTION["TOGGLE_TRACK_CHANGES"] = "TOGGLE_TRACK_CHANGES";
9
+ TOGGLE_TRACK_CHANGES_ACTION["RESET_BASELINE"] = "RESET_BASELINE";
9
10
  return TOGGLE_TRACK_CHANGES_ACTION;
10
11
  }({});
@@ -10,17 +10,20 @@ var _main = require("./pm-plugins/main");
10
10
  var _types = require("./pm-plugins/types");
11
11
  var _TrackChangesToolbarButton = require("./ui/TrackChangesToolbarButton");
12
12
  var trackChangesPlugin = exports.trackChangesPlugin = function trackChangesPlugin(_ref) {
13
- var _api$primaryToolbar;
14
- var api = _ref.api;
13
+ var api = _ref.api,
14
+ options = _ref.config;
15
15
  var primaryToolbarComponent = function primaryToolbarComponent() {
16
16
  return /*#__PURE__*/_react.default.createElement(_TrackChangesToolbarButton.TrackChangesToolbarButton, {
17
17
  api: api
18
18
  });
19
19
  };
20
- api === null || api === void 0 || (_api$primaryToolbar = api.primaryToolbar) === null || _api$primaryToolbar === void 0 || (_api$primaryToolbar = _api$primaryToolbar.actions) === null || _api$primaryToolbar === void 0 || _api$primaryToolbar.registerComponent({
21
- name: 'trackChanges',
22
- component: primaryToolbarComponent
23
- });
20
+ if ((options === null || options === void 0 ? void 0 : options.showOnToolbar) === true) {
21
+ var _api$primaryToolbar;
22
+ api === null || api === void 0 || (_api$primaryToolbar = api.primaryToolbar) === null || _api$primaryToolbar === void 0 || (_api$primaryToolbar = _api$primaryToolbar.actions) === null || _api$primaryToolbar === void 0 || _api$primaryToolbar.registerComponent({
23
+ name: 'trackChanges',
24
+ component: primaryToolbarComponent
25
+ });
26
+ }
24
27
  return {
25
28
  name: 'trackChanges',
26
29
  pmPlugins: function pmPlugins() {
@@ -37,6 +40,16 @@ var trackChangesPlugin = exports.trackChangesPlugin = function trackChangesPlugi
37
40
  return tr.setMeta(_main.trackChangesPluginKey, {
38
41
  action: _types.TOGGLE_TRACK_CHANGES_ACTION.TOGGLE_TRACK_CHANGES
39
42
  });
43
+ },
44
+ resetBaseline: function resetBaseline(_ref3) {
45
+ var _api$trackChanges;
46
+ var tr = _ref3.tr;
47
+ if (!(api !== null && api !== void 0 && (_api$trackChanges = api.trackChanges) !== null && _api$trackChanges !== void 0 && (_api$trackChanges = _api$trackChanges.sharedState.currentState()) !== null && _api$trackChanges !== void 0 && _api$trackChanges.isShowDiffAvailable)) {
48
+ return null;
49
+ }
50
+ return tr.setMeta(_main.trackChangesPluginKey, {
51
+ action: _types.TOGGLE_TRACK_CHANGES_ACTION.RESET_BASELINE
52
+ });
40
53
  }
41
54
  },
42
55
  getSharedState: function getSharedState(editorState) {
@@ -6,8 +6,10 @@ Object.defineProperty(exports, "__esModule", {
6
6
  });
7
7
  exports.TrackChangesToolbarButton = void 0;
8
8
  var _react = _interopRequireDefault(require("react"));
9
+ var _reactIntlNext = require("react-intl-next");
9
10
  var _new = require("@atlaskit/button/new");
10
11
  var _hooks = require("@atlaskit/editor-common/hooks");
12
+ var _messages = require("@atlaskit/editor-common/messages");
11
13
  var _history = _interopRequireDefault(require("@atlaskit/icon-lab/core/history"));
12
14
  var TrackChangesToolbarButton = exports.TrackChangesToolbarButton = function TrackChangesToolbarButton(_ref) {
13
15
  var _api$trackChanges;
@@ -21,12 +23,14 @@ var TrackChangesToolbarButton = exports.TrackChangesToolbarButton = function Tra
21
23
  }),
22
24
  isDisplayingChanges = _useSharedPluginState.isDisplayingChanges,
23
25
  isShowDiffAvailable = _useSharedPluginState.isShowDiffAvailable;
26
+ var _useIntl = (0, _reactIntlNext.useIntl)(),
27
+ formatMessage = _useIntl.formatMessage;
24
28
  var handleClick = _react.default.useCallback(function () {
25
29
  api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 ? void 0 : api.trackChanges.commands.toggleChanges);
26
30
  }, [api === null || api === void 0 || (_api$trackChanges = api.trackChanges) === null || _api$trackChanges === void 0 ? void 0 : _api$trackChanges.commands, api === null || api === void 0 ? void 0 : api.core.actions]);
27
31
  return /*#__PURE__*/_react.default.createElement(_new.IconButton, {
28
32
  icon: _history.default,
29
- label: "Track Changes",
33
+ label: formatMessage(_messages.trackChangesMessages.toolbarIconLabel),
30
34
  appearance: "subtle",
31
35
  isDisabled: !isShowDiffAvailable,
32
36
  isSelected: isDisplayingChanges,
@@ -0,0 +1,32 @@
1
+ import { MAX_STEPS_FROM_BASELINE } from './maxSteps';
2
+
3
+ /**
4
+ * Returns the filtered steps to ensure we don't track an entire document worth of changes
5
+ */
6
+ export function filterSteps(steps, allocations) {
7
+ if (allocations.size <= MAX_STEPS_FROM_BASELINE) {
8
+ return {
9
+ steps,
10
+ allocations
11
+ };
12
+ }
13
+
14
+ // Create a new allocation, retaining only the most recent values
15
+ const elements = Array.from(allocations);
16
+ const newAllocation = new Set(elements.slice(-MAX_STEPS_FROM_BASELINE));
17
+ const finalSteps = [];
18
+ let cutoffFound = false;
19
+ for (const step of steps) {
20
+ if (newAllocation.has(step.allocation)) {
21
+ cutoffFound = true;
22
+ }
23
+ // Accept everything after this point otherwise we could have mis-ordered steps
24
+ if (cutoffFound) {
25
+ finalSteps.push(step);
26
+ }
27
+ }
28
+ return {
29
+ steps: finalSteps,
30
+ allocations: newAllocation
31
+ };
32
+ }
@@ -0,0 +1,7 @@
1
+ export class InvertableStep {
2
+ constructor(step, inverted, allocation) {
3
+ this.step = step;
4
+ this.inverted = inverted;
5
+ this.allocation = allocation;
6
+ }
7
+ }
@@ -1,15 +1,12 @@
1
1
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
2
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
3
3
  import { ReplaceAroundStep, ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
4
+ import { filterSteps } from './filterSteps';
5
+ import { InvertableStep } from './invertableStep';
4
6
  import { TOGGLE_TRACK_CHANGES_ACTION as ACTION } from './types';
5
7
  export const trackChangesPluginKey = new PluginKey('trackChangesPlugin');
6
- export class InvertableStep {
7
- constructor(step, inverted) {
8
- this.step = step;
9
- this.inverted = inverted;
10
- }
11
- }
12
- const getBaselineFromSteps = (doc, steps) => {
8
+ // Exported for test purposes
9
+ export const getBaselineFromSteps = (doc, steps) => {
13
10
  for (const step of steps.slice().reverse()) {
14
11
  const result = step.inverted.apply(doc);
15
12
  if (result.failed === null && result.doc) {
@@ -28,11 +25,20 @@ export const createTrackChangesPlugin = api => {
28
25
  return {
29
26
  steps: [],
30
27
  shouldChangesBeDisplayed: false,
31
- isShowDiffAvailable: false
28
+ isShowDiffAvailable: false,
29
+ allocations: new Set()
32
30
  };
33
31
  },
34
32
  apply(tr, state) {
33
+ var _api$history, _state$steps$at$alloc, _state$steps$at;
35
34
  const metadata = tr.getMeta(trackChangesPluginKey);
35
+ if (metadata && metadata.action === ACTION.RESET_BASELINE) {
36
+ return {
37
+ ...state,
38
+ steps: [],
39
+ isShowDiffAvailable: false
40
+ };
41
+ }
36
42
  if (metadata && metadata.action === ACTION.TOGGLE_TRACK_CHANGES) {
37
43
  resetBaseline = true;
38
44
  return {
@@ -45,13 +51,24 @@ export const createTrackChangesPlugin = api => {
45
51
  // If no document changes, return the old changeSet
46
52
  return state;
47
53
  }
48
- const newSteps = tr.steps.map((step, idx) => new InvertableStep(step, step.invert(tr.docs[idx])));
49
- const steps = resetBaseline ? newSteps : [...state.steps, ...newSteps];
54
+
55
+ // If we don't have the history plugin don't limit the change tracking
56
+ const historyState = api === null || api === void 0 ? void 0 : (_api$history = api.history) === null || _api$history === void 0 ? void 0 : _api$history.sharedState.currentState();
57
+ const currentAllocation = historyState ?
58
+ // Combine both done + undone so we have the total "distance".
59
+ historyState.done.eventCount + historyState.undone.eventCount : ((_state$steps$at$alloc = (_state$steps$at = state.steps.at(-1)) === null || _state$steps$at === void 0 ? void 0 : _state$steps$at.allocation) !== null && _state$steps$at$alloc !== void 0 ? _state$steps$at$alloc : 0) + 1;
60
+ const newSteps = tr.steps.map((step, idx) => new InvertableStep(step, step.invert(tr.docs[idx]), currentAllocation));
61
+ const concatSteps = resetBaseline ? newSteps : [...state.steps, ...newSteps];
50
62
  resetBaseline = false;
63
+ const {
64
+ allocations,
65
+ steps
66
+ } = filterSteps(concatSteps, state.allocations.add(currentAllocation));
51
67
 
52
68
  // Create a new ChangeSet based on document changes
53
69
  return {
54
70
  ...state,
71
+ allocations,
55
72
  steps,
56
73
  shouldChangesBeDisplayed: false,
57
74
  isShowDiffAvailable: true
@@ -0,0 +1,3 @@
1
+ // To be determined a suitable threshold
2
+ // Exported for testing
3
+ export const MAX_STEPS_FROM_BASELINE = 10;
@@ -1,4 +1,5 @@
1
1
  export let TOGGLE_TRACK_CHANGES_ACTION = /*#__PURE__*/function (TOGGLE_TRACK_CHANGES_ACTION) {
2
2
  TOGGLE_TRACK_CHANGES_ACTION["TOGGLE_TRACK_CHANGES"] = "TOGGLE_TRACK_CHANGES";
3
+ TOGGLE_TRACK_CHANGES_ACTION["RESET_BASELINE"] = "RESET_BASELINE";
3
4
  return TOGGLE_TRACK_CHANGES_ACTION;
4
5
  }({});
@@ -3,18 +3,21 @@ import { createTrackChangesPlugin, trackChangesPluginKey } from './pm-plugins/ma
3
3
  import { TOGGLE_TRACK_CHANGES_ACTION as ACTION } from './pm-plugins/types';
4
4
  import { TrackChangesToolbarButton } from './ui/TrackChangesToolbarButton';
5
5
  export const trackChangesPlugin = ({
6
- api
6
+ api,
7
+ config: options
7
8
  }) => {
8
- var _api$primaryToolbar, _api$primaryToolbar$a;
9
9
  const primaryToolbarComponent = () => {
10
10
  return /*#__PURE__*/React.createElement(TrackChangesToolbarButton, {
11
11
  api: api
12
12
  });
13
13
  };
14
- api === null || api === void 0 ? void 0 : (_api$primaryToolbar = api.primaryToolbar) === null || _api$primaryToolbar === void 0 ? void 0 : (_api$primaryToolbar$a = _api$primaryToolbar.actions) === null || _api$primaryToolbar$a === void 0 ? void 0 : _api$primaryToolbar$a.registerComponent({
15
- name: 'trackChanges',
16
- component: primaryToolbarComponent
17
- });
14
+ if ((options === null || options === void 0 ? void 0 : options.showOnToolbar) === true) {
15
+ var _api$primaryToolbar, _api$primaryToolbar$a;
16
+ api === null || api === void 0 ? void 0 : (_api$primaryToolbar = api.primaryToolbar) === null || _api$primaryToolbar === void 0 ? void 0 : (_api$primaryToolbar$a = _api$primaryToolbar.actions) === null || _api$primaryToolbar$a === void 0 ? void 0 : _api$primaryToolbar$a.registerComponent({
17
+ name: 'trackChanges',
18
+ component: primaryToolbarComponent
19
+ });
20
+ }
18
21
  return {
19
22
  name: 'trackChanges',
20
23
  pmPlugins() {
@@ -30,6 +33,17 @@ export const trackChangesPlugin = ({
30
33
  return tr.setMeta(trackChangesPluginKey, {
31
34
  action: ACTION.TOGGLE_TRACK_CHANGES
32
35
  });
36
+ },
37
+ resetBaseline: ({
38
+ tr
39
+ }) => {
40
+ var _api$trackChanges, _api$trackChanges$sha;
41
+ if (!(api !== null && api !== void 0 && (_api$trackChanges = api.trackChanges) !== null && _api$trackChanges !== void 0 && (_api$trackChanges$sha = _api$trackChanges.sharedState.currentState()) !== null && _api$trackChanges$sha !== void 0 && _api$trackChanges$sha.isShowDiffAvailable)) {
42
+ return null;
43
+ }
44
+ return tr.setMeta(trackChangesPluginKey, {
45
+ action: ACTION.RESET_BASELINE
46
+ });
33
47
  }
34
48
  },
35
49
  getSharedState: editorState => {
@@ -1,6 +1,8 @@
1
1
  import React from 'react';
2
+ import { useIntl } from 'react-intl-next';
2
3
  import { IconButton } from '@atlaskit/button/new';
3
4
  import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
5
+ import { trackChangesMessages } from '@atlaskit/editor-common/messages';
4
6
  import HistoryIcon from '@atlaskit/icon-lab/core/history';
5
7
  export const TrackChangesToolbarButton = ({
6
8
  api
@@ -16,12 +18,15 @@ export const TrackChangesToolbarButton = ({
16
18
  isShowDiffAvailable: (_states$trackChangesS2 = states.trackChangesState) === null || _states$trackChangesS2 === void 0 ? void 0 : _states$trackChangesS2.isShowDiffAvailable
17
19
  };
18
20
  });
21
+ const {
22
+ formatMessage
23
+ } = useIntl();
19
24
  const handleClick = React.useCallback(() => {
20
25
  api === null || api === void 0 ? void 0 : api.core.actions.execute(api === null || api === void 0 ? void 0 : api.trackChanges.commands.toggleChanges);
21
26
  }, [api === null || api === void 0 ? void 0 : (_api$trackChanges = api.trackChanges) === null || _api$trackChanges === void 0 ? void 0 : _api$trackChanges.commands, api === null || api === void 0 ? void 0 : api.core.actions]);
22
27
  return /*#__PURE__*/React.createElement(IconButton, {
23
28
  icon: HistoryIcon,
24
- label: "Track Changes",
29
+ label: formatMessage(trackChangesMessages.toolbarIconLabel),
25
30
  appearance: "subtle",
26
31
  isDisabled: !isShowDiffAvailable,
27
32
  isSelected: isDisplayingChanges,
@@ -0,0 +1,44 @@
1
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
2
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
3
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
4
+ import { MAX_STEPS_FROM_BASELINE } from './maxSteps';
5
+
6
+ /**
7
+ * Returns the filtered steps to ensure we don't track an entire document worth of changes
8
+ */
9
+ export function filterSteps(steps, allocations) {
10
+ if (allocations.size <= MAX_STEPS_FROM_BASELINE) {
11
+ return {
12
+ steps: steps,
13
+ allocations: allocations
14
+ };
15
+ }
16
+
17
+ // Create a new allocation, retaining only the most recent values
18
+ var elements = Array.from(allocations);
19
+ var newAllocation = new Set(elements.slice(-MAX_STEPS_FROM_BASELINE));
20
+ var finalSteps = [];
21
+ var cutoffFound = false;
22
+ var _iterator = _createForOfIteratorHelper(steps),
23
+ _step;
24
+ try {
25
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
26
+ var step = _step.value;
27
+ if (newAllocation.has(step.allocation)) {
28
+ cutoffFound = true;
29
+ }
30
+ // Accept everything after this point otherwise we could have mis-ordered steps
31
+ if (cutoffFound) {
32
+ finalSteps.push(step);
33
+ }
34
+ }
35
+ } catch (err) {
36
+ _iterator.e(err);
37
+ } finally {
38
+ _iterator.f();
39
+ }
40
+ return {
41
+ steps: finalSteps,
42
+ allocations: newAllocation
43
+ };
44
+ }
@@ -0,0 +1,8 @@
1
+ import _createClass from "@babel/runtime/helpers/createClass";
2
+ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
3
+ export var InvertableStep = /*#__PURE__*/_createClass(function InvertableStep(step, inverted, allocation) {
4
+ _classCallCheck(this, InvertableStep);
5
+ this.step = step;
6
+ this.inverted = inverted;
7
+ this.allocation = allocation;
8
+ });
@@ -1,7 +1,5 @@
1
1
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
2
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
- import _createClass from "@babel/runtime/helpers/createClass";
4
- import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
5
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; }
6
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; }
7
5
  function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
@@ -10,20 +8,18 @@ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length)
10
8
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
11
9
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
12
10
  import { ReplaceAroundStep, ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
11
+ import { filterSteps } from './filterSteps';
12
+ import { InvertableStep } from './invertableStep';
13
13
  import { TOGGLE_TRACK_CHANGES_ACTION as ACTION } from './types';
14
14
  export var trackChangesPluginKey = new PluginKey('trackChangesPlugin');
15
- export var InvertableStep = /*#__PURE__*/_createClass(function InvertableStep(step, inverted) {
16
- _classCallCheck(this, InvertableStep);
17
- this.step = step;
18
- this.inverted = inverted;
19
- });
20
- var getBaselineFromSteps = function getBaselineFromSteps(doc, steps) {
15
+ // Exported for test purposes
16
+ export var getBaselineFromSteps = function getBaselineFromSteps(doc, steps) {
21
17
  var _iterator = _createForOfIteratorHelper(steps.slice().reverse()),
22
18
  _step;
23
19
  try {
24
20
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
25
- var _step2 = _step.value;
26
- var result = _step2.inverted.apply(doc);
21
+ var step = _step.value;
22
+ var result = step.inverted.apply(doc);
27
23
  if (result.failed === null && result.doc) {
28
24
  doc = result.doc;
29
25
  }
@@ -45,11 +41,19 @@ export var createTrackChangesPlugin = function createTrackChangesPlugin(api) {
45
41
  return {
46
42
  steps: [],
47
43
  shouldChangesBeDisplayed: false,
48
- isShowDiffAvailable: false
44
+ isShowDiffAvailable: false,
45
+ allocations: new Set()
49
46
  };
50
47
  },
51
48
  apply: function apply(tr, state) {
49
+ var _api$history, _state$steps$at$alloc, _state$steps$at;
52
50
  var metadata = tr.getMeta(trackChangesPluginKey);
51
+ if (metadata && metadata.action === ACTION.RESET_BASELINE) {
52
+ return _objectSpread(_objectSpread({}, state), {}, {
53
+ steps: [],
54
+ isShowDiffAvailable: false
55
+ });
56
+ }
53
57
  if (metadata && metadata.action === ACTION.TOGGLE_TRACK_CHANGES) {
54
58
  resetBaseline = true;
55
59
  return _objectSpread(_objectSpread({}, state), {}, {
@@ -63,14 +67,24 @@ export var createTrackChangesPlugin = function createTrackChangesPlugin(api) {
63
67
  // If no document changes, return the old changeSet
64
68
  return state;
65
69
  }
70
+
71
+ // If we don't have the history plugin don't limit the change tracking
72
+ var historyState = api === null || api === void 0 || (_api$history = api.history) === null || _api$history === void 0 ? void 0 : _api$history.sharedState.currentState();
73
+ var currentAllocation = historyState ?
74
+ // Combine both done + undone so we have the total "distance".
75
+ historyState.done.eventCount + historyState.undone.eventCount : ((_state$steps$at$alloc = (_state$steps$at = state.steps.at(-1)) === null || _state$steps$at === void 0 ? void 0 : _state$steps$at.allocation) !== null && _state$steps$at$alloc !== void 0 ? _state$steps$at$alloc : 0) + 1;
66
76
  var newSteps = tr.steps.map(function (step, idx) {
67
- return new InvertableStep(step, step.invert(tr.docs[idx]));
77
+ return new InvertableStep(step, step.invert(tr.docs[idx]), currentAllocation);
68
78
  });
69
- var steps = resetBaseline ? newSteps : [].concat(_toConsumableArray(state.steps), _toConsumableArray(newSteps));
79
+ var concatSteps = resetBaseline ? newSteps : [].concat(_toConsumableArray(state.steps), _toConsumableArray(newSteps));
70
80
  resetBaseline = false;
81
+ var _filterSteps = filterSteps(concatSteps, state.allocations.add(currentAllocation)),
82
+ allocations = _filterSteps.allocations,
83
+ steps = _filterSteps.steps;
71
84
 
72
85
  // Create a new ChangeSet based on document changes
73
86
  return _objectSpread(_objectSpread({}, state), {}, {
87
+ allocations: allocations,
74
88
  steps: steps,
75
89
  shouldChangesBeDisplayed: false,
76
90
  isShowDiffAvailable: true
@@ -0,0 +1,3 @@
1
+ // To be determined a suitable threshold
2
+ // Exported for testing
3
+ export var MAX_STEPS_FROM_BASELINE = 10;
@@ -1,4 +1,5 @@
1
1
  export var TOGGLE_TRACK_CHANGES_ACTION = /*#__PURE__*/function (TOGGLE_TRACK_CHANGES_ACTION) {
2
2
  TOGGLE_TRACK_CHANGES_ACTION["TOGGLE_TRACK_CHANGES"] = "TOGGLE_TRACK_CHANGES";
3
+ TOGGLE_TRACK_CHANGES_ACTION["RESET_BASELINE"] = "RESET_BASELINE";
3
4
  return TOGGLE_TRACK_CHANGES_ACTION;
4
5
  }({});
@@ -3,17 +3,20 @@ import { createTrackChangesPlugin, trackChangesPluginKey } from './pm-plugins/ma
3
3
  import { TOGGLE_TRACK_CHANGES_ACTION as ACTION } from './pm-plugins/types';
4
4
  import { TrackChangesToolbarButton } from './ui/TrackChangesToolbarButton';
5
5
  export var trackChangesPlugin = function trackChangesPlugin(_ref) {
6
- var _api$primaryToolbar;
7
- var api = _ref.api;
6
+ var api = _ref.api,
7
+ options = _ref.config;
8
8
  var primaryToolbarComponent = function primaryToolbarComponent() {
9
9
  return /*#__PURE__*/React.createElement(TrackChangesToolbarButton, {
10
10
  api: api
11
11
  });
12
12
  };
13
- api === null || api === void 0 || (_api$primaryToolbar = api.primaryToolbar) === null || _api$primaryToolbar === void 0 || (_api$primaryToolbar = _api$primaryToolbar.actions) === null || _api$primaryToolbar === void 0 || _api$primaryToolbar.registerComponent({
14
- name: 'trackChanges',
15
- component: primaryToolbarComponent
16
- });
13
+ if ((options === null || options === void 0 ? void 0 : options.showOnToolbar) === true) {
14
+ var _api$primaryToolbar;
15
+ api === null || api === void 0 || (_api$primaryToolbar = api.primaryToolbar) === null || _api$primaryToolbar === void 0 || (_api$primaryToolbar = _api$primaryToolbar.actions) === null || _api$primaryToolbar === void 0 || _api$primaryToolbar.registerComponent({
16
+ name: 'trackChanges',
17
+ component: primaryToolbarComponent
18
+ });
19
+ }
17
20
  return {
18
21
  name: 'trackChanges',
19
22
  pmPlugins: function pmPlugins() {
@@ -30,6 +33,16 @@ export var trackChangesPlugin = function trackChangesPlugin(_ref) {
30
33
  return tr.setMeta(trackChangesPluginKey, {
31
34
  action: ACTION.TOGGLE_TRACK_CHANGES
32
35
  });
36
+ },
37
+ resetBaseline: function resetBaseline(_ref3) {
38
+ var _api$trackChanges;
39
+ var tr = _ref3.tr;
40
+ if (!(api !== null && api !== void 0 && (_api$trackChanges = api.trackChanges) !== null && _api$trackChanges !== void 0 && (_api$trackChanges = _api$trackChanges.sharedState.currentState()) !== null && _api$trackChanges !== void 0 && _api$trackChanges.isShowDiffAvailable)) {
41
+ return null;
42
+ }
43
+ return tr.setMeta(trackChangesPluginKey, {
44
+ action: ACTION.RESET_BASELINE
45
+ });
33
46
  }
34
47
  },
35
48
  getSharedState: function getSharedState(editorState) {
@@ -1,6 +1,8 @@
1
1
  import React from 'react';
2
+ import { useIntl } from 'react-intl-next';
2
3
  import { IconButton } from '@atlaskit/button/new';
3
4
  import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
5
+ import { trackChangesMessages } from '@atlaskit/editor-common/messages';
4
6
  import HistoryIcon from '@atlaskit/icon-lab/core/history';
5
7
  export var TrackChangesToolbarButton = function TrackChangesToolbarButton(_ref) {
6
8
  var _api$trackChanges;
@@ -14,12 +16,14 @@ export var TrackChangesToolbarButton = function TrackChangesToolbarButton(_ref)
14
16
  }),
15
17
  isDisplayingChanges = _useSharedPluginState.isDisplayingChanges,
16
18
  isShowDiffAvailable = _useSharedPluginState.isShowDiffAvailable;
19
+ var _useIntl = useIntl(),
20
+ formatMessage = _useIntl.formatMessage;
17
21
  var handleClick = React.useCallback(function () {
18
22
  api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 ? void 0 : api.trackChanges.commands.toggleChanges);
19
23
  }, [api === null || api === void 0 || (_api$trackChanges = api.trackChanges) === null || _api$trackChanges === void 0 ? void 0 : _api$trackChanges.commands, api === null || api === void 0 ? void 0 : api.core.actions]);
20
24
  return /*#__PURE__*/React.createElement(IconButton, {
21
25
  icon: HistoryIcon,
22
- label: "Track Changes",
26
+ label: formatMessage(trackChangesMessages.toolbarIconLabel),
23
27
  appearance: "subtle",
24
28
  isDisabled: !isShowDiffAvailable,
25
29
  isSelected: isDisplayingChanges,
@@ -0,0 +1,8 @@
1
+ import type { InvertableStep } from './invertableStep';
2
+ /**
3
+ * Returns the filtered steps to ensure we don't track an entire document worth of changes
4
+ */
5
+ export declare function filterSteps(steps: InvertableStep[], allocations: Set<number>): {
6
+ steps: InvertableStep[];
7
+ allocations: Set<number>;
8
+ };
@@ -0,0 +1,7 @@
1
+ import { type Step } from '@atlaskit/editor-prosemirror/transform';
2
+ export declare class InvertableStep {
3
+ readonly step: Step;
4
+ readonly inverted: Step;
5
+ readonly allocation: number;
6
+ constructor(step: Step, inverted: Step, allocation: number);
7
+ }
@@ -1,18 +1,16 @@
1
1
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
2
  import { type ExtractInjectionAPI } from '@atlaskit/editor-common/types';
3
+ import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
3
4
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
4
- import { type Step } from '@atlaskit/editor-prosemirror/transform';
5
5
  import type { TrackChangesPlugin } from '../trackChangesPluginType';
6
+ import { InvertableStep } from './invertableStep';
6
7
  export declare const trackChangesPluginKey: PluginKey<TrackChangesPluginState>;
7
8
  type TrackChangesPluginState = {
8
9
  shouldChangesBeDisplayed: boolean;
9
10
  isShowDiffAvailable: boolean;
10
11
  steps: InvertableStep[];
12
+ allocations: Set<number>;
11
13
  };
12
- export declare class InvertableStep {
13
- readonly step: Step;
14
- readonly inverted: Step;
15
- constructor(step: Step, inverted: Step);
16
- }
14
+ export declare const getBaselineFromSteps: (doc: PMNode, steps: InvertableStep[]) => PMNode;
17
15
  export declare const createTrackChangesPlugin: (api: ExtractInjectionAPI<TrackChangesPlugin> | undefined) => SafePlugin<TrackChangesPluginState>;
18
16
  export {};
@@ -0,0 +1 @@
1
+ export declare const MAX_STEPS_FROM_BASELINE = 10;
@@ -1,3 +1,4 @@
1
1
  export declare enum TOGGLE_TRACK_CHANGES_ACTION {
2
- TOGGLE_TRACK_CHANGES = "TOGGLE_TRACK_CHANGES"
2
+ TOGGLE_TRACK_CHANGES = "TOGGLE_TRACK_CHANGES",
3
+ RESET_BASELINE = "RESET_BASELINE"
3
4
  }
@@ -1,4 +1,5 @@
1
1
  import type { EditorCommand, NextEditorPlugin, OptionalPlugin } from '@atlaskit/editor-common/types';
2
+ import type { HistoryPlugin } from '@atlaskit/editor-plugin-history';
2
3
  import { type PrimaryToolbarPlugin } from '@atlaskit/editor-plugin-primary-toolbar';
3
4
  import type { ShowDiffPlugin } from '@atlaskit/editor-plugin-show-diff';
4
5
  export type TrackChangesPlugin = NextEditorPlugin<'trackChanges', {
@@ -7,8 +8,32 @@ export type TrackChangesPlugin = NextEditorPlugin<'trackChanges', {
7
8
  * Toggles the displaying of changes in the editor.
8
9
  */
9
10
  toggleChanges: EditorCommand;
11
+ /**
12
+ * Resets the baseline used for tracking changes in the editor.
13
+ */
14
+ resetBaseline: EditorCommand;
15
+ };
16
+ dependencies: [
17
+ /**
18
+ * Primary toolbar plugin for registering the track changes button.
19
+ */
20
+ OptionalPlugin<PrimaryToolbarPlugin>,
21
+ /**
22
+ * For ensuring the tracked changes align with the history
23
+ */
24
+ OptionalPlugin<HistoryPlugin>,
25
+ /**
26
+ * Show diff plugin for showing the changes in a diff view.
27
+ */
28
+ ShowDiffPlugin
29
+ ];
30
+ pluginConfiguration?: {
31
+ /**
32
+ * Whether the track changes button should be shown on the toolbar.
33
+ * Defaults to false.
34
+ */
35
+ showOnToolbar?: boolean;
10
36
  };
11
- dependencies: [OptionalPlugin<PrimaryToolbarPlugin>, ShowDiffPlugin];
12
37
  sharedState: {
13
38
  /**
14
39
  * Whether the track changes feature is currently displaying changes.
@@ -0,0 +1,8 @@
1
+ import type { InvertableStep } from './invertableStep';
2
+ /**
3
+ * Returns the filtered steps to ensure we don't track an entire document worth of changes
4
+ */
5
+ export declare function filterSteps(steps: InvertableStep[], allocations: Set<number>): {
6
+ steps: InvertableStep[];
7
+ allocations: Set<number>;
8
+ };
@@ -0,0 +1,7 @@
1
+ import { type Step } from '@atlaskit/editor-prosemirror/transform';
2
+ export declare class InvertableStep {
3
+ readonly step: Step;
4
+ readonly inverted: Step;
5
+ readonly allocation: number;
6
+ constructor(step: Step, inverted: Step, allocation: number);
7
+ }
@@ -1,18 +1,16 @@
1
1
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
2
  import { type ExtractInjectionAPI } from '@atlaskit/editor-common/types';
3
+ import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
3
4
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
4
- import { type Step } from '@atlaskit/editor-prosemirror/transform';
5
5
  import type { TrackChangesPlugin } from '../trackChangesPluginType';
6
+ import { InvertableStep } from './invertableStep';
6
7
  export declare const trackChangesPluginKey: PluginKey<TrackChangesPluginState>;
7
8
  type TrackChangesPluginState = {
8
9
  shouldChangesBeDisplayed: boolean;
9
10
  isShowDiffAvailable: boolean;
10
11
  steps: InvertableStep[];
12
+ allocations: Set<number>;
11
13
  };
12
- export declare class InvertableStep {
13
- readonly step: Step;
14
- readonly inverted: Step;
15
- constructor(step: Step, inverted: Step);
16
- }
14
+ export declare const getBaselineFromSteps: (doc: PMNode, steps: InvertableStep[]) => PMNode;
17
15
  export declare const createTrackChangesPlugin: (api: ExtractInjectionAPI<TrackChangesPlugin> | undefined) => SafePlugin<TrackChangesPluginState>;
18
16
  export {};
@@ -0,0 +1 @@
1
+ export declare const MAX_STEPS_FROM_BASELINE = 10;
@@ -1,3 +1,4 @@
1
1
  export declare enum TOGGLE_TRACK_CHANGES_ACTION {
2
- TOGGLE_TRACK_CHANGES = "TOGGLE_TRACK_CHANGES"
2
+ TOGGLE_TRACK_CHANGES = "TOGGLE_TRACK_CHANGES",
3
+ RESET_BASELINE = "RESET_BASELINE"
3
4
  }
@@ -1,4 +1,5 @@
1
1
  import type { EditorCommand, NextEditorPlugin, OptionalPlugin } from '@atlaskit/editor-common/types';
2
+ import type { HistoryPlugin } from '@atlaskit/editor-plugin-history';
2
3
  import { type PrimaryToolbarPlugin } from '@atlaskit/editor-plugin-primary-toolbar';
3
4
  import type { ShowDiffPlugin } from '@atlaskit/editor-plugin-show-diff';
4
5
  export type TrackChangesPlugin = NextEditorPlugin<'trackChanges', {
@@ -7,11 +8,32 @@ export type TrackChangesPlugin = NextEditorPlugin<'trackChanges', {
7
8
  * Toggles the displaying of changes in the editor.
8
9
  */
9
10
  toggleChanges: EditorCommand;
11
+ /**
12
+ * Resets the baseline used for tracking changes in the editor.
13
+ */
14
+ resetBaseline: EditorCommand;
10
15
  };
11
16
  dependencies: [
17
+ /**
18
+ * Primary toolbar plugin for registering the track changes button.
19
+ */
12
20
  OptionalPlugin<PrimaryToolbarPlugin>,
21
+ /**
22
+ * For ensuring the tracked changes align with the history
23
+ */
24
+ OptionalPlugin<HistoryPlugin>,
25
+ /**
26
+ * Show diff plugin for showing the changes in a diff view.
27
+ */
13
28
  ShowDiffPlugin
14
29
  ];
30
+ pluginConfiguration?: {
31
+ /**
32
+ * Whether the track changes button should be shown on the toolbar.
33
+ * Defaults to false.
34
+ */
35
+ showOnToolbar?: boolean;
36
+ };
15
37
  sharedState: {
16
38
  /**
17
39
  * Whether the track changes feature is currently displaying changes.
package/docs/0-intro.tsx CHANGED
@@ -30,11 +30,47 @@ The \`dependencies\`, \`configuration\`, \`state\`, \`actions\`, and \`commands\
30
30
  below:
31
31
 
32
32
  ${code`
33
- type TrackChangesPlugin = NextEditorPlugin<'trackChanges', {
34
- commands: {
35
- toggleChanges: EditorCommand
36
- }
37
- }>;
33
+ type TrackChangesPlugin = NextEditorPlugin<
34
+ 'trackChanges',
35
+ {
36
+ commands: {
37
+ /**
38
+ * Toggles the displaying of changes in the editor.
39
+ */
40
+ toggleChanges: EditorCommand;
41
+ };
42
+ dependencies: [
43
+ /**
44
+ * Primary toolbar plugin for registering the track changes button.
45
+ */
46
+ OptionalPlugin<PrimaryToolbarPlugin>,
47
+ /**
48
+ * Show diff plugin for showing the changes in a diff view.
49
+ */
50
+ ShowDiffPlugin,
51
+ ];
52
+ pluginConfiguration?: {
53
+ /**
54
+ * Whether the track changes button should be shown on the toolbar.
55
+ * Defaults to false.
56
+ */
57
+ showOnToolbar?: boolean;
58
+ };
59
+ sharedState: {
60
+ /**
61
+ * Whether the track changes feature is currently displaying changes.
62
+ * Defaults to false.
63
+ */
64
+ isDisplayingChanges: boolean;
65
+ /**
66
+ * If there are changes in the document that determine if track changes button
67
+ * should be enabled.
68
+ * This will only be false initially before any changes in the session.
69
+ */
70
+ isShowDiffAvailable: boolean;
71
+ };
72
+ }
73
+ >;
38
74
  `}
39
75
 
40
76
  ### Example Usage
@@ -51,7 +87,8 @@ import { basePlugin } from '@atlaskit/editor-plugins/base';
51
87
  import { Box } from '@atlaskit/primitives/compiled';
52
88
  import { token } from '@atlaskit/tokens';
53
89
 
54
- import { trackChangesPlugin } from '../src/trackChangesPlugin';
90
+ import { showDiffPlugin } from '@atlaskit/editor-plugin-show-diff';
91
+ import { trackChangesPlugin } from '@atlaskit/editor-plugin-track-changes';
55
92
 
56
93
  const styles = cssMap({
57
94
  aboveEditor: {
@@ -69,7 +106,7 @@ const styles = cssMap({
69
106
  function Editor() {
70
107
  const { preset, editorApi } = usePreset(
71
108
  (builder) =>
72
- builder.add(basePlugin).add(trackChangesPlugin),
109
+ builder.add(basePlugin).add(showDiffPlugin).add(trackChangesPlugin),
73
110
  [],
74
111
  );
75
112
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-track-changes",
3
- "version": "2.2.0",
3
+ "version": "2.4.0",
4
4
  "description": "ShowDiff plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -32,14 +32,16 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "@atlaskit/button": "^23.3.0",
35
+ "@atlaskit/editor-plugin-history": "3.1.0",
35
36
  "@atlaskit/editor-plugin-primary-toolbar": "^4.1.0",
36
37
  "@atlaskit/editor-plugin-show-diff": "0.0.0",
37
38
  "@atlaskit/editor-prosemirror": "7.0.0",
38
39
  "@atlaskit/icon-lab": "^5.2.0",
39
- "@babel/runtime": "^7.0.0"
40
+ "@babel/runtime": "^7.0.0",
41
+ "react-intl-next": "npm:react-intl@^5.18.1"
40
42
  },
41
43
  "peerDependencies": {
42
- "@atlaskit/editor-common": "^107.13.0",
44
+ "@atlaskit/editor-common": "^107.14.0",
43
45
  "react": "^18.2.0"
44
46
  },
45
47
  "devDependencies": {
package/tsconfig.json CHANGED
@@ -1,12 +1,18 @@
1
1
  {
2
- "extends": "../../../tsconfig.json",
3
- "include": [
4
- "examples/**/*.ts",
5
- "examples/**/*.tsx",
6
- "example-helpers/**/*.ts",
7
- "example-helpers/**/*.tsx",
8
- "src/**/*.ts",
9
- "src/**/*.tsx"
10
- ],
11
- "compilerOptions": {}
2
+ "extends": "../../../tsconfig.json",
3
+ "include": [
4
+ "examples/**/*.ts",
5
+ "examples/**/*.tsx",
6
+ "example-helpers/**/*.ts",
7
+ "example-helpers/**/*.tsx",
8
+ "src/**/*.ts",
9
+ "src/**/*.tsx",
10
+ "**/stories.ts",
11
+ "**/stories.tsx",
12
+ "**/stories/*.ts",
13
+ "**/stories/*.tsx",
14
+ "**/stories/**/*.ts",
15
+ "**/stories/**/*.tsx"
16
+ ],
17
+ "compilerOptions": {}
12
18
  }