@atlaskit/editor-core 215.24.1 → 215.26.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 (28) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/cjs/create-editor/ReactEditorView/handleEditorFocus.js +45 -54
  3. package/dist/cjs/create-editor/ReactEditorView.js +33 -43
  4. package/dist/cjs/ui/EditorContentContainer/EditorContentContainer.js +3 -1
  5. package/dist/cjs/ui/EditorContentContainer/styles/blockTypeStyles.js +14 -1
  6. package/dist/cjs/ui/EditorContentContainer/styles/placeholderStyles.js +13 -0
  7. package/dist/cjs/version-wrapper.js +1 -1
  8. package/dist/es2019/create-editor/ReactEditorView/handleEditorFocus.js +45 -49
  9. package/dist/es2019/create-editor/ReactEditorView.js +34 -42
  10. package/dist/es2019/ui/EditorContentContainer/EditorContentContainer.js +5 -3
  11. package/dist/es2019/ui/EditorContentContainer/styles/blockTypeStyles.js +13 -0
  12. package/dist/es2019/ui/EditorContentContainer/styles/placeholderStyles.js +14 -1
  13. package/dist/es2019/version-wrapper.js +1 -1
  14. package/dist/esm/create-editor/ReactEditorView/handleEditorFocus.js +45 -53
  15. package/dist/esm/create-editor/ReactEditorView.js +33 -43
  16. package/dist/esm/ui/EditorContentContainer/EditorContentContainer.js +5 -3
  17. package/dist/esm/ui/EditorContentContainer/styles/blockTypeStyles.js +13 -0
  18. package/dist/esm/ui/EditorContentContainer/styles/placeholderStyles.js +14 -1
  19. package/dist/esm/version-wrapper.js +1 -1
  20. package/dist/types/create-editor/create-universal-preset.d.ts +1 -0
  21. package/dist/types/presets/universal.d.ts +1 -0
  22. package/dist/types/presets/useUniversalPreset.d.ts +1 -0
  23. package/dist/types/ui/EditorContentContainer/styles/blockTypeStyles.d.ts +1 -0
  24. package/dist/types-ts4.5/create-editor/create-universal-preset.d.ts +1 -0
  25. package/dist/types-ts4.5/presets/universal.d.ts +1 -0
  26. package/dist/types-ts4.5/presets/useUniversalPreset.d.ts +1 -0
  27. package/dist/types-ts4.5/ui/EditorContentContainer/styles/blockTypeStyles.d.ts +1 -0
  28. package/package.json +4 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # @atlaskit/editor-core
2
2
 
