@atlaskit/editor-plugin-expand 15.0.5 → 15.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @atlaskit/editor-plugin-expand
2
2
 
3
+ ## 15.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`2d23b40eed4f0`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/2d23b40eed4f0) -
8
+ Add gated content-visibility:auto to tables, expands and media singles to improve editor rendering
9
+ performance on large documents. Applied only to nodes whose rendered size can be estimated closely
10
+ — structurally (row/child counts) for tables and expands, and from the media's own dimensions and
11
+ the renderer's width calculation for media singles. Behind the
12
+ cc_editor_limited_mode_perf_improvements experiment and only active when limited mode is enabled
13
+ for the document (shared large-document detection with the limited-mode plugin).
14
+
15
+ ### Patch Changes
16
+
17
+ - Updated dependencies
18
+
3
19
  ## 15.0.5
4
20
 
5
21
  ### Patch Changes
@@ -16,6 +16,7 @@ var _selection = require("@atlaskit/editor-common/selection");
16
16
  var _styles = require("@atlaskit/editor-common/styles");
17
17
  var _ui = require("@atlaskit/editor-common/ui");
18
18
  var _utils = require("@atlaskit/editor-common/utils");
19
+ var _contentVisibility = require("@atlaskit/editor-common/utils/content-visibility");
19
20
  var _model = require("@atlaskit/editor-prosemirror/model");
20
21
  var _state = require("@atlaskit/editor-prosemirror/state");
21
22
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
@@ -535,6 +536,11 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
535
536
  this.input = this.dom.querySelector(".".concat(_styles.expandClassNames.titleInput));
536
537
  this.titleContainer = this.dom.querySelector(".".concat(_styles.expandClassNames.titleContainer));
537
538
  this.content = this.dom.querySelector(".".concat(_styles.expandClassNames.content));
539
+ (0, _contentVisibility.applyContentVisibility)(this.dom, this.isLimitedModeEnabled(), function () {
540
+ return {
541
+ height: (0, _contentVisibility.estimateExpandIntrinsicHeight)(_this.node, !_this.isCollapsed())
542
+ };
543
+ });
538
544
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
539
545
  this.renderKey = (0, _v.default)();
540
546
  if ((0, _expValEquals.expValEquals)('platform_editor_vc90_transition_expand_icon', 'isEnabled', true)) {
@@ -623,14 +629,31 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
623
629
  }, {
624
630
  key: "updateDisplayStyle",
625
631
  value: function updateDisplayStyle(node) {
632
+ var isCollapsed = this.__livePage ? node.attrs.__expanded : !node.attrs.__expanded;
626
633
  if (this.content) {
627
- var isCollapsed = this.__livePage ? node.attrs.__expanded : !node.attrs.__expanded;
628
634
  if (isCollapsed) {
629
635
  this.content.classList.add(_styles.expandClassNames.contentCollapsed);
630
636
  } else {
631
637
  this.content.classList.remove(_styles.expandClassNames.contentCollapsed);
632
638
  }
633
639
  }
640
+ // Collapsed vs expanded changes the reserved height, so re-apply the intrinsic-size estimate.
641
+ if (this.dom) {
642
+ (0, _contentVisibility.applyContentVisibility)(this.dom, this.isLimitedModeEnabled(), function () {
643
+ return {
644
+ height: (0, _contentVisibility.estimateExpandIntrinsicHeight)(node, !isCollapsed)
645
+ };
646
+ });
647
+ }
648
+ }
649
+ }, {
650
+ key: "isLimitedModeEnabled",
651
+ value: function isLimitedModeEnabled() {
652
+ var _this$api9;
653
+ // Read from `this.view.state` via the exposed plugin key rather than the shared state's
654
+ // `enabled`, which reads a stale `false` during initial EditorView construction (the injection
655
+ // API's editor state isn't wired up yet).
656
+ return Boolean((_this$api9 = this.api) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.limitedMode) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.sharedState.currentState()) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.limitedModePluginKey) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.getState(this.view.state)) === null || _this$api9 === void 0 ? void 0 : _this$api9.documentSizeBreachesThreshold);
634
657
  }
