@atlaskit/editor-core
Version:
A package contains Atlassian editor core functionality
239 lines (236 loc) • 14.8 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.FullPageEditor = void 0;
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _react = _interopRequireWildcard(require("react"));
var _react2 = require("@emotion/react");
var _browser = require("@atlaskit/editor-common/browser");
var _hooks = require("@atlaskit/editor-common/hooks");
var _ssrMeasures = require("@atlaskit/editor-common/performance/ssr-measures");
var _ui = require("@atlaskit/editor-common/ui");
var _useSharedPluginStateSelector = require("@atlaskit/editor-common/use-shared-plugin-state-selector");
var _editorSharedStyles = require("@atlaskit/editor-shared-styles");
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
var _getPrimaryToolbarComponents = require("../../Toolbar/getPrimaryToolbarComponents");
var _FullPageContentArea = require("./FullPageContentArea");
var _FullPageToolbar = require("./FullPageToolbar");
var _FullPageToolbarNext = require("./FullPageToolbarNext");
var _StyledComponents = require("./StyledComponents");
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
/**
* @jsxRuntime classic
* @jsx jsx
*/
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled, @typescript-eslint/consistent-type-imports -- Ignored via go/DSP-18766; jsx required at runtime for @jsxRuntime classic
var SSR_TRACE_SEGMENT_NAME = 'reactEditorView/fullPageAppearance';
var useShowKeyline = function useShowKeyline(contentAreaRef) {
var _useState = (0, _react.useState)(false),
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
showKeyline = _useState2[0],
setShowKeyline = _useState2[1];
(0, _react.useEffect)(function () {
var _contentAreaRef$curre;
if (!((_contentAreaRef$curre = contentAreaRef.current) !== null && _contentAreaRef$curre !== void 0 && _contentAreaRef$curre.contentArea)) {
return;
}
var browser = (0, _browser.getBrowserInfo)();
var intersection = new IntersectionObserver(function (_ref) {
var _ref2 = (0, _slicedToArray2.default)(_ref, 1),
entry = _ref2[0];
setShowKeyline(!entry.isIntersecting && entry.boundingClientRect.top < entry.intersectionRect.top);
}, {
root: undefined,
// Safari seems to miss events (on fast scroll) sometimes due
// to differences in IntersectionObserver behaviour between browsers.
// By lowering the threshold a little it gives Safari more
// time to catch these events.
threshold: browser.safari ? 0.98 : 1
});
intersection.observe(contentAreaRef.current.contentArea);
return function () {
intersection.disconnect();
};
}, [contentAreaRef]);
return showKeyline;
};
var hasCustomComponents = function hasCustomComponents(components) {
if (!components) {
return false;
}
if ('before' in components) {
return Array.isArray(components.before) && components.before.length > 0 || !!components.before || Array.isArray(components.after) && components.after.length > 0 || !!components.after;
}
return true;
};
var FullPageEditor = exports.FullPageEditor = function FullPageEditor(props) {
var _scrollContentContain, _scrollContentContain2, _scrollContentContain3, _wrapperElementRef$cu;
// Should be always the first statement in the component
var firstRenderStartTimestampRef = (0, _react.useRef)(performance.now());
var wrapperElementRef = (0, _react.useMemo)(function () {
return props.innerRef;
}, [props.innerRef]);
var scrollContentContainerRef = (0, _react.useRef)(null);
var showKeyline = useShowKeyline(scrollContentContainerRef);
var editorAPI = props.editorAPI;
var state = (0, _hooks.useSharedPluginStateWithSelector)(editorAPI, ['primaryToolbar', 'interaction', 'editorViewMode', 'toolbar'], function (states) {
var _states$primaryToolba, _states$interactionSt, _states$editorViewMod, _states$toolbarState;
return {
primaryToolbarComponents: (_states$primaryToolba = states.primaryToolbarState) === null || _states$primaryToolba === void 0 ? void 0 : _states$primaryToolba.components,
interactionState: (_states$interactionSt = states.interactionState) === null || _states$interactionSt === void 0 ? void 0 : _states$interactionSt.interactionState,
editorViewMode: (_states$editorViewMod = states.editorViewModeState) === null || _states$editorViewMod === void 0 ? void 0 : _states$editorViewMod.mode,
contextualFormattingModeOverride: (_states$toolbarState = states.toolbarState) === null || _states$toolbarState === void 0 ? void 0 : _states$toolbarState.contextualFormattingModeOverride
};
});
// Markdown Mode forces `'always-pinned'` while in source / preview view
// (no PM selection to anchor a floating toolbar to). The user's docking
// pref alone is not enough to decide whether to mount the primary toolbar
// in that case — the override has to short-circuit the hide gate below.
var forcePrimaryToolbarPinned = state.contextualFormattingModeOverride === 'always-pinned' && (0, _platformFeatureFlags.fg)('platform_editor_toolbar_mode_override');
var interactionState = state.interactionState;
var primaryToolbarState = (0, _getPrimaryToolbarComponents.getPrimaryToolbarComponents)(editorAPI, state.primaryToolbarComponents);
var hasHadInteraction = interactionState !== 'hasNotHadInteraction';
var toolbarDocking = (0, _useSharedPluginStateSelector.useSharedPluginStateSelector)(editorAPI, 'selectionToolbar.toolbarDocking', {
disabled: (0, _platformFeatureFlags.fg)('platform_editor_use_preferences_plugin')
});
if (!(0, _platformFeatureFlags.fg)('platform_editor_use_preferences_plugin')) {
if (!toolbarDocking) {
var _editorAPI$selectionT, _editorAPI$selectionT2;
// This is a workaround for the rendering issue with the selection toolbar
// where using useSharedPluginStateSelector or useSharedPluginState the state are not
// available when the editor is first loaded. and cause the toolbar to blink.
var defaultDocking = props.__livePage ? 'none' : 'top';
toolbarDocking = (_editorAPI$selectionT = editorAPI === null || editorAPI === void 0 || (_editorAPI$selectionT2 = editorAPI.selectionToolbar) === null || _editorAPI$selectionT2 === void 0 || (_editorAPI$selectionT2 = _editorAPI$selectionT2.sharedState.currentState()) === null || _editorAPI$selectionT2 === void 0 ? void 0 : _editorAPI$selectionT2.toolbarDocking) !== null && _editorAPI$selectionT !== void 0 ? _editorAPI$selectionT : defaultDocking;
}
}
var _ref3 = (0, _useSharedPluginStateSelector.useSharedPluginStateSelector)(editorAPI, 'userPreferences.preferences', {
disabled: !(0, _platformFeatureFlags.fg)('platform_editor_use_preferences_plugin')
}) || {},
toolbarDockingPosition = _ref3.toolbarDockingPosition;
if ((0, _platformFeatureFlags.fg)('platform_editor_use_preferences_plugin')) {
if (!toolbarDockingPosition) {
var _editorAPI$userPrefer, _editorAPI$userPrefer2;
// This is a workaround for the rendering issue with the selection toolbar
// when using useSharedPluginStateWithSelector the state is not yet
// available when the editor is first loaded.
// This causes the toolbar to blink creating a layout shift.
var defaultDockingPosition = props.__livePage ? 'none' : 'top';
toolbarDockingPosition = (_editorAPI$userPrefer = editorAPI === null || editorAPI === void 0 || (_editorAPI$userPrefer2 = editorAPI.userPreferences) === null || _editorAPI$userPrefer2 === void 0 || (_editorAPI$userPrefer2 = _editorAPI$userPrefer2.actions.getUserPreferences()) === null || _editorAPI$userPrefer2 === void 0 ? void 0 : _editorAPI$userPrefer2.toolbarDockingPosition) !== null && _editorAPI$userPrefer !== void 0 ? _editorAPI$userPrefer : defaultDockingPosition;
}
}
var primaryToolbarComponents = props.primaryToolbarComponents;
if (Array.isArray(primaryToolbarState === null || primaryToolbarState === void 0 ? void 0 : primaryToolbarState.components) && Array.isArray(primaryToolbarComponents)) {
primaryToolbarComponents = primaryToolbarState.components.concat(primaryToolbarComponents);
}
var isEditorToolbarHidden = state.editorViewMode === 'view';
var customPrimaryToolbarComponents = props.customPrimaryToolbarComponents;
if ((0, _experiments.editorExperiment)('platform_editor_controls', 'variant1', {
exposure: true
})) {
if ((0, _platformFeatureFlags.fg)('platform_editor_use_preferences_plugin')) {
// need to check if the toolbarDockingPosition is set to 'none' or 'top'
if (toolbarDockingPosition === 'none' && !forcePrimaryToolbarPinned) {
primaryToolbarComponents = [];
if (!hasCustomComponents(customPrimaryToolbarComponents)) {
isEditorToolbarHidden = true;
}
}
} else {
if (toolbarDocking === 'none' && !forcePrimaryToolbarPinned) {
primaryToolbarComponents = [];
if (!hasCustomComponents(customPrimaryToolbarComponents)) {
isEditorToolbarHidden = true;
}
}
}
}
var isToolbarAIFCEnabled = Boolean(editorAPI === null || editorAPI === void 0 ? void 0 : editorAPI.toolbar);
var popupsBoundariesElement = props.popupsBoundariesElement || (scrollContentContainerRef === null || scrollContentContainerRef === void 0 || (_scrollContentContain = scrollContentContainerRef.current) === null || _scrollContentContain === void 0 ? void 0 : _scrollContentContain.containerArea) || undefined;
return (0, _react2.jsx)(_ssrMeasures.SSRRenderMeasure, {
segmentName: SSR_TRACE_SEGMENT_NAME,
startTimestampRef: firstRenderStartTimestampRef,
onSSRMeasure: props.onSSRMeasure
}, (0, _react2.jsx)(_ui.ContextPanelWidthProvider, null, (0, _react2.jsx)("div", {
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766
css: _StyledComponents.fullPageEditorWrapper
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
,
className: "akEditor",
ref: wrapperElementRef,
style: {
'--ak-editor-fullpage-toolbar-height':
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values
(0, _editorSharedStyles.FULL_PAGE_EDITOR_TOOLBAR_HEIGHT)(isToolbarAIFCEnabled)
}
}, !isEditorToolbarHidden && (isToolbarAIFCEnabled ? (0, _react2.jsx)(_FullPageToolbarNext.FullPageToolbarNext, {
disabled: !!props.disabled || !hasHadInteraction && (0, _expValEquals.expValEquals)('platform_editor_default_toolbar_state', 'isEnabled', true),
toolbarDockingPosition: toolbarDockingPosition !== null && toolbarDockingPosition !== void 0 ? toolbarDockingPosition : toolbarDocking,
beforeIcon: props.primaryToolbarIconBefore,
editorAPI: editorAPI,
editorView: props.editorView,
popupsMountPoint: props.popupsMountPoint,
popupsBoundariesElement: props.popupsBoundariesElement,
popupsScrollableElement: props.popupsScrollableElement,
showKeyline: showKeyline,
customPrimaryToolbarComponents: props.customPrimaryToolbarComponents
}) : (0, _react2.jsx)(_FullPageToolbar.FullPageToolbar, {
appearance: props.appearance,
editorAPI: editorAPI,
beforeIcon: props.primaryToolbarIconBefore,
collabEdit: props.collabEdit,
containerElement: (_scrollContentContain2 = (_scrollContentContain3 = scrollContentContainerRef.current) === null || _scrollContentContain3 === void 0 ? void 0 : _scrollContentContain3.scrollContainer) !== null && _scrollContentContain2 !== void 0 ? _scrollContentContain2 : null,
customPrimaryToolbarComponents: props.customPrimaryToolbarComponents,
disabled: !!props.disabled,
dispatchAnalyticsEvent: props.dispatchAnalyticsEvent,
editorActions: props.editorActions,
editorDOMElement: props.editorDOMElement
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
,
editorView: props.editorView
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
,
eventDispatcher: props.eventDispatcher,
hasMinWidth: props.enableToolbarMinWidth,
popupsBoundariesElement: props.popupsBoundariesElement,
popupsMountPoint: props.popupsMountPoint,
popupsScrollableElement: props.popupsScrollableElement,
primaryToolbarComponents: primaryToolbarComponents,
providerFactory: props.providerFactory,
showKeyline: showKeyline,
featureFlags: props.featureFlags
})), (0, _react2.jsx)(_FullPageContentArea.FullPageContentArea, {
editorAPI: editorAPI,
ref: scrollContentContainerRef,
appearance: props.appearance,
contentComponents: props.contentComponents,
contextPanel: props.contextPanel,
customContentComponents: props.customContentComponents,
disabled: props.disabled,
dispatchAnalyticsEvent: props.dispatchAnalyticsEvent,
editorActions: props.editorActions,
editorDOMElement: props.editorDOMElement
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
,
editorView: props.editorView,
eventDispatcher: props.eventDispatcher,
popupsBoundariesElement: popupsBoundariesElement,
popupsMountPoint: props.popupsMountPoint,
popupsScrollableElement: props.popupsScrollableElement,
providerFactory: props.providerFactory,
wrapperElement: (_wrapperElementRef$cu = wrapperElementRef === null || wrapperElementRef === void 0 ? void 0 : wrapperElementRef.current) !== null && _wrapperElementRef$cu !== void 0 ? _wrapperElementRef$cu : null,
pluginHooks: props.pluginHooks,
featureFlags: props.featureFlags,
isEditorToolbarHidden: isEditorToolbarHidden,
viewMode: state.editorViewMode,
hasHadInteraction: hasHadInteraction,
contentMode: props.contentMode
}))));
};