3
+ ## 215.26.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`595b07a99bd65`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/595b07a99bd65) -
8
+ [https://hello.jira.atlassian.cloud/browse/EDITOR-3995](EDITOR-3995) - add toolbar supporting to
9
+ `EditorSSRRenderer`
10
+
11
+ ### Patch Changes
12
+
13
+ - [`58e8dc3afa08d`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/58e8dc3afa08d) -
14
+ [ux] [EDITOR-2469] add fade in animation to placeholder on empty paragraph
15
+ - Updated dependencies
16
+
17
+ ## 215.25.0
18
+
19
+ ### Minor Changes
20
+
21
+ - [`4d73a0f30526b`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/4d73a0f30526b) -
22
+ Cleanup platform_editor_react_18_autofocus_fix
23
+
24
+ ### Patch Changes
25
+
26
+ - [`b10f0252621b0`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/b10f0252621b0) -
27
+ Set padding top and bottom on blockquote to avoid batch.css overrides
28
+ - [`342bed74cf6e9`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/342bed74cf6e9) -
29
+ EDITOR-4037 Block menu selection extension click handling
30
+ - Updated dependencies
31
+
3
32
  ## 215.24.1
4
33
 
5
34
  ### Patch Changes
@@ -1,68 +1,59 @@
1
1
  "use strict";
2
2
 
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
3
  Object.defineProperty(exports, "__esModule", {
5
4
  value: true
6
5
  });
7
6
  exports.handleEditorFocus = handleEditorFocus;
8
- var _react = _interopRequireDefault(require("react"));
9
7
  var _state = require("@atlaskit/editor-prosemirror/state");
10
- var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
11
8
  function handleEditorFocus(view) {
9
+ var _domSelection$getRang;
12
10
  if (view !== null && view !== void 0 && view.hasFocus()) {
13
11
  return;
14
12
  }
15
13
 
16
- /**
17
- * If startTransition is available (in React 18),
18
- * don't use setTimeout as startTransition will be used in ReactEditorViewNext.
19
- * setTimeout(fn, 0) will not defer the focus reliably in React 18 with
20
- * concurrent rendering.
21
- */
22
- var react16OnlySetTimeout = _react.default !== null && _react.default !== void 0 && _react.default.startTransition && (0, _platformFeatureFlags.fg)('platform_editor_react_18_autofocus_fix') ? function (fn) {
23
- return fn();
24
- } : function (fn) {
25
- return window.setTimeout(fn, 0);
26
- };
27
- return react16OnlySetTimeout(function () {
28
- // Due to race conditions during editor lifecycle transitions (e.g. SPA route changes during opening or closing)
29
- // where the view (and its internal docView) may have been destroyed, the timeout callback may fire on a stale view.
30
- // Bail out in that scenario to prevent operating on an unmounted view.
31
- if (view !== null && view !== void 0 && view.isDestroyed) {
32
- return;
33
- }
34
- if (view !== null && view !== void 0 && view.hasFocus()) {
35
- return;
36
- }
37
- if (!window.getSelection) {
38
- view === null || view === void 0 || view.focus();
39
- return;
40
- }
41
- var domSelection = window.getSelection();
42
- if (!domSelection || domSelection.rangeCount === 0) {
43
- view === null || view === void 0 || view.focus();
44
- return;
45
- }
46
- var range = domSelection.getRangeAt(0);
47
- // if selection is outside editor focus and exit
48
- if (view && range.startContainer.contains(view.dom)) {
49
- view.focus();
50
- return;
51
- }
14
+ // Due to race conditions during editor lifecycle transitions (e.g. SPA route changes during opening or closing)
15
+ // where the view (and its internal docView) may have been destroyed, the timeout callback may fire on a stale view.
16
+ // Bail out in that scenario to prevent operating on an unmounted view.
17
+ if (view !== null && view !== void 0 && view.isDestroyed) {
18
+ return;
19
+ }
20
+ if (view !== null && view !== void 0 && view.hasFocus()) {
21
+ return;
22
+ }
23
+ if (!window.getSelection) {
24
+ view === null || view === void 0 || view.focus();
25
+ return;
26
+ }
27
+ var domSelection = window.getSelection();
28
+ if (!domSelection || domSelection.rangeCount === 0) {
29
+ view === null || view === void 0 || view.focus();
30
+ return;
31
+ }
52
32
 
53
- // set cursor/selection and focus
54
- var anchor = view === null || view === void 0 ? void 0 : view.posAtDOM(range.startContainer, range.startOffset);
55
- var head = view === null || view === void 0 ? void 0 : view.posAtDOM(range.endContainer, range.endOffset);
56
- // if anchor or head < 0 focus and exit
57
- if (anchor && anchor < 0 || head && head < 0) {
58
- view === null || view === void 0 || view.focus();
59
- return;
60
- }
61
- if (view && anchor) {
62
- var selection = _state.TextSelection.create(view.state.doc, anchor, head);
63
- var tr = view.state.tr.setSelection(selection);
64
- view.dispatch(tr);
65
- view.focus();
66
- }
67
- });
33
+ // If not mocked properly in tests, getRangeAt may not exist.
34
+ var range = (_domSelection$getRang = domSelection.getRangeAt) === null || _domSelection$getRang === void 0 ? void 0 : _domSelection$getRang.call(domSelection, 0);
35
+ if (!range) {
36
+ return;
37
+ }
38
+
39
+ // if selection is outside editor focus and exit
40
+ if (view && range !== null && range !== void 0 && range.startContainer.contains(view.dom)) {
41
+ view.focus();
42
+ return;
43
+ }
44
+
45
+ // set cursor/selection and focus
46
+ var anchor = view === null || view === void 0 ? void 0 : view.posAtDOM(range.startContainer, range.startOffset);
47
+ var head = view === null || view === void 0 ? void 0 : view.posAtDOM(range.endContainer, range.endOffset);
48
+ // if anchor or head < 0 focus and exit
49
+ if (anchor && anchor < 0 || head && head < 0) {
50
+ view === null || view === void 0 || view.focus();
51
+ return;
52
+ }
53
+ if (view && anchor) {
54
+ var selection = _state.TextSelection.create(view.state.doc, anchor, head);
55
+ var tr = view.state.tr.setSelection(selection);
56
+ view.dispatch(tr);
57
+ view.focus();
58
+ }
68
59
  }
@@ -74,6 +74,7 @@ function ReactEditorView(props) {
74
74
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
75
75
  editorAPI = _useState2[0],
76
76
  setEditorAPI = _useState2[1];
77
+ var ssrEditorStateRef = (0, _react.useRef)(undefined);
77
78
  var editorRef = (0, _react.useRef)(null);
78
79
  var viewRef = (0, _react.useRef)();
79
80
  var focusTimeoutId = (0, _react.useRef)();
@@ -101,8 +102,8 @@ function ReactEditorView(props) {
101
102
  return (0, _featureFlagsFromProps.createFeatureFlagsFromProps)(editorPropFeatureFlags);
102
103
  }, [editorPropFeatureFlags]);
103
104
  var getEditorState = (0, _react.useCallback)(function () {
104
- var _viewRef$current;
105
- return (_viewRef$current = viewRef.current) === null || _viewRef$current === void 0 ? void 0 : _viewRef$current.state;
105
+ var _ssrEditorStateRef$cu, _viewRef$current;
106
+ return (_ssrEditorStateRef$cu = ssrEditorStateRef.current) !== null && _ssrEditorStateRef$cu !== void 0 ? _ssrEditorStateRef$cu : (_viewRef$current = viewRef.current) === null || _viewRef$current === void 0 ? void 0 : _viewRef$current.state;
106
107
  }, []);
107
108
  var getEditorView = (0, _react.useCallback)(function () {
108
109
  return viewRef.current;
@@ -546,7 +547,7 @@ function ReactEditorView(props) {
546
547
  // We don't need to focus anything in SSR.
547
548
  return;
548
549
  }
549
- if (shouldFocus && editorView !== null && editorView !== void 0 && (_editorView$props$edi = (_editorView$props = editorView.props).editable) !== null && _editorView$props$edi !== void 0 && _editorView$props$edi.call(_editorView$props, editorView.state) && (0, _platformFeatureFlags.fg)('platform_editor_react_18_autofocus_fix')) {
550
+ if (shouldFocus && editorView !== null && editorView !== void 0 && (_editorView$props$edi = (_editorView$props = editorView.props).editable) !== null && _editorView$props$edi !== void 0 && _editorView$props$edi.call(_editorView$props, editorView.state)) {
550
551
  if (!mitigateScrollJump) {
551
552
  var liveDocWithContent = (__livePage || (0, _expValEquals.expValEquals)('platform_editor_no_cursor_on_edit_page_init', 'isEnabled', true)) && !(0, _document.isEmptyDocument)(editorView.state.doc);
552
553
  if (!liveDocWithContent) {
@@ -648,38 +649,10 @@ function ReactEditorView(props) {
648
649
  eventDispatcher: eventDispatcher,
649
650
  transformer: contentTransformer.current
650
651
  });
651
- if ((0, _platformFeatureFlags.fg)('platform_editor_react_18_autofocus_fix')) {
652
- var _startTransition;
653
- /**
654
- * Defer using startTransition when it is available (in React 18) to fix
655
- * autofocus bug where React 18's concurrent rendering mode interferes with
656
- * setTimeout used in handleEditorFocus, causing autofocus to break.
657
- */
658
- var react18OnlyStartTransition = (_startTransition = _react.default === null || _react.default === void 0 ? void 0 : _react.default.startTransition) !== null && _startTransition !== void 0 ? _startTransition : function (fn) {
659
- return fn();
660
- };
661
- react18OnlyStartTransition(function () {
662
- // Force React to re-render so consumers get a reference to the editor view
663
- setEditorView(view);
664
- });
665
- } else {
666
- if (shouldFocus && view.props.editable && view.props.editable(view.state)) {
667
- if (!mitigateScrollJump) {
668
- var isLivePageWithContent = (__livePage || (0, _expValEquals.expValEquals)('platform_editor_no_cursor_on_edit_page_init', 'isEnabled', true)) && !(0, _document.isEmptyDocument)(view.state.doc);
669
- if (!isLivePageWithContent && shouldFocus && view.props.editable && view.props.editable(view.state)) {
670
- focusTimeoutId.current = (0, _handleEditorFocus.handleEditorFocus)(view);
671
- }
672
- if ((0, _expValEquals.expValEquals)('platform_editor_no_cursor_on_edit_page_init', 'isEnabled', true) && (0, _platformFeatureFlags.fg)('cc_editor_focus_before_editor_on_load')) {
673
- if (shouldFocus && view.props.editable && view.props.editable(view.state) && !(0, _document.isEmptyDocument)(view.state.doc)) {
674
- (0, _focusEditorElement.focusEditorElement)(editorId.current);
675
- }
676
- }
677
- }
678
- }
679
-
652
+ _react.default.startTransition(function () {
680
653
  // Force React to re-render so consumers get a reference to the editor view
681
654
  setEditorView(view);
682
- }
655
+ });
683
656
  } else if (viewRef.current && !node) {
684
657
  // When the appearance is changed, React will call handleEditorViewRef with node === null
685
658
  // to destroy the old EditorView, before calling this method again with node === div to
@@ -703,7 +676,7 @@ function ReactEditorView(props) {
703
676
  (0, _nodeVisibility.nodeVisibilityManager)(viewRef.current.dom).disconnect();
704
677
  viewRef.current = undefined;
705
678
  }
706
- }, [createEditorView, onEditorCreated, eventDispatcher, shouldFocus, __livePage, onEditorDestroyed, handleAnalyticsEvent, mitigateScrollJump]);
679
+ }, [createEditorView, onEditorCreated, eventDispatcher, onEditorDestroyed, handleAnalyticsEvent, mitigateScrollJump]);
707
680
  var createEditor = (0, _react.useCallback)(function (assistiveLabel, assistiveDescribedBy) {
708
681
  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (0, _platformFeatureFlags.fg)('cc_editor_focus_before_editor_on_load') && /*#__PURE__*/_react.default.createElement("div", {
709
682
  tabIndex: -1,
@@ -785,15 +758,16 @@ function ReactEditorView(props) {
785
758
  doc: defaultValue
786
759
  });
787
760
  }, [defaultValue, parseDoc, props.editorProps.sanitizePrivateContent, props.providerFactory]);
788
- var _props$editorProps3 = props.editorProps,
789
- assistiveLabel = _props$editorProps3.assistiveLabel,
790
- assistiveDescribedBy = _props$editorProps3.assistiveDescribedBy;
761
+
791
762
  // We need to check `allowBlockType` in props, because it is now exist in EditorNextProps type.
792
763
  var _ref5 = 'allowBlockType' in props.editorProps ? props.editorProps : {
793
764
  allowBlockType: undefined
794
765
  },
795
766
  allowBlockType = _ref5.allowBlockType;
796
- var ssrEditor = (0, _react.useMemo)(function () {
767
+
768
+ // In separate memo, because some props like `props.intl` that need only for rendering
769
+ // changes many times, but we don't want to process plugins and ADF document for each unnecessary changes.
770
+ var ssrDeps = (0, _react.useMemo)(function () {
797
771
  if (!(0, _coreUtils.isSSR)() || !(0, _expValEquals.expValEquals)('platform_editor_ssr_renderer', 'isEnabled', true)) {
798
772
  return null;
799
773
  }
@@ -805,11 +779,24 @@ function ReactEditorView(props) {
805
779
  }, pluginInjectionAPI.current);
806
780
  var schema = (0, _createSchema.createSchema)((0, _createEditor.processPluginsList)(plugins));
807
781
  var doc = buildDoc(schema);
782
+ return {
783
+ plugins: plugins,
784
+ schema: schema,
785
+ doc: doc
786
+ };
787
+ }, [allowBlockType, buildDoc, props.preset]);
788
+ var _props$editorProps3 = props.editorProps,
789
+ assistiveLabel = _props$editorProps3.assistiveLabel,
790
+ assistiveDescribedBy = _props$editorProps3.assistiveDescribedBy;
791
+ var ssrEditor = (0, _react.useMemo)(function () {
792
+ if (!ssrDeps) {
793
+ return null;
794
+ }
808
795
  return /*#__PURE__*/_react.default.createElement(_editorSsrRenderer.EditorSSRRenderer, {
809
796
  intl: props.intl,
810
- doc: doc,
811
- schema: schema,
812
- plugins: plugins,
797
+ doc: ssrDeps.doc,
798
+ schema: ssrDeps.schema,
799
+ plugins: ssrDeps.plugins,
813
800
  portalProviderAPI: props.portalProviderAPI
814
801
  // IMPORTANT: Keep next props in sync with div that renders a real ProseMirror editor.
815
802
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
@@ -819,9 +806,12 @@ function ReactEditorView(props) {
819
806
  "aria-label": assistiveLabel || props.intl.formatMessage(_messages.editorMessages.editorAssistiveLabel),
820
807
  id: EDIT_AREA_ID,
821
808
  "aria-describedby": assistiveDescribedBy,
822
- "data-editor-id": editorId.current
809
+ "data-editor-id": editorId.current,
810
+ onEditorStateChanged: function onEditorStateChanged(state) {
811
+ ssrEditorStateRef.current = state;
812
+ }
823
813
  });
824
- }, [props.preset, allowBlockType, assistiveLabel, assistiveDescribedBy, props.intl, props.portalProviderAPI, buildDoc]);
814
+ }, [ssrDeps, props.intl, props.portalProviderAPI, assistiveLabel, assistiveDescribedBy]);
825
815
  var editor = (0, _react.useMemo)(function () {
826
816
  // SSR editor will be available only in SSR environment,
827
817
  // in a browser `ssrEditor` will be `null`, and we will render a normal one ProseMirror.
@@ -200,7 +200,9 @@ var EditorContentContainer = /*#__PURE__*/_react.default.forwardRef(function (pr
200
200
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values
201
201
  _blockTypeStyles.blocktypeStyles, (0, _expValEquals.expValEquals)('platform_editor_block_menu', 'isEnabled', true) &&
202
202
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values
203
- _blockTypeStyles.blockquoteSelectedNodeStyles,
203
+ _blockTypeStyles.blockquoteSelectedNodeStyles, (0, _expVal.expVal)('platform_editor_blockquote_zero_padding', 'isEnabled', false) ?
204
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values
205
+ _blockTypeStyles.blockquoteZeroPadding : null,
204
206
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values
205
207
  (0, _platformFeatureFlags.fg)('platform_editor_typography_ugc') ?
206
208
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values
@@ -3,10 +3,23 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.blocktypeStyles_without_fg_platform_editor_typography_ugc = exports.blocktypeStyles_fg_platform_editor_typography_ugc = exports.blocktypeStyles_fg_platform_editor_nested_dnd_styles_changes = exports.blocktypeStyles = exports.blockquoteSelectedNodeStyles = void 0;
6
+ exports.blocktypeStyles_without_fg_platform_editor_typography_ugc = exports.blocktypeStyles_fg_platform_editor_typography_ugc = exports.blocktypeStyles_fg_platform_editor_nested_dnd_styles_changes = exports.blocktypeStyles = exports.blockquoteZeroPadding = exports.blockquoteSelectedNodeStyles = void 0;
7
7
  var _react = require("@emotion/react");
8
8
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled
9
9
 
10
+ // This style is needed to avoid Confluence's batch.css overrides that expand blockquote with extra padding after SSR.
11
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-exported-styles
12
+ var blockquoteZeroPadding = exports.blockquoteZeroPadding = (0, _react.css)({
13
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
14
+ '.ProseMirror': {
15
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
16
+ '& blockquote': {
17
+ paddingTop: 0,
18
+ paddingBottom: 0
19
+ }
20
+ }
21
+ });
22
+
10
23
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-exported-styles
11
24
  var blocktypeStyles = exports.blocktypeStyles = (0, _react.css)({
12
25
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
@@ -7,6 +7,15 @@ exports.placeholderWrapStyles = exports.placeholderTextStyles = exports.placehol
7
7
  var _react = require("@emotion/react");
8
8
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled
9
9
 
10
+ var placeholderFadeInKeyframes = (0, _react.keyframes)({
11
+ from: {
12
+ opacity: 0
13
+ },
14
+ to: {
15
+ opacity: 1
16
+ }
17
+ });
18
+
10
19
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-exported-styles
11
20
  var placeholderTextStyles = exports.placeholderTextStyles = (0, _react.css)({
12
21
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
@@ -90,6 +99,10 @@ var placeholderStyles = exports.placeholderStyles = (0, _react.css)({
90
99
  userSelect: 'none',
91
100
  position: 'absolute'
92
101
  }
102
+ },
103
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
104
+ '.ProseMirror .placeholder-decoration-fade-in': {
105
+ animation: "".concat(placeholderFadeInKeyframes, " 300ms ease-out forwards")
93
106
  }
94
107
  });
95
108
 
@@ -5,4 +5,4 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.version = exports.name = void 0;
7
7
  var name = exports.name = "@atlaskit/editor-core";
8
- var version = exports.version = "0.0.0-development";
8
+ var version = exports.version = "215.25.0";
@@ -1,57 +1,53 @@
1
- import React from 'react';
2
1
  import { TextSelection } from '@atlaskit/editor-prosemirror/state';
3
- import { fg } from '@atlaskit/platform-feature-flags';
4
2
  export function handleEditorFocus(view) {
3
+ var _domSelection$getRang;
5
4
  if (view !== null && view !== void 0 && view.hasFocus()) {
6
5
  return;
7
6
  }
8
7
 
9
- /**
10
- * If startTransition is available (in React 18),
11
- * don't use setTimeout as startTransition will be used in ReactEditorViewNext.
12
- * setTimeout(fn, 0) will not defer the focus reliably in React 18 with
13
- * concurrent rendering.
14
- */
15
- const react16OnlySetTimeout = React !== null && React !== void 0 && React.startTransition && fg('platform_editor_react_18_autofocus_fix') ? fn => fn() : fn => window.setTimeout(fn, 0);
16
- return react16OnlySetTimeout(() => {
17
- // Due to race conditions during editor lifecycle transitions (e.g. SPA route changes during opening or closing)
18
- // where the view (and its internal docView) may have been destroyed, the timeout callback may fire on a stale view.
19
- // Bail out in that scenario to prevent operating on an unmounted view.
20
- if (view !== null && view !== void 0 && view.isDestroyed) {
21
- return;
22
- }
23
- if (view !== null && view !== void 0 && view.hasFocus()) {
24
- return;
25
- }
26
- if (!window.getSelection) {
27
- view === null || view === void 0 ? void 0 : view.focus();
28
- return;
29
- }
30
- const domSelection = window.getSelection();
31
- if (!domSelection || domSelection.rangeCount === 0) {
32
- view === null || view === void 0 ? void 0 : view.focus();
33
- return;
34
- }
35
- const range = domSelection.getRangeAt(0);
36
- // if selection is outside editor focus and exit
37
- if (view && range.startContainer.contains(view.dom)) {
38
- view.focus();
39
- return;
40
- }
8
+ // Due to race conditions during editor lifecycle transitions (e.g. SPA route changes during opening or closing)
9
+ // where the view (and its internal docView) may have been destroyed, the timeout callback may fire on a stale view.
10
+ // Bail out in that scenario to prevent operating on an unmounted view.
11
+ if (view !== null && view !== void 0 && view.isDestroyed) {
12
+ return;
13
+ }
14
+ if (view !== null && view !== void 0 && view.hasFocus()) {
15
+ return;
16
+ }
17
+ if (!window.getSelection) {
18
+ view === null || view === void 0 ? void 0 : view.focus();
19
+ return;
20
+ }
21
+ const domSelection = window.getSelection();
22
+ if (!domSelection || domSelection.rangeCount === 0) {
23
+ view === null || view === void 0 ? void 0 : view.focus();
24
+ return;
25
+ }
41
26
 
42
- // set cursor/selection and focus
43
- const anchor = view === null || view === void 0 ? void 0 : view.posAtDOM(range.startContainer, range.startOffset);
44
- const head = view === null || view === void 0 ? void 0 : view.posAtDOM(range.endContainer, range.endOffset);
45
- // if anchor or head < 0 focus and exit
46
- if (anchor && anchor < 0 || head && head < 0) {
47
- view === null || view === void 0 ? void 0 : view.focus();
48
- return;
49
- }
50
- if (view && anchor) {
51
- const selection = TextSelection.create(view.state.doc, anchor, head);
52
- const tr = view.state.tr.setSelection(selection);
53
- view.dispatch(tr);
54
- view.focus();
55
- }
56
- });
27
+ // If not mocked properly in tests, getRangeAt may not exist.
28
+ const range = (_domSelection$getRang = domSelection.getRangeAt) === null || _domSelection$getRang === void 0 ? void 0 : _domSelection$getRang.call(domSelection, 0);
29
+ if (!range) {
30
+ return;
31
+ }
32
+
33
+ // if selection is outside editor focus and exit
34
+ if (view && range !== null && range !== void 0 && range.startContainer.contains(view.dom)) {
35
+ view.focus();
36
+ return;
37
+ }
38
+
39
+ // set cursor/selection and focus
40
+ const anchor = view === null || view === void 0 ? void 0 : view.posAtDOM(range.startContainer, range.startOffset);
41
+ const head = view === null || view === void 0 ? void 0 : view.posAtDOM(range.endContainer, range.endOffset);
42
+ // if anchor or head < 0 focus and exit
43
+ if (anchor && anchor < 0 || head && head < 0) {
44
+ view === null || view === void 0 ? void 0 : view.focus();
45
+ return;
46
+ }
47
+ if (view && anchor) {
48
+ const selection = TextSelection.create(view.state.doc, anchor, head);
49
+ const tr = view.state.tr.setSelection(selection);
50
+ view.dispatch(tr);
51
+ view.focus();
52
+ }
57
53
  }
@@ -57,6 +57,7 @@ export function ReactEditorView(props) {
57
57
  onEditorDestroyed
58
58
  } = props;
59
59
  const [editorAPI, setEditorAPI] = useState(undefined);
60
+ const ssrEditorStateRef = useRef(undefined);
60
61
  const editorRef = useRef(null);
61
62
  const viewRef = useRef();
62
63
  const focusTimeoutId = useRef();
@@ -80,8 +81,8 @@ export function ReactEditorView(props) {
80
81
  const contentTransformer = useRef(undefined);
81
82
  const featureFlags = useMemo(() => createFeatureFlagsFromProps(editorPropFeatureFlags), [editorPropFeatureFlags]);
82
83
  const getEditorState = useCallback(() => {
83
- var _viewRef$current;
84
- return (_viewRef$current = viewRef.current) === null || _viewRef$current === void 0 ? void 0 : _viewRef$current.state;
84
+ var _ssrEditorStateRef$cu, _viewRef$current;
85
+ return (_ssrEditorStateRef$cu = ssrEditorStateRef.current) !== null && _ssrEditorStateRef$cu !== void 0 ? _ssrEditorStateRef$cu : (_viewRef$current = viewRef.current) === null || _viewRef$current === void 0 ? void 0 : _viewRef$current.state;
85
86
  }, []);
86
87
  const getEditorView = useCallback(() => viewRef.current, []);
87
88
  const dispatch = useMemo(() => createDispatch(eventDispatcher), [eventDispatcher]);
@@ -515,7 +516,7 @@ export function ReactEditorView(props) {
515
516
  // We don't need to focus anything in SSR.
516
517
  return;
517
518
  }
518
- if (shouldFocus && editorView !== null && editorView !== void 0 && (_editorView$props$edi = (_editorView$props = editorView.props).editable) !== null && _editorView$props$edi !== void 0 && _editorView$props$edi.call(_editorView$props, editorView.state) && fg('platform_editor_react_18_autofocus_fix')) {
519
+ if (shouldFocus && editorView !== null && editorView !== void 0 && (_editorView$props$edi = (_editorView$props = editorView.props).editable) !== null && _editorView$props$edi !== void 0 && _editorView$props$edi.call(_editorView$props, editorView.state)) {
519
520
  if (!mitigateScrollJump) {
520
521
  const liveDocWithContent = (__livePage || expValEquals('platform_editor_no_cursor_on_edit_page_init', 'isEnabled', true)) && !isEmptyDocument(editorView.state.doc);
521
522
  if (!liveDocWithContent) {
@@ -599,36 +600,10 @@ export function ReactEditorView(props) {
599
600
  eventDispatcher: eventDispatcher,
600
601
  transformer: contentTransformer.current
601
602
  });
602
- if (fg('platform_editor_react_18_autofocus_fix')) {
603
- var _startTransition;
604
- /**
605
- * Defer using startTransition when it is available (in React 18) to fix
606
- * autofocus bug where React 18's concurrent rendering mode interferes with
607
- * setTimeout used in handleEditorFocus, causing autofocus to break.
608
- */
609
- const react18OnlyStartTransition = (_startTransition = React === null || React === void 0 ? void 0 : React.startTransition) !== null && _startTransition !== void 0 ? _startTransition : fn => fn();
610
- react18OnlyStartTransition(() => {
611
- // Force React to re-render so consumers get a reference to the editor view
612
- setEditorView(view);
613
- });
614
- } else {
615
- if (shouldFocus && view.props.editable && view.props.editable(view.state)) {
616
- if (!mitigateScrollJump) {
617
- const isLivePageWithContent = (__livePage || expValEquals('platform_editor_no_cursor_on_edit_page_init', 'isEnabled', true)) && !isEmptyDocument(view.state.doc);
618
- if (!isLivePageWithContent && shouldFocus && view.props.editable && view.props.editable(view.state)) {
619
- focusTimeoutId.current = handleEditorFocus(view);
620
- }
621
- if (expValEquals('platform_editor_no_cursor_on_edit_page_init', 'isEnabled', true) && fg('cc_editor_focus_before_editor_on_load')) {
622
- if (shouldFocus && view.props.editable && view.props.editable(view.state) && !isEmptyDocument(view.state.doc)) {
623
- focusEditorElement(editorId.current);
624
- }
625
- }
626
- }
627
- }
628
-
603
+ React.startTransition(() => {
629
604
  // Force React to re-render so consumers get a reference to the editor view
630
605
  setEditorView(view);
631
- }
606
+ });
632
607
  } else if (viewRef.current && !node) {
633
608
  // When the appearance is changed, React will call handleEditorViewRef with node === null
634
609
  // to destroy the old EditorView, before calling this method again with node === div to
@@ -652,7 +627,7 @@ export function ReactEditorView(props) {
652
627
  nodeVisibilityManager(viewRef.current.dom).disconnect();
653
628
  viewRef.current = undefined;
654
629
  }
655
- }, [createEditorView, onEditorCreated, eventDispatcher, shouldFocus, __livePage, onEditorDestroyed, handleAnalyticsEvent, mitigateScrollJump]);
630
+ }, [createEditorView, onEditorCreated, eventDispatcher, onEditorDestroyed, handleAnalyticsEvent, mitigateScrollJump]);
656
631
  const createEditor = useCallback((assistiveLabel, assistiveDescribedBy) => {
657
632
  return /*#__PURE__*/React.createElement(React.Fragment, null, fg('cc_editor_focus_before_editor_on_load') && /*#__PURE__*/React.createElement("div", {
658
633
  tabIndex: -1,
@@ -732,17 +707,17 @@ export function ReactEditorView(props) {
732
707
  doc: defaultValue
733
708
  });
734
709
  }, [defaultValue, parseDoc, props.editorProps.sanitizePrivateContent, props.providerFactory]);
735
- const {
736
- assistiveLabel,
737
- assistiveDescribedBy
738
- } = props.editorProps;
710
+
739
711
  // We need to check `allowBlockType` in props, because it is now exist in EditorNextProps type.
740
712
  const {
741
713
  allowBlockType
742
714
  } = 'allowBlockType' in props.editorProps ? props.editorProps : {
743
715
  allowBlockType: undefined
744
716
  };
745
- const ssrEditor = useMemo(() => {
717
+
718
+ // In separate memo, because some props like `props.intl` that need only for rendering
719
+ // changes many times, but we don't want to process plugins and ADF document for each unnecessary changes.
720
+ const ssrDeps = useMemo(() => {
746
721
  if (!isSSR() || !expValEquals('platform_editor_ssr_renderer', 'isEnabled', true)) {
747
722
  return null;
748
723
  }
@@ -754,11 +729,25 @@ export function ReactEditorView(props) {
754
729
  }, pluginInjectionAPI.current);
755
730
  const schema = createSchema(processPluginsList(plugins));
756
731
  const doc = buildDoc(schema);
732
+ return {
733
+ plugins,
734
+ schema,
735
+ doc
736
+ };
737
+ }, [allowBlockType, buildDoc, props.preset]);
738
+ const {
739
+ assistiveLabel,
740
+ assistiveDescribedBy
741
+ } = props.editorProps;
742
+ const ssrEditor = useMemo(() => {
743
+ if (!ssrDeps) {
744
+ return null;
745
+ }
757
746
  return /*#__PURE__*/React.createElement(EditorSSRRenderer, {
758
747
  intl: props.intl,
759
- doc: doc,
760
- schema: schema,
761
- plugins: plugins,
748
+ doc: ssrDeps.doc,
749
+ schema: ssrDeps.schema,
750
+ plugins: ssrDeps.plugins,
762
751
  portalProviderAPI: props.portalProviderAPI
763
752
  // IMPORTANT: Keep next props in sync with div that renders a real ProseMirror editor.
764
753
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
@@ -768,9 +757,12 @@ export function ReactEditorView(props) {
768
757
  "aria-label": assistiveLabel || props.intl.formatMessage(editorMessages.editorAssistiveLabel),
769
758
  id: EDIT_AREA_ID,
770
759
  "aria-describedby": assistiveDescribedBy,
771
- "data-editor-id": editorId.current
760
+ "data-editor-id": editorId.current,
761
+ onEditorStateChanged: state => {
762
+ ssrEditorStateRef.current = state;
763
+ }
772
764
  });
773
- }, [props.preset, allowBlockType, assistiveLabel, assistiveDescribedBy, props.intl, props.portalProviderAPI, buildDoc]);
765
+ }, [ssrDeps, props.intl, props.portalProviderAPI, assistiveLabel, assistiveDescribedBy]);
774
766
  const editor = useMemo(() => {
775
767
  // SSR editor will be available only in SSR environment,
776
768
  // in a browser `ssrEditor` will be `null`, and we will render a normal one ProseMirror.
@@ -14,7 +14,7 @@ import { fg } from '@atlaskit/platform-feature-flags';
14
14
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
15
15
  import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
16
16
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
17
- import { expValNoExposure } from '@atlaskit/tmp-editor-statsig/expVal';
17
+ import { expVal, expValNoExposure } from '@atlaskit/tmp-editor-statsig/expVal';
18
18
  import { useThemeObserver } from '@atlaskit/tokens';
19
19
  import { getBaseFontSize } from '../../composable-editor/utils/getBaseFontSize';
20
20
  import { aiPanelBaseFirefoxStyles, aiPanelBaseStyles, aiPanelDarkFirefoxStyles, aiPanelDarkStyles } from './styles/aiPanel';
@@ -22,7 +22,7 @@ import { annotationStyles } from './styles/annotationStyles';
22
22
  import { backgroundColorStyles, textHighlightPaddingStyles } from './styles/backgroundColorStyles';
23
23
  import { baseStyles, baseStylesMaxContainerWidthFixes, editorLargeGutterPuddingBaseStyles, editorLargeGutterPuddingBaseStylesEditorControls, editorLargeGutterPuddingReducedBaseStyles } from './styles/baseStyles';
24
24
  import { blockMarksStyles } from './styles/blockMarksStyles';
25
- import { blockquoteSelectedNodeStyles, blocktypeStyles, blocktypeStyles_fg_platform_editor_nested_dnd_styles_changes, blocktypeStyles_fg_platform_editor_typography_ugc, blocktypeStyles_without_fg_platform_editor_typography_ugc } from './styles/blockTypeStyles';
25
+ import { blockquoteSelectedNodeStyles, blocktypeStyles, blockquoteZeroPadding, blocktypeStyles_fg_platform_editor_nested_dnd_styles_changes, blocktypeStyles_fg_platform_editor_typography_ugc, blocktypeStyles_without_fg_platform_editor_typography_ugc } from './styles/blockTypeStyles';
26
26
  import { codeBidiWarningStyles } from './styles/codeBidiWarningStyles';
27
27
  import { codeBgColorStyles, codeBlockStyles, codeBlockStylesWithEmUnits, firstCodeBlockWithNoMargin, firstCodeBlockWithNoMarginOld } from './styles/codeBlockStyles';
28
28
  import { codeMarkStyles } from './styles/codeMarkStyles';
@@ -196,7 +196,9 @@ const EditorContentContainer = /*#__PURE__*/React.forwardRef((props, ref) => {
196
196
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values
197
197
  blocktypeStyles, expValEquals('platform_editor_block_menu', 'isEnabled', true) &&
198
198
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values
199
- blockquoteSelectedNodeStyles,
199
+ blockquoteSelectedNodeStyles, expVal('platform_editor_blockquote_zero_padding', 'isEnabled', false) ?
200
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values
201
+ blockquoteZeroPadding : null,
200
202
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values
201
203
  fg('platform_editor_typography_ugc') ?
202
204
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values
@@ -1,5 +1,18 @@
1
1
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled
2
2
  import { css } from '@emotion/react';
3
+ // This style is needed to avoid Confluence's batch.css overrides that expand blockquote with extra padding after SSR.
4
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-exported-styles
5
+ export const blockquoteZeroPadding = css({
6
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
7
+ '.ProseMirror': {
8
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
9
+ '& blockquote': {
10
+ paddingTop: 0,
11
+ paddingBottom: 0
12
+ }
13
+ }
14
+ });
15
+
3
16
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-exported-styles
4
17
  export const blocktypeStyles = css({
5
18
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
@@ -1,5 +1,14 @@
1
1
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled
2
- import { css } from '@emotion/react';
2
+ import { css, keyframes } from '@emotion/react';
3
+ const placeholderFadeInKeyframes = keyframes({
4
+ from: {
5
+ opacity: 0
6
+ },
7
+ to: {
8
+ opacity: 1
9
+ }
10
+ });
11
+
3
12
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-exported-styles
4
13
  export const placeholderTextStyles = css({
5
14
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
@@ -83,6 +92,10 @@ export const placeholderStyles = css({
83
92
  userSelect: 'none',
84
93
  position: 'absolute'
85
94
  }
95
+ },
96
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
97
+ '.ProseMirror .placeholder-decoration-fade-in': {
98
+ animation: `${placeholderFadeInKeyframes} 300ms ease-out forwards`
86
99
  }
87
100
  });
88
101
 
@@ -1,2 +1,2 @@
1
1
  export const name = "@atlaskit/editor-core";
2
- export const version = "0.0.0-development";
2
+ export const version = "215.25.0";
@@ -1,61 +1,53 @@
1
- import React from 'react';
2
1
  import { TextSelection } from '@atlaskit/editor-prosemirror/state';
3
- import { fg } from '@atlaskit/platform-feature-flags';
4
2
  export function handleEditorFocus(view) {
3
+ var _domSelection$getRang;
5
4
  if (view !== null && view !== void 0 && view.hasFocus()) {
6
5
  return;
7
6
  }
8
7
 
9
- /**
10
- * If startTransition is available (in React 18),
11
- * don't use setTimeout as startTransition will be used in ReactEditorViewNext.
12
- * setTimeout(fn, 0) will not defer the focus reliably in React 18 with
13
- * concurrent rendering.
14
- */
15
- var react16OnlySetTimeout = React !== null && React !== void 0 && React.startTransition && fg('platform_editor_react_18_autofocus_fix') ? function (fn) {
16
- return fn();
17
- } : function (fn) {
18
- return window.setTimeout(fn, 0);
19
- };
20
- return react16OnlySetTimeout(function () {
21
- // Due to race conditions during editor lifecycle transitions (e.g. SPA route changes during opening or closing)
22
- // where the view (and its internal docView) may have been destroyed, the timeout callback may fire on a stale view.
23
- // Bail out in that scenario to prevent operating on an unmounted view.
24
- if (view !== null && view !== void 0 && view.isDestroyed) {
25
- return;
26
- }
27
- if (view !== null && view !== void 0 && view.hasFocus()) {
28
- return;
29
- }
30
- if (!window.getSelection) {
31
- view === null || view === void 0 || view.focus();
32
- return;
33
- }
34
- var domSelection = window.getSelection();
35
- if (!domSelection || domSelection.rangeCount === 0) {
36
- view === null || view === void 0 || view.focus();
37
- return;
38
- }
39
- var range = domSelection.getRangeAt(0);
40
- // if selection is outside editor focus and exit
41
- if (view && range.startContainer.contains(view.dom)) {
42
- view.focus();
43
- return;
44
- }
8
+ // Due to race conditions during editor lifecycle transitions (e.g. SPA route changes during opening or closing)
9
+ // where the view (and its internal docView) may have been destroyed, the timeout callback may fire on a stale view.
10
+ // Bail out in that scenario to prevent operating on an unmounted view.
11
+ if (view !== null && view !== void 0 && view.isDestroyed) {
12
+ return;
13
+ }
14
+ if (view !== null && view !== void 0 && view.hasFocus()) {
15
+ return;
16
+ }
17
+ if (!window.getSelection) {
18
+ view === null || view === void 0 || view.focus();
19
+ return;
20
+ }
21
+ var domSelection = window.getSelection();
22
+ if (!domSelection || domSelection.rangeCount === 0) {
23
+ view === null || view === void 0 || view.focus();
24
+ return;
25
+ }
45
26
 
46
- // set cursor/selection and focus
47
- var anchor = view === null || view === void 0 ? void 0 : view.posAtDOM(range.startContainer, range.startOffset);
48
- var head = view === null || view === void 0 ? void 0 : view.posAtDOM(range.endContainer, range.endOffset);
49
- // if anchor or head < 0 focus and exit
50
- if (anchor && anchor < 0 || head && head < 0) {
51
- view === null || view === void 0 || view.focus();
52
- return;
53
- }
54
- if (view && anchor) {
55
- var selection = TextSelection.create(view.state.doc, anchor, head);
56
- var tr = view.state.tr.setSelection(selection);
57
- view.dispatch(tr);
58
- view.focus();
59
- }
60
- });
27
+ // If not mocked properly in tests, getRangeAt may not exist.
28
+ var range = (_domSelection$getRang = domSelection.getRangeAt) === null || _domSelection$getRang === void 0 ? void 0 : _domSelection$getRang.call(domSelection, 0);
29
+ if (!range) {
30
+ return;
31
+ }
32
+
33
+ // if selection is outside editor focus and exit
34
+ if (view && range !== null && range !== void 0 && range.startContainer.contains(view.dom)) {
35
+ view.focus();
36
+ return;
37
+ }
38
+
39
+ // set cursor/selection and focus
40
+ var anchor = view === null || view === void 0 ? void 0 : view.posAtDOM(range.startContainer, range.startOffset);
41
+ var head = view === null || view === void 0 ? void 0 : view.posAtDOM(range.endContainer, range.endOffset);
42
+ // if anchor or head < 0 focus and exit
43
+ if (anchor && anchor < 0 || head && head < 0) {
44
+ view === null || view === void 0 || view.focus();
45
+ return;
46
+ }
47
+ if (view && anchor) {
48
+ var selection = TextSelection.create(view.state.doc, anchor, head);
49
+ var tr = view.state.tr.setSelection(selection);
50
+ view.dispatch(tr);
51
+ view.focus();
52
+ }
61
53
  }
@@ -65,6 +65,7 @@ export function ReactEditorView(props) {
65
65
  _useState2 = _slicedToArray(_useState, 2),
66
66
  editorAPI = _useState2[0],
67
67
  setEditorAPI = _useState2[1];
68
+ var ssrEditorStateRef = useRef(undefined);
68
69
  var editorRef = useRef(null);
69
70
  var viewRef = useRef();
70
71
  var focusTimeoutId = useRef();
@@ -92,8 +93,8 @@ export function ReactEditorView(props) {
92
93
  return createFeatureFlagsFromProps(editorPropFeatureFlags);
93
94
  }, [editorPropFeatureFlags]);
94
95
  var getEditorState = useCallback(function () {
95
- var _viewRef$current;
96
- return (_viewRef$current = viewRef.current) === null || _viewRef$current === void 0 ? void 0 : _viewRef$current.state;
96
+ var _ssrEditorStateRef$cu, _viewRef$current;
97
+ return (_ssrEditorStateRef$cu = ssrEditorStateRef.current) !== null && _ssrEditorStateRef$cu !== void 0 ? _ssrEditorStateRef$cu : (_viewRef$current = viewRef.current) === null || _viewRef$current === void 0 ? void 0 : _viewRef$current.state;
97
98
  }, []);
98
99
  var getEditorView = useCallback(function () {
99
100
  return viewRef.current;
@@ -537,7 +538,7 @@ export function ReactEditorView(props) {
537
538
  // We don't need to focus anything in SSR.
538
539
  return;
539
540
  }
540
- if (shouldFocus && editorView !== null && editorView !== void 0 && (_editorView$props$edi = (_editorView$props = editorView.props).editable) !== null && _editorView$props$edi !== void 0 && _editorView$props$edi.call(_editorView$props, editorView.state) && fg('platform_editor_react_18_autofocus_fix')) {
541
+ if (shouldFocus && editorView !== null && editorView !== void 0 && (_editorView$props$edi = (_editorView$props = editorView.props).editable) !== null && _editorView$props$edi !== void 0 && _editorView$props$edi.call(_editorView$props, editorView.state)) {
541
542
  if (!mitigateScrollJump) {
542
543
  var liveDocWithContent = (__livePage || expValEquals('platform_editor_no_cursor_on_edit_page_init', 'isEnabled', true)) && !isEmptyDocument(editorView.state.doc);
543
544
  if (!liveDocWithContent) {
@@ -639,38 +640,10 @@ export function ReactEditorView(props) {
639
640
  eventDispatcher: eventDispatcher,
640
641
  transformer: contentTransformer.current
641
642
  });
642
- if (fg('platform_editor_react_18_autofocus_fix')) {
643
- var _startTransition;
644
- /**
645
- * Defer using startTransition when it is available (in React 18) to fix
646
- * autofocus bug where React 18's concurrent rendering mode interferes with
647
- * setTimeout used in handleEditorFocus, causing autofocus to break.
648
- */
649
- var react18OnlyStartTransition = (_startTransition = React === null || React === void 0 ? void 0 : React.startTransition) !== null && _startTransition !== void 0 ? _startTransition : function (fn) {
650
- return fn();
651
- };
652
- react18OnlyStartTransition(function () {
653
- // Force React to re-render so consumers get a reference to the editor view
654
- setEditorView(view);
655
- });
656
- } else {
657
- if (shouldFocus && view.props.editable && view.props.editable(view.state)) {
658
- if (!mitigateScrollJump) {
659
- var isLivePageWithContent = (__livePage || expValEquals('platform_editor_no_cursor_on_edit_page_init', 'isEnabled', true)) && !isEmptyDocument(view.state.doc);
660
- if (!isLivePageWithContent && shouldFocus && view.props.editable && view.props.editable(view.state)) {
661
- focusTimeoutId.current = handleEditorFocus(view);
662
- }
663
- if (expValEquals('platform_editor_no_cursor_on_edit_page_init', 'isEnabled', true) && fg('cc_editor_focus_before_editor_on_load')) {
664
- if (shouldFocus && view.props.editable && view.props.editable(view.state) && !isEmptyDocument(view.state.doc)) {
665
- focusEditorElement(editorId.current);
666
- }
667
- }
668
- }
669
- }
670
-
643
+ React.startTransition(function () {
671
644
  // Force React to re-render so consumers get a reference to the editor view
672
645
  setEditorView(view);
673
- }
646
+ });
674
647
  } else if (viewRef.current && !node) {
675
648
  // When the appearance is changed, React will call handleEditorViewRef with node === null
676
649
  // to destroy the old EditorView, before calling this method again with node === div to
@@ -694,7 +667,7 @@ export function ReactEditorView(props) {
694
667
  nodeVisibilityManager(viewRef.current.dom).disconnect();
695
668
  viewRef.current = undefined;
696
669
  }
697
- }, [createEditorView, onEditorCreated, eventDispatcher, shouldFocus, __livePage, onEditorDestroyed, handleAnalyticsEvent, mitigateScrollJump]);
670
+ }, [createEditorView, onEditorCreated, eventDispatcher, onEditorDestroyed, handleAnalyticsEvent, mitigateScrollJump]);
698
671
  var createEditor = useCallback(function (assistiveLabel, assistiveDescribedBy) {
699
672
  return /*#__PURE__*/React.createElement(React.Fragment, null, fg('cc_editor_focus_before_editor_on_load') && /*#__PURE__*/React.createElement("div", {
700
673
  tabIndex: -1,
@@ -776,15 +749,16 @@ export function ReactEditorView(props) {
776
749
  doc: defaultValue
777
750
  });
778
751
  }, [defaultValue, parseDoc, props.editorProps.sanitizePrivateContent, props.providerFactory]);
779
- var _props$editorProps3 = props.editorProps,
780
- assistiveLabel = _props$editorProps3.assistiveLabel,
781
- assistiveDescribedBy = _props$editorProps3.assistiveDescribedBy;
752
+
782
753
  // We need to check `allowBlockType` in props, because it is now exist in EditorNextProps type.
783
754
  var _ref5 = 'allowBlockType' in props.editorProps ? props.editorProps : {
784
755
  allowBlockType: undefined
785
756
  },
786
757
  allowBlockType = _ref5.allowBlockType;
787
- var ssrEditor = useMemo(function () {
758
+
759
+ // In separate memo, because some props like `props.intl` that need only for rendering
760
+ // changes many times, but we don't want to process plugins and ADF document for each unnecessary changes.
761
+ var ssrDeps = useMemo(function () {
788
762
  if (!isSSR() || !expValEquals('platform_editor_ssr_renderer', 'isEnabled', true)) {
789
763
  return null;
790
764
  }
@@ -796,11 +770,24 @@ export function ReactEditorView(props) {
796
770
  }, pluginInjectionAPI.current);
797
771
  var schema = createSchema(processPluginsList(plugins));
798
772
  var doc = buildDoc(schema);
773
+ return {
774
+ plugins: plugins,
775
+ schema: schema,
776
+ doc: doc
777
+ };
778
+ }, [allowBlockType, buildDoc, props.preset]);
779
+ var _props$editorProps3 = props.editorProps,
780
+ assistiveLabel = _props$editorProps3.assistiveLabel,
781
+ assistiveDescribedBy = _props$editorProps3.assistiveDescribedBy;
782
+ var ssrEditor = useMemo(function () {
783
+ if (!ssrDeps) {
784
+ return null;
785
+ }
799
786
  return /*#__PURE__*/React.createElement(EditorSSRRenderer, {
800
787
  intl: props.intl,
801
- doc: doc,
802
- schema: schema,
803
- plugins: plugins,
788
+ doc: ssrDeps.doc,
789
+ schema: ssrDeps.schema,
790
+ plugins: ssrDeps.plugins,
804
791
  portalProviderAPI: props.portalProviderAPI
805
792
  // IMPORTANT: Keep next props in sync with div that renders a real ProseMirror editor.
806
793
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
@@ -810,9 +797,12 @@ export function ReactEditorView(props) {
810
797
  "aria-label": assistiveLabel || props.intl.formatMessage(editorMessages.editorAssistiveLabel),
811
798
  id: EDIT_AREA_ID,
812
799
  "aria-describedby": assistiveDescribedBy,
813
- "data-editor-id": editorId.current
800
+ "data-editor-id": editorId.current,
801
+ onEditorStateChanged: function onEditorStateChanged(state) {
802
+ ssrEditorStateRef.current = state;
803
+ }
814
804
  });
815
- }, [props.preset, allowBlockType, assistiveLabel, assistiveDescribedBy, props.intl, props.portalProviderAPI, buildDoc]);
805
+ }, [ssrDeps, props.intl, props.portalProviderAPI, assistiveLabel, assistiveDescribedBy]);
816
806
  var editor = useMemo(function () {
817
807
  // SSR editor will be available only in SSR environment,
818
808
  // in a browser `ssrEditor` will be `null`, and we will render a normal one ProseMirror.
@@ -15,7 +15,7 @@ import { fg } from '@atlaskit/platform-feature-flags';
15
15
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
16
16
  import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
17
17
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
18
- import { expValNoExposure } from '@atlaskit/tmp-editor-statsig/expVal';
18
+ import { expVal, expValNoExposure } from '@atlaskit/tmp-editor-statsig/expVal';
19
19
  import { useThemeObserver } from '@atlaskit/tokens';
20
20
  import { getBaseFontSize } from '../../composable-editor/utils/getBaseFontSize';
21
21
  import { aiPanelBaseFirefoxStyles, aiPanelBaseStyles, aiPanelDarkFirefoxStyles, aiPanelDarkStyles } from './styles/aiPanel';
@@ -23,7 +23,7 @@ import { annotationStyles } from './styles/annotationStyles';
23
23
  import { backgroundColorStyles, textHighlightPaddingStyles } from './styles/backgroundColorStyles';
24
24
  import { baseStyles, baseStylesMaxContainerWidthFixes, editorLargeGutterPuddingBaseStyles, editorLargeGutterPuddingBaseStylesEditorControls, editorLargeGutterPuddingReducedBaseStyles } from './styles/baseStyles';
25
25
  import { blockMarksStyles } from './styles/blockMarksStyles';
26
- import { blockquoteSelectedNodeStyles, blocktypeStyles, blocktypeStyles_fg_platform_editor_nested_dnd_styles_changes, blocktypeStyles_fg_platform_editor_typography_ugc, blocktypeStyles_without_fg_platform_editor_typography_ugc } from './styles/blockTypeStyles';
26
+ import { blockquoteSelectedNodeStyles, blocktypeStyles, blockquoteZeroPadding, blocktypeStyles_fg_platform_editor_nested_dnd_styles_changes, blocktypeStyles_fg_platform_editor_typography_ugc, blocktypeStyles_without_fg_platform_editor_typography_ugc } from './styles/blockTypeStyles';
27
27
  import { codeBidiWarningStyles } from './styles/codeBidiWarningStyles';
28
28
  import { codeBgColorStyles, codeBlockStyles, codeBlockStylesWithEmUnits, firstCodeBlockWithNoMargin, firstCodeBlockWithNoMarginOld } from './styles/codeBlockStyles';
29
29
  import { codeMarkStyles } from './styles/codeMarkStyles';
@@ -192,7 +192,9 @@ var EditorContentContainer = /*#__PURE__*/React.forwardRef(function (props, ref)
192
192
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values
193
193
  blocktypeStyles, expValEquals('platform_editor_block_menu', 'isEnabled', true) &&
194
194
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values
195
- blockquoteSelectedNodeStyles,
195
+ blockquoteSelectedNodeStyles, expVal('platform_editor_blockquote_zero_padding', 'isEnabled', false) ?
196
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values
197
+ blockquoteZeroPadding : null,
196
198
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values
197
199
  fg('platform_editor_typography_ugc') ?
198
200
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values
@@ -1,5 +1,18 @@
1
1
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled
2
2
  import { css } from '@emotion/react';
3
+ // This style is needed to avoid Confluence's batch.css overrides that expand blockquote with extra padding after SSR.
4
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-exported-styles
5
+ export var blockquoteZeroPadding = css({
6
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
7
+ '.ProseMirror': {
8
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
9
+ '& blockquote': {
10
+ paddingTop: 0,
11
+ paddingBottom: 0
12
+ }
13
+ }
14
+ });
15
+
3
16
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-exported-styles
4
17
  export var blocktypeStyles = css({
5
18
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
@@ -1,5 +1,14 @@
1
1
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled
2
- import { css } from '@emotion/react';
2
+ import { css, keyframes } from '@emotion/react';
3
+ var placeholderFadeInKeyframes = keyframes({
4
+ from: {
5
+ opacity: 0
6
+ },
7
+ to: {
8
+ opacity: 1
9
+ }
10
+ });
11
+
3
12
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-exported-styles
4
13
  export var placeholderTextStyles = css({
5
14
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
@@ -83,6 +92,10 @@ export var placeholderStyles = css({
83
92
  userSelect: 'none',
84
93
  position: 'absolute'
85
94
  }
95
+ },
96
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
97
+ '.ProseMirror .placeholder-decoration-fade-in': {
98
+ animation: "".concat(placeholderFadeInKeyframes, " 300ms ease-out forwards")
86
99
  }
87
100
  });
88
101
 
@@ -1,2 +1,2 @@
1
1
  export var name = "@atlaskit/editor-core";
2
- export var version = "0.0.0-development";
2
+ export var version = "215.25.0";
@@ -399,6 +399,7 @@ export declare function createUniversalPreset({ props, prevProps, initialPluginC
399
399
  }, import("@atlaskit/editor-plugins/editor-viewmode").EditorViewModePluginOptions | undefined>>, import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"blockMenu", {
400
400
  actions: {
401
401
  getBlockMenuComponents: () => Array<import("@atlaskit/editor-plugins/block-menu").RegisterBlockMenuComponent>;
402
+ isTransformOptionDisabled: (optionNodeTypeName: string, optionNodeTypeAttrs?: Record<string, unknown>) => boolean;
402
403
  registerBlockMenuComponents: (blockMenuComponents: Array<import("@atlaskit/editor-plugins/block-menu").RegisterBlockMenuComponent>) => void;
403
404
  };
404
405
  commands: {
@@ -472,6 +472,7 @@ export default function createUniversalPresetInternal({ appearance, props, featu
472
472
  }, import("@atlaskit/editor-plugins/editor-viewmode").EditorViewModePluginOptions | undefined>>, import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"blockMenu", {
473
473
  actions: {
474
474
  getBlockMenuComponents: () => Array<import("@atlaskit/editor-plugins/block-menu").RegisterBlockMenuComponent>;
475
+ isTransformOptionDisabled: (optionNodeTypeName: string, optionNodeTypeAttrs?: Record<string, unknown>) => boolean;
475
476
  registerBlockMenuComponents: (blockMenuComponents: Array<import("@atlaskit/editor-plugins/block-menu").RegisterBlockMenuComponent>) => void;
476
477
  };
477
478
  commands: {
@@ -399,6 +399,7 @@ export default function useUniversalPreset({ props, initialPluginConfiguration }
399
399
  }, import("@atlaskit/editor-plugins/editor-viewmode").EditorViewModePluginOptions | undefined>>, import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"blockMenu", {
400
400
  actions: {
401
401
  getBlockMenuComponents: () => Array<import("@atlaskit/editor-plugins/block-menu").RegisterBlockMenuComponent>;
402
+ isTransformOptionDisabled: (optionNodeTypeName: string, optionNodeTypeAttrs?: Record<string, unknown>) => boolean;
402
403
  registerBlockMenuComponents: (blockMenuComponents: Array<import("@atlaskit/editor-plugins/block-menu").RegisterBlockMenuComponent>) => void;
403
404
  };
404
405
  commands: {
@@ -1,4 +1,5 @@
1
1
  import { type SerializedStyles } from '@emotion/react';
2
+ export declare const blockquoteZeroPadding: SerializedStyles;
2
3
  export declare const blocktypeStyles: SerializedStyles;
3
4
  export declare const blockquoteSelectedNodeStyles: SerializedStyles;
4
5
  export declare const blocktypeStyles_fg_platform_editor_typography_ugc: SerializedStyles;
@@ -564,6 +564,7 @@ export declare function createUniversalPreset({ props, prevProps, initialPluginC
564
564
  import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"blockMenu", {
565
565
  actions: {
566
566
  getBlockMenuComponents: () => Array<import("@atlaskit/editor-plugins/block-menu").RegisterBlockMenuComponent>;
567
+ isTransformOptionDisabled: (optionNodeTypeName: string, optionNodeTypeAttrs?: Record<string, unknown>) => boolean;
567
568
  registerBlockMenuComponents: (blockMenuComponents: Array<import("@atlaskit/editor-plugins/block-menu").RegisterBlockMenuComponent>) => void;
568
569
  };
569
570
  commands: {
@@ -637,6 +637,7 @@ export default function createUniversalPresetInternal({ appearance, props, featu
637
637
  import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"blockMenu", {
638
638
  actions: {
639
639
  getBlockMenuComponents: () => Array<import("@atlaskit/editor-plugins/block-menu").RegisterBlockMenuComponent>;
640
+ isTransformOptionDisabled: (optionNodeTypeName: string, optionNodeTypeAttrs?: Record<string, unknown>) => boolean;
640
641
  registerBlockMenuComponents: (blockMenuComponents: Array<import("@atlaskit/editor-plugins/block-menu").RegisterBlockMenuComponent>) => void;
641
642
  };
642
643
  commands: {
@@ -564,6 +564,7 @@ export default function useUniversalPreset({ props, initialPluginConfiguration }
564
564
  import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"blockMenu", {
565
565
  actions: {
566
566
  getBlockMenuComponents: () => Array<import("@atlaskit/editor-plugins/block-menu").RegisterBlockMenuComponent>;
567
+ isTransformOptionDisabled: (optionNodeTypeName: string, optionNodeTypeAttrs?: Record<string, unknown>) => boolean;
567
568
  registerBlockMenuComponents: (blockMenuComponents: Array<import("@atlaskit/editor-plugins/block-menu").RegisterBlockMenuComponent>) => void;
568
569
  };
569
570
  commands: {
@@ -1,4 +1,5 @@
1
1
  import { type SerializedStyles } from '@emotion/react';
2
+ export declare const blockquoteZeroPadding: SerializedStyles;
2
3
  export declare const blocktypeStyles: SerializedStyles;
3
4
  export declare const blockquoteSelectedNodeStyles: SerializedStyles;
4
5
  export declare const blocktypeStyles_fg_platform_editor_typography_ugc: SerializedStyles;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-core",
3
- "version": "215.24.1",
3
+ "version": "215.26.0",
4
4
  "description": "A package contains Atlassian editor core functionality",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -54,7 +54,7 @@
54
54
  "@atlaskit/editor-plugins": "^11.1.0",
55
55
  "@atlaskit/editor-prosemirror": "^7.2.0",
56
56
  "@atlaskit/editor-shared-styles": "^3.10.0",
57
- "@atlaskit/editor-ssr-renderer": "^1.5.0",
57
+ "@atlaskit/editor-ssr-renderer": "^1.6.0",
58
58
  "@atlaskit/editor-toolbar": "^0.18.0",
59
59
  "@atlaskit/editor-toolbar-model": "^0.2.0",
60
60
  "@atlaskit/emoji": "^69.9.0",
@@ -66,7 +66,7 @@
66
66
  "@atlaskit/platform-feature-flags-react": "^0.4.0",
67
67
  "@atlaskit/react-ufo": "^4.16.0",
68
68
  "@atlaskit/task-decision": "^19.2.0",
69
- "@atlaskit/tmp-editor-statsig": "^16.0.0",
69
+ "@atlaskit/tmp-editor-statsig": "^16.2.0",
70
70
  "@atlaskit/tokens": "^9.0.0",
71
71
  "@atlaskit/tooltip": "^20.11.0",
72
72
  "@atlaskit/width-detector": "^5.0.0",
@@ -83,7 +83,7 @@
83
83
  "uuid": "^3.1.0"
84
84
  },
85
85
  "peerDependencies": {
86
- "@atlaskit/editor-common": "^110.47.0",
86
+ "@atlaskit/editor-common": "^110.49.0",
87
87
  "@atlaskit/link-provider": "^4.0.0",
88
88
  "@atlaskit/media-core": "^37.0.0",
89
89
  "react": "^18.2.0",