635
658
  }, {
636
659
  key: "stopEvent",
@@ -658,6 +681,14 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
658
681
  value: function update(node, _decorations) {
659
682
  var _this4 = this;
660
683
  if (this.node.type === node.type) {
684
+ // Re-apply in case limited mode flipped from disabled→enabled after the document loaded
685
+ // (the flip is transaction-driven, so this update() fires once it becomes enabled).
686
+ var isCollapsed = this.__livePage ? node.attrs.__expanded : !node.attrs.__expanded;
687
+ (0, _contentVisibility.applyContentVisibility)(this.dom, this.isLimitedModeEnabled(), function () {
688
+ return {
689
+ height: (0, _contentVisibility.estimateExpandIntrinsicHeight)(node, !isCollapsed)
690
+ };
691
+ });
661
692
  if (this.node.attrs.__expanded !== node.attrs.__expanded) {
662
693
  // Instead of re-rendering the view on an expand toggle
663
694
  // we toggle a class name to hide the content and animate the chevron.
@@ -17,8 +17,10 @@ var _expand = require("@atlaskit/editor-common/expand");
17
17
  var _selection = require("@atlaskit/editor-common/selection");
18
18
  var _styles = require("@atlaskit/editor-common/styles");
19
19
  var _utils = require("@atlaskit/editor-common/utils");
20
+ var _contentVisibility = require("@atlaskit/editor-common/utils/content-visibility");
20
21
  var _model = require("@atlaskit/editor-prosemirror/model");
21
22
  var _state = require("@atlaskit/editor-prosemirror/state");
23
+ var _isExperimentEnabled = require("@atlaskit/platform-feature-experiments/is-experiment-enabled");
22
24
  var _prosemirrorHistory = require("@atlaskit/prosemirror-history");
23
25
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
24
26
  var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
@@ -516,6 +518,11 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
516
518
  if (!_expand.expandedState.has(this.node)) {
517
519
  _expand.expandedState.set(this.node, false);
518
520
  }
521
+ (0, _contentVisibility.applyContentVisibility)(this.dom, this.isLimitedModeEnabled(), function () {
522
+ return {
523
+ height: (0, _contentVisibility.estimateExpandIntrinsicHeight)(_this.node, !(0, _expand.isExpandCollapsed)(_this.node))
524
+ };
525
+ });
519
526
  if ((0, _expValEquals.expValEquals)('platform_editor_vc90_transition_expand_icon', 'isEnabled', true)) {
520
527
  this.renderNativeIcon(this.node);
521
528
  } else {
@@ -537,19 +544,39 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
537
544
  this.titleContainer.addEventListener('focus', this.handleFocus);
538
545
  this.icon.addEventListener('keydown', this.handleIconKeyDown);
539
546
  if ((_this$api8 = this.api) !== null && _this$api8 !== void 0 && _this$api8.editorDisabled) {
540
- this.cleanUpEditorDisabledOnChange = this.api.editorDisabled.sharedState.onChange(function (sharedState) {
541
- var editorDisabled = sharedState.nextSharedState.editorDisabled;
542
- if (_this.input) {
543
- if (editorDisabled) {
544
- _this.input.setAttribute('readonly', 'true');
545
- } else {
546
- _this.input.removeAttribute('readonly');
547
- }
548
- }
549
- if (_this.content) {
550
- _this.content.setAttribute('contenteditable', _this.getContentEditable(_this.node) ? 'true' : 'false');
547
+ if ((0, _isExperimentEnabled.isExperimentEnabled)('cc_editor_limited_mode_perf_improvements')) {
548
+ if (this.content) {
549
+ this.content.setAttribute('contenteditable', this.getContentEditable(this.node) ? 'true' : 'false');
551
550
  }
552
- });
551
+ this.cleanUpEditorDisabledOnChange = this.api.editorDisabled.sharedState.onChange(function (sharedState) {
552
+ var editorDisabled = sharedState.nextSharedState.editorDisabled;
553
+ if (_this.input) {
554
+ if (editorDisabled) {
555
+ _this.input.setAttribute('readonly', 'true');
556
+ } else {
557
+ _this.input.removeAttribute('readonly');
558
+ }
559
+ }
560
+ var nextContentEditableValue = _this.getContentEditable(_this.node) ? 'true' : 'false';
561
+ if (_this.content && _this.content.getAttribute('contenteditable') !== nextContentEditableValue) {
562
+ _this.content.setAttribute('contenteditable', nextContentEditableValue);
563
+ }
564
+ });
565
+ } else {
566
+ this.cleanUpEditorDisabledOnChange = this.api.editorDisabled.sharedState.onChange(function (sharedState) {
567
+ var editorDisabled = sharedState.nextSharedState.editorDisabled;
568
+ if (_this.input) {
569
+ if (editorDisabled) {
570
+ _this.input.setAttribute('readonly', 'true');
571
+ } else {
572
+ _this.input.removeAttribute('readonly');
573
+ }
574
+ }
575
+ if (_this.content) {
576
+ _this.content.setAttribute('contenteditable', _this.getContentEditable(_this.node) ? 'true' : 'false');
577
+ }
578
+ });
579
+ }
553
580
  }
554
581
  }
555
582
  return (0, _createClass2.default)(ExpandNodeView, [{
@@ -599,6 +626,13 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
599
626
  }
600
627
  }
601
628
  this.node = node;
629
+ // Re-apply in case limited mode flipped from disabled→enabled after the document loaded
630
+ // (the flip is transaction-driven, so this update() fires once it becomes enabled).
631
+ (0, _contentVisibility.applyContentVisibility)(this.dom, this.isLimitedModeEnabled(), function () {
632
+ return {
633
+ height: (0, _contentVisibility.estimateExpandIntrinsicHeight)(_this2.node, !(0, _expand.isExpandCollapsed)(_this2.node))
634
+ };
635
+ });
602
636
  var currentExpanded = (_expandedState$get2 = _expand.expandedState.get(node)) !== null && _expandedState$get2 !== void 0 ? _expandedState$get2 : false;
603
637
  var hasChanged = (0, _experiments.editorExperiment)('platform_editor_block_menu', true, {
604
638
  exposure: true
@@ -640,6 +674,15 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
640
674
  expanded: expanded !== null && expanded !== void 0 ? expanded : false
641
675
  };
642
676
  }
677
+ }, {
678
+ key: "isLimitedModeEnabled",
679
+ value: function isLimitedModeEnabled() {
680
+ var _this$api9;
681
+ // Read from `this.view.state` via the exposed plugin key rather than the shared state's
682
+ // `enabled`, which reads a stale `false` during initial EditorView construction (the injection
683
+ // API's editor state isn't wired up yet).
684
+ return Boolean((_this$api9 = this.api) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.limitedMode) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.sharedState.currentState()) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.limitedModePluginKey) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.getState(this.view.state)) === null || _this$api9 === void 0 ? void 0 : _this$api9.documentSizeBreachesThreshold);
685
+ }
643
686
  }, {
644
687
  key: "updateDisplayStyle",
645
688
  value: function updateDisplayStyle(node) {
@@ -650,6 +693,12 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
650
693
  this.content.classList.remove(_styles.expandClassNames.contentCollapsed);
651
694
  }
652
695
  }
696
+ // Collapsed vs expanded changes the reserved height, so re-apply the intrinsic-size estimate.
697
+ (0, _contentVisibility.applyContentVisibility)(this.dom, this.isLimitedModeEnabled(), function () {
698
+ return {
699
+ height: (0, _contentVisibility.estimateExpandIntrinsicHeight)(node, !(0, _expand.isExpandCollapsed)(node))
700
+ };
701
+ });
653
702
  }
654
703
  }, {
655
704
  key: "updateExpandBodyContentEditable",
@@ -7,6 +7,7 @@ import { GapCursorSelection, RelativeSelectionPos, Side } from '@atlaskit/editor
7
7
  import { expandClassNames } from '@atlaskit/editor-common/styles';
8
8
  import { expandMessages } from '@atlaskit/editor-common/ui';
9
9
  import { closestElement, isEmptyNode } from '@atlaskit/editor-common/utils';
10
+ import { applyContentVisibility, estimateExpandIntrinsicHeight } from '@atlaskit/editor-common/utils/content-visibility';
10
11
  import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
11
12
  import { NodeSelection, Selection } from '@atlaskit/editor-prosemirror/state';
12
13
  import { fg } from '@atlaskit/platform-feature-flags';
@@ -543,6 +544,9 @@ export class ExpandNodeView {
543
544
  this.input = this.dom.querySelector(`.${expandClassNames.titleInput}`);
544
545
  this.titleContainer = this.dom.querySelector(`.${expandClassNames.titleContainer}`);
545
546
  this.content = this.dom.querySelector(`.${expandClassNames.content}`);
547
+ applyContentVisibility(this.dom, this.isLimitedModeEnabled(), () => ({
548
+ height: estimateExpandIntrinsicHeight(this.node, !this.isCollapsed())
549
+ }));
546
550
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
547
551
  this.renderKey = uuid();
548
552
  if (expValEquals('platform_editor_vc90_transition_expand_icon', 'isEnabled', true)) {
@@ -622,14 +626,27 @@ export class ExpandNodeView {
622
626
  }), this.icon, this.renderKey);
623
627
  }
624
628
  updateDisplayStyle(node) {
629
+ const isCollapsed = this.__livePage ? node.attrs.__expanded : !node.attrs.__expanded;
625
630
  if (this.content) {
626
- const isCollapsed = this.__livePage ? node.attrs.__expanded : !node.attrs.__expanded;
627
631
  if (isCollapsed) {
628
632
  this.content.classList.add(expandClassNames.contentCollapsed);
629
633
  } else {
630
634
  this.content.classList.remove(expandClassNames.contentCollapsed);
631
635
  }
632
636
  }
637
+ // Collapsed vs expanded changes the reserved height, so re-apply the intrinsic-size estimate.
638
+ if (this.dom) {
639
+ applyContentVisibility(this.dom, this.isLimitedModeEnabled(), () => ({
640
+ height: estimateExpandIntrinsicHeight(node, !isCollapsed)
641
+ }));
642
+ }
643
+ }
644
+ isLimitedModeEnabled() {
645
+ var _this$api9, _this$api9$limitedMod, _this$api9$limitedMod2, _this$api9$limitedMod3, _this$api9$limitedMod4;
646
+ // Read from `this.view.state` via the exposed plugin key rather than the shared state's
647
+ // `enabled`, which reads a stale `false` during initial EditorView construction (the injection
648
+ // API's editor state isn't wired up yet).
649
+ return Boolean((_this$api9 = this.api) === null || _this$api9 === void 0 ? void 0 : (_this$api9$limitedMod = _this$api9.limitedMode) === null || _this$api9$limitedMod === void 0 ? void 0 : (_this$api9$limitedMod2 = _this$api9$limitedMod.sharedState.currentState()) === null || _this$api9$limitedMod2 === void 0 ? void 0 : (_this$api9$limitedMod3 = _this$api9$limitedMod2.limitedModePluginKey) === null || _this$api9$limitedMod3 === void 0 ? void 0 : (_this$api9$limitedMod4 = _this$api9$limitedMod3.getState(this.view.state)) === null || _this$api9$limitedMod4 === void 0 ? void 0 : _this$api9$limitedMod4.documentSizeBreachesThreshold);
633
650
  }
634
651
  stopEvent(event) {
635
652
  // Ignored via go/ees005
@@ -650,6 +667,12 @@ export class ExpandNodeView {
650
667
  }
651
668
  update(node, _decorations) {
652
669
  if (this.node.type === node.type) {
670
+ // Re-apply in case limited mode flipped from disabled→enabled after the document loaded
671
+ // (the flip is transaction-driven, so this update() fires once it becomes enabled).
672
+ const isCollapsed = this.__livePage ? node.attrs.__expanded : !node.attrs.__expanded;
673
+ applyContentVisibility(this.dom, this.isLimitedModeEnabled(), () => ({
674
+ height: estimateExpandIntrinsicHeight(node, !isCollapsed)
675
+ }));
653
676
  if (this.node.attrs.__expanded !== node.attrs.__expanded) {
654
677
  // Instead of re-rendering the view on an expand toggle
655
678
  // we toggle a class name to hide the content and animate the chevron.
@@ -8,8 +8,10 @@ import { expandedState, isExpandCollapsed } from '@atlaskit/editor-common/expand
8
8
  import { GapCursorSelection, RelativeSelectionPos, Side } from '@atlaskit/editor-common/selection';
9
9
  import { expandClassNames } from '@atlaskit/editor-common/styles';
10
10
  import { closestElement, isEmptyNode } from '@atlaskit/editor-common/utils';
11
+ import { applyContentVisibility, estimateExpandIntrinsicHeight } from '@atlaskit/editor-common/utils/content-visibility';
11
12
  import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
12
13
  import { NodeSelection, Selection } from '@atlaskit/editor-prosemirror/state';
14
+ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
13
15
  import { redo, undo } from '@atlaskit/prosemirror-history';
14
16
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
15
17
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
@@ -520,6 +522,9 @@ export class ExpandNodeView {
520
522
  if (!expandedState.has(this.node)) {
521
523
  expandedState.set(this.node, false);
522
524
  }
525
+ applyContentVisibility(this.dom, this.isLimitedModeEnabled(), () => ({
526
+ height: estimateExpandIntrinsicHeight(this.node, !isExpandCollapsed(this.node))
527
+ }));
523
528
  if (expValEquals('platform_editor_vc90_transition_expand_icon', 'isEnabled', true)) {
524
529
  this.renderNativeIcon(this.node);
525
530
  } else {
@@ -541,19 +546,39 @@ export class ExpandNodeView {
541
546
  this.titleContainer.addEventListener('focus', this.handleFocus);
542
547
  this.icon.addEventListener('keydown', this.handleIconKeyDown);
543
548
  if ((_this$api8 = this.api) !== null && _this$api8 !== void 0 && _this$api8.editorDisabled) {
544
- this.cleanUpEditorDisabledOnChange = this.api.editorDisabled.sharedState.onChange(sharedState => {
545
- const editorDisabled = sharedState.nextSharedState.editorDisabled;
546
- if (this.input) {
547
- if (editorDisabled) {
548
- this.input.setAttribute('readonly', 'true');
549
- } else {
550
- this.input.removeAttribute('readonly');
551
- }
552
- }
549
+ if (isExperimentEnabled('cc_editor_limited_mode_perf_improvements')) {
553
550
  if (this.content) {
554
551
  this.content.setAttribute('contenteditable', this.getContentEditable(this.node) ? 'true' : 'false');
555
552
  }
556
- });
553
+ this.cleanUpEditorDisabledOnChange = this.api.editorDisabled.sharedState.onChange(sharedState => {
554
+ const editorDisabled = sharedState.nextSharedState.editorDisabled;
555
+ if (this.input) {
556
+ if (editorDisabled) {
557
+ this.input.setAttribute('readonly', 'true');
558
+ } else {
559
+ this.input.removeAttribute('readonly');
560
+ }
561
+ }
562
+ const nextContentEditableValue = this.getContentEditable(this.node) ? 'true' : 'false';
563
+ if (this.content && this.content.getAttribute('contenteditable') !== nextContentEditableValue) {
564
+ this.content.setAttribute('contenteditable', nextContentEditableValue);
565
+ }
566
+ });
567
+ } else {
568
+ this.cleanUpEditorDisabledOnChange = this.api.editorDisabled.sharedState.onChange(sharedState => {
569
+ const editorDisabled = sharedState.nextSharedState.editorDisabled;
570
+ if (this.input) {
571
+ if (editorDisabled) {
572
+ this.input.setAttribute('readonly', 'true');
573
+ } else {
574
+ this.input.removeAttribute('readonly');
575
+ }
576
+ }
577
+ if (this.content) {
578
+ this.content.setAttribute('contenteditable', this.getContentEditable(this.node) ? 'true' : 'false');
579
+ }
580
+ });
581
+ }
557
582
  }
558
583
  }
559
584
  stopEvent(event) {
@@ -596,6 +621,11 @@ export class ExpandNodeView {
596
621
  }
597
622
  }
598
623
  this.node = node;
624
+ // Re-apply in case limited mode flipped from disabled→enabled after the document loaded
625
+ // (the flip is transaction-driven, so this update() fires once it becomes enabled).
626
+ applyContentVisibility(this.dom, this.isLimitedModeEnabled(), () => ({
627
+ height: estimateExpandIntrinsicHeight(this.node, !isExpandCollapsed(this.node))
628
+ }));
599
629
  const currentExpanded = (_expandedState$get2 = expandedState.get(node)) !== null && _expandedState$get2 !== void 0 ? _expandedState$get2 : false;
600
630
  const hasChanged = editorExperiment('platform_editor_block_menu', true, {
601
631
  exposure: true
@@ -633,6 +663,13 @@ export class ExpandNodeView {
633
663
  expanded: expanded !== null && expanded !== void 0 ? expanded : false
634
664
  };
635
665
  }
666
+ isLimitedModeEnabled() {
667
+ var _this$api9, _this$api9$limitedMod, _this$api9$limitedMod2, _this$api9$limitedMod3, _this$api9$limitedMod4;
668
+ // Read from `this.view.state` via the exposed plugin key rather than the shared state's
669
+ // `enabled`, which reads a stale `false` during initial EditorView construction (the injection
670
+ // API's editor state isn't wired up yet).
671
+ return Boolean((_this$api9 = this.api) === null || _this$api9 === void 0 ? void 0 : (_this$api9$limitedMod = _this$api9.limitedMode) === null || _this$api9$limitedMod === void 0 ? void 0 : (_this$api9$limitedMod2 = _this$api9$limitedMod.sharedState.currentState()) === null || _this$api9$limitedMod2 === void 0 ? void 0 : (_this$api9$limitedMod3 = _this$api9$limitedMod2.limitedModePluginKey) === null || _this$api9$limitedMod3 === void 0 ? void 0 : (_this$api9$limitedMod4 = _this$api9$limitedMod3.getState(this.view.state)) === null || _this$api9$limitedMod4 === void 0 ? void 0 : _this$api9$limitedMod4.documentSizeBreachesThreshold);
672
+ }
636
673
  updateDisplayStyle(node) {
637
674
  if (this.content) {
638
675
  if (isExpandCollapsed(node)) {
@@ -641,6 +678,10 @@ export class ExpandNodeView {
641
678
  this.content.classList.remove(expandClassNames.contentCollapsed);
642
679
  }
643
680
  }
681
+ // Collapsed vs expanded changes the reserved height, so re-apply the intrinsic-size estimate.
682
+ applyContentVisibility(this.dom, this.isLimitedModeEnabled(), () => ({
683
+ height: estimateExpandIntrinsicHeight(node, !isExpandCollapsed(node))
684
+ }));
644
685
  }
645
686
  updateExpandBodyContentEditable() {
646
687
  // Disallow interaction/selection inside expand body when collapsed.
@@ -11,6 +11,7 @@ import { GapCursorSelection, RelativeSelectionPos, Side } from '@atlaskit/editor
11
11
  import { expandClassNames } from '@atlaskit/editor-common/styles';
12
12
  import { expandMessages } from '@atlaskit/editor-common/ui';
13
13
  import { closestElement, isEmptyNode } from '@atlaskit/editor-common/utils';
14
+ import { applyContentVisibility, estimateExpandIntrinsicHeight } from '@atlaskit/editor-common/utils/content-visibility';
14
15
  import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
15
16
  import { NodeSelection, Selection } from '@atlaskit/editor-prosemirror/state';
16
17
  import { fg } from '@atlaskit/platform-feature-flags';
@@ -528,6 +529,11 @@ export var ExpandNodeView = /*#__PURE__*/function () {
528
529
  this.input = this.dom.querySelector(".".concat(expandClassNames.titleInput));
529
530
  this.titleContainer = this.dom.querySelector(".".concat(expandClassNames.titleContainer));
530
531
  this.content = this.dom.querySelector(".".concat(expandClassNames.content));
532
+ applyContentVisibility(this.dom, this.isLimitedModeEnabled(), function () {
533
+ return {
534
+ height: estimateExpandIntrinsicHeight(_this.node, !_this.isCollapsed())
535
+ };
536
+ });
531
537
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
532
538
  this.renderKey = uuid();
533
539
  if (expValEquals('platform_editor_vc90_transition_expand_icon', 'isEnabled', true)) {
@@ -616,14 +622,31 @@ export var ExpandNodeView = /*#__PURE__*/function () {
616
622
  }, {
617
623
  key: "updateDisplayStyle",
618
624
  value: function updateDisplayStyle(node) {
625
+ var isCollapsed = this.__livePage ? node.attrs.__expanded : !node.attrs.__expanded;
619
626
  if (this.content) {
620
- var isCollapsed = this.__livePage ? node.attrs.__expanded : !node.attrs.__expanded;
621
627
  if (isCollapsed) {
622
628
  this.content.classList.add(expandClassNames.contentCollapsed);
623
629
  } else {
624
630
  this.content.classList.remove(expandClassNames.contentCollapsed);
625
631
  }
626
632
  }
633
+ // Collapsed vs expanded changes the reserved height, so re-apply the intrinsic-size estimate.
634
+ if (this.dom) {
635
+ applyContentVisibility(this.dom, this.isLimitedModeEnabled(), function () {
636
+ return {
637
+ height: estimateExpandIntrinsicHeight(node, !isCollapsed)
638
+ };
639
+ });
640
+ }
641
+ }
642
+ }, {
643
+ key: "isLimitedModeEnabled",
644
+ value: function isLimitedModeEnabled() {
645
+ var _this$api9;
646
+ // Read from `this.view.state` via the exposed plugin key rather than the shared state's
647
+ // `enabled`, which reads a stale `false` during initial EditorView construction (the injection
648
+ // API's editor state isn't wired up yet).
649
+ return Boolean((_this$api9 = this.api) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.limitedMode) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.sharedState.currentState()) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.limitedModePluginKey) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.getState(this.view.state)) === null || _this$api9 === void 0 ? void 0 : _this$api9.documentSizeBreachesThreshold);
627
650
  }
628
651
  }, {
629
652
  key: "stopEvent",
@@ -651,6 +674,14 @@ export var ExpandNodeView = /*#__PURE__*/function () {
651
674
  value: function update(node, _decorations) {
652
675
  var _this4 = this;
653
676
  if (this.node.type === node.type) {
677
+ // Re-apply in case limited mode flipped from disabled→enabled after the document loaded
678
+ // (the flip is transaction-driven, so this update() fires once it becomes enabled).
679
+ var isCollapsed = this.__livePage ? node.attrs.__expanded : !node.attrs.__expanded;
680
+ applyContentVisibility(this.dom, this.isLimitedModeEnabled(), function () {
681
+ return {
682
+ height: estimateExpandIntrinsicHeight(node, !isCollapsed)
683
+ };
684
+ });
654
685
  if (this.node.attrs.__expanded !== node.attrs.__expanded) {
655
686
  // Instead of re-rendering the view on an expand toggle
656
687
  // we toggle a class name to hide the content and animate the chevron.
@@ -10,8 +10,10 @@ import { expandedState, isExpandCollapsed } from '@atlaskit/editor-common/expand
10
10
  import { GapCursorSelection, RelativeSelectionPos, Side } from '@atlaskit/editor-common/selection';
11
11
  import { expandClassNames } from '@atlaskit/editor-common/styles';
12
12
  import { closestElement, isEmptyNode } from '@atlaskit/editor-common/utils';
13
+ import { applyContentVisibility, estimateExpandIntrinsicHeight } from '@atlaskit/editor-common/utils/content-visibility';
13
14
  import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
14
15
  import { NodeSelection, Selection } from '@atlaskit/editor-prosemirror/state';
16
+ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
15
17
  import { redo, undo } from '@atlaskit/prosemirror-history';
16
18
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
17
19
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
@@ -508,6 +510,11 @@ export var ExpandNodeView = /*#__PURE__*/function () {
508
510
  if (!expandedState.has(this.node)) {
509
511
  expandedState.set(this.node, false);
510
512
  }
513
+ applyContentVisibility(this.dom, this.isLimitedModeEnabled(), function () {
514
+ return {
515
+ height: estimateExpandIntrinsicHeight(_this.node, !isExpandCollapsed(_this.node))
516
+ };
517
+ });
511
518
  if (expValEquals('platform_editor_vc90_transition_expand_icon', 'isEnabled', true)) {
512
519
  this.renderNativeIcon(this.node);
513
520
  } else {
@@ -529,19 +536,39 @@ export var ExpandNodeView = /*#__PURE__*/function () {
529
536
  this.titleContainer.addEventListener('focus', this.handleFocus);
530
537
  this.icon.addEventListener('keydown', this.handleIconKeyDown);
531
538
  if ((_this$api8 = this.api) !== null && _this$api8 !== void 0 && _this$api8.editorDisabled) {
532
- this.cleanUpEditorDisabledOnChange = this.api.editorDisabled.sharedState.onChange(function (sharedState) {
533
- var editorDisabled = sharedState.nextSharedState.editorDisabled;
534
- if (_this.input) {
535
- if (editorDisabled) {
536
- _this.input.setAttribute('readonly', 'true');
537
- } else {
538
- _this.input.removeAttribute('readonly');
539
- }
540
- }
541
- if (_this.content) {
542
- _this.content.setAttribute('contenteditable', _this.getContentEditable(_this.node) ? 'true' : 'false');
539
+ if (isExperimentEnabled('cc_editor_limited_mode_perf_improvements')) {
540
+ if (this.content) {
541
+ this.content.setAttribute('contenteditable', this.getContentEditable(this.node) ? 'true' : 'false');
543
542
  }
544
- });
543
+ this.cleanUpEditorDisabledOnChange = this.api.editorDisabled.sharedState.onChange(function (sharedState) {
544
+ var editorDisabled = sharedState.nextSharedState.editorDisabled;
545
+ if (_this.input) {
546
+ if (editorDisabled) {
547
+ _this.input.setAttribute('readonly', 'true');
548
+ } else {
549
+ _this.input.removeAttribute('readonly');
550
+ }
551
+ }
552
+ var nextContentEditableValue = _this.getContentEditable(_this.node) ? 'true' : 'false';
553
+ if (_this.content && _this.content.getAttribute('contenteditable') !== nextContentEditableValue) {
554
+ _this.content.setAttribute('contenteditable', nextContentEditableValue);
555
+ }
556
+ });
557
+ } else {
558
+ this.cleanUpEditorDisabledOnChange = this.api.editorDisabled.sharedState.onChange(function (sharedState) {
559
+ var editorDisabled = sharedState.nextSharedState.editorDisabled;
560
+ if (_this.input) {
561
+ if (editorDisabled) {
562
+ _this.input.setAttribute('readonly', 'true');
563
+ } else {
564
+ _this.input.removeAttribute('readonly');
565
+ }
566
+ }
567
+ if (_this.content) {
568
+ _this.content.setAttribute('contenteditable', _this.getContentEditable(_this.node) ? 'true' : 'false');
569
+ }
570
+ });
571
+ }
545
572
  }
546
573
  }
547
574
  return _createClass(ExpandNodeView, [{
@@ -591,6 +618,13 @@ export var ExpandNodeView = /*#__PURE__*/function () {
591
618
  }
592
619
  }
593
620
  this.node = node;
621
+ // Re-apply in case limited mode flipped from disabled→enabled after the document loaded
622
+ // (the flip is transaction-driven, so this update() fires once it becomes enabled).
623
+ applyContentVisibility(this.dom, this.isLimitedModeEnabled(), function () {
624
+ return {
625
+ height: estimateExpandIntrinsicHeight(_this2.node, !isExpandCollapsed(_this2.node))
626
+ };
627
+ });
594
628
  var currentExpanded = (_expandedState$get2 = expandedState.get(node)) !== null && _expandedState$get2 !== void 0 ? _expandedState$get2 : false;
595
629
  var hasChanged = editorExperiment('platform_editor_block_menu', true, {
596
630
  exposure: true
@@ -632,6 +666,15 @@ export var ExpandNodeView = /*#__PURE__*/function () {
632
666
  expanded: expanded !== null && expanded !== void 0 ? expanded : false
633
667
  };
634
668
  }
669
+ }, {
670
+ key: "isLimitedModeEnabled",
671
+ value: function isLimitedModeEnabled() {
672
+ var _this$api9;
673
+ // Read from `this.view.state` via the exposed plugin key rather than the shared state's
674
+ // `enabled`, which reads a stale `false` during initial EditorView construction (the injection
675
+ // API's editor state isn't wired up yet).
676
+ return Boolean((_this$api9 = this.api) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.limitedMode) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.sharedState.currentState()) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.limitedModePluginKey) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.getState(this.view.state)) === null || _this$api9 === void 0 ? void 0 : _this$api9.documentSizeBreachesThreshold);
677
+ }
635
678
  }, {
636
679
  key: "updateDisplayStyle",
637
680
  value: function updateDisplayStyle(node) {
@@ -642,6 +685,12 @@ export var ExpandNodeView = /*#__PURE__*/function () {
642
685
  this.content.classList.remove(expandClassNames.contentCollapsed);
643
686
  }
644
687
  }
688
+ // Collapsed vs expanded changes the reserved height, so re-apply the intrinsic-size estimate.
689
+ applyContentVisibility(this.dom, this.isLimitedModeEnabled(), function () {
690
+ return {
691
+ height: estimateExpandIntrinsicHeight(node, !isExpandCollapsed(node))
692
+ };
693
+ });
645
694
  }
646
695
  }, {
647
696
  key: "updateExpandBodyContentEditable",
@@ -50,6 +50,7 @@ export declare class ExpandNodeView implements NodeView {
50
50
  private handleRedoFromTitle;
51
51
  private getContentEditable;
52
52
  private updateDisplayStyle;
53
+ private isLimitedModeEnabled;
53
54
  stopEvent(event: Event): boolean;
54
55
  ignoreMutation(mutationRecord: MutationRecord | {
55
56
  target: Node;
@@ -57,6 +57,7 @@ export declare class ExpandNodeView implements NodeView {
57
57
  }): boolean;
58
58
  update(node: PmNode, _decorations: readonly Decoration[]): boolean;
59
59
  updateExpandToggleIcon(node: PmNode): void;
60
+ private isLimitedModeEnabled;
60
61
  private updateDisplayStyle;
61
62
  updateExpandBodyContentEditable(): void;
62
63
  private renderNativeIcon;
@@ -7,6 +7,7 @@ import type { DecorationsPlugin } from '@atlaskit/editor-plugin-decorations';
7
7
  import type { EditorDisabledPlugin } from '@atlaskit/editor-plugin-editor-disabled';
8
8
  import type { EditorViewModePlugin } from '@atlaskit/editor-plugin-editor-viewmode';
9
9
  import type { FeatureFlagsPlugin } from '@atlaskit/editor-plugin-feature-flags';
10
+ import type { LimitedModePlugin } from '@atlaskit/editor-plugin-limited-mode/limited-mode-plugin-type';
10
11
  import type { LocalIdPlugin } from '@atlaskit/editor-plugin-local-id';
11
12
  import type { SelectionPlugin } from '@atlaskit/editor-plugin-selection';
12
13
  import type { SelectionMarkerPlugin } from '@atlaskit/editor-plugin-selection-marker';
@@ -53,6 +54,7 @@ export type ExpandPluginDependencies = [
53
54
  OptionalPlugin<EditorDisabledPlugin>,
54
55
  OptionalPlugin<FeatureFlagsPlugin>,
55
56
  OptionalPlugin<EditorViewModePlugin>,
57
+ OptionalPlugin<LimitedModePlugin>,
56
58
  OptionalPlugin<BlockMenuPlugin>,
57
59
  OptionalPlugin<LocalIdPlugin>,
58
60
  OptionalPlugin<BlockControlsPlugin>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-expand",
3
- "version": "15.0.5",
3
+ "version": "15.1.0",
4
4
  "description": "Expand plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -29,6 +29,7 @@
29
29
  "@atlaskit/editor-plugin-decorations": "^14.0.0",
30
30
  "@atlaskit/editor-plugin-editor-disabled": "^14.0.0",
31
31
  "@atlaskit/editor-plugin-editor-viewmode": "^16.0.0",
32
+ "@atlaskit/editor-plugin-limited-mode": "^11.0.0",
32
33
  "@atlaskit/editor-plugin-local-id": "^12.0.0",
33
34
  "@atlaskit/editor-plugin-selection": "^14.0.0",
34
35
  "@atlaskit/editor-plugin-selection-marker": "^14.0.0",
@@ -38,6 +39,7 @@
38
39
  "@atlaskit/editor-toolbar": "^2.4.0",
39
40
  "@atlaskit/icon": "^37.3.0",
40
41
  "@atlaskit/icon-lab": "^7.5.0",
42
+ "@atlaskit/platform-feature-experiments": "^0.3.0",
41
43
  "@atlaskit/platform-feature-flags": "^2.1.0",
42
44
  "@atlaskit/prosemirror-history": "^1.1.0",
43
45
  "@atlaskit/tmp-editor-statsig": "^147.0.0",
@@ -49,7 +51,7 @@
49
51
  "w3c-keyname": "^2.1.8"
50
52
  },
51
53
  "peerDependencies": {
52
- "@atlaskit/editor-common": "^118.10.0",
54
+ "@atlaskit/editor-common": "^118.11.0",
53
55
  "react": "^18.2.0 || ^19.2.0",
54
56
  "react-dom": "^18.2.0 || ^19.2.0",
55
57
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"