@atlaskit/editor-plugin-block-controls
Version:
Block controls plugin for @atlaskit/editor-core
125 lines (122 loc) • 6.62 kB
JavaScript
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
/**
* @jsxRuntime classic
* @jsx jsx
*/
import React, { useEffect, useRef, useState } from 'react';
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled, @typescript-eslint/consistent-type-imports
import { css, jsx } from '@emotion/react';
import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
import { akEditorFullPageNarrowBreakout } from '@atlaskit/editor-shared-styles';
// eslint-disable-next-line @atlaskit/design-system/no-emotion-primitives -- to be migrated to @atlaskit/primitives/compiled – go/akcss
import { Box, xcss } from '@atlaskit/primitives';
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
var RIGHT_CONTROL_HIDE_DELAY_MS = 150;
var baseStyles = xcss({
transition: 'opacity 0.1s ease-in-out, visibility 0.1s ease-in-out'
});
var visibleStyles = xcss({
opacity: 1,
visibility: 'visible'
});
var hiddenStyles = xcss({
opacity: 0,
visibility: 'hidden'
});
var baseStylesCSS = css(_defineProperty({
transition: 'opacity 0.1s ease-in-out, visibility 0.1s ease-in-out'
}, "@container editor-area (max-width: ".concat(akEditorFullPageNarrowBreakout, "px)"), {
opacity: 0,
visibility: 'hidden'
}));
var visibleStylesCSS = css({
opacity: 1,
visibility: 'visible'
});
var hiddenStylesCSS = css({
opacity: 0,
visibility: 'hidden'
});
export var VisibilityContainer = function VisibilityContainer(_ref) {
var api = _ref.api,
children = _ref.children,
controlSide = _ref.controlSide,
forceVisibleOnMouseOut = _ref.forceVisibleOnMouseOut;
var _useSharedPluginState = useSharedPluginStateWithSelector(api, ['typeAhead', 'blockControls', 'editorViewMode', 'userIntent'], function (states) {
var _states$typeAheadStat, _states$blockControls, _states$blockControls2, _states$blockControls3, _states$editorViewMod, _states$userIntentSta, _states$blockControls4;
return {
isTypeAheadOpen: (_states$typeAheadStat = states.typeAheadState) === null || _states$typeAheadStat === void 0 ? void 0 : _states$typeAheadStat.isOpen,
isEditing: (_states$blockControls = states.blockControlsState) === null || _states$blockControls === void 0 ? void 0 : _states$blockControls.isEditing,
isMouseOut: (_states$blockControls2 = states.blockControlsState) === null || _states$blockControls2 === void 0 ? void 0 : _states$blockControls2.isMouseOut,
hoverSide: (_states$blockControls3 = states.blockControlsState) === null || _states$blockControls3 === void 0 ? void 0 : _states$blockControls3.hoverSide,
editorViewMode: (_states$editorViewMod = states.editorViewModeState) === null || _states$editorViewMod === void 0 ? void 0 : _states$editorViewMod.mode,
userIntent: (_states$userIntentSta = states.userIntentState) === null || _states$userIntentSta === void 0 ? void 0 : _states$userIntentSta.currentUserIntent,
rightSideControlsEnabled: (_states$blockControls4 = states.blockControlsState) === null || _states$blockControls4 === void 0 ? void 0 : _states$blockControls4.rightSideControlsEnabled
};
}),
isTypeAheadOpen = _useSharedPluginState.isTypeAheadOpen,
isEditing = _useSharedPluginState.isEditing,
isMouseOut = _useSharedPluginState.isMouseOut,
hoverSide = _useSharedPluginState.hoverSide,
editorViewMode = _useSharedPluginState.editorViewMode,
userIntent = _useSharedPluginState.userIntent,
rightSideControlsEnabled = _useSharedPluginState.rightSideControlsEnabled;
var isViewMode = editorViewMode === 'view';
// rightSideControlsEnabled is the single source of truth (confluence_remix_button_right_side_block_fg from preset)
var shouldRestrictBySide = rightSideControlsEnabled && controlSide !== undefined && !isViewMode;
// Only restrict by side when hoverSide is known (after mousemove). When undefined, show both
// controls so drag handle is visible on load and for keyboard-only users.
var sideHidden = shouldRestrictBySide && hoverSide !== undefined ? hoverSide !== controlSide : false;
// In view mode with right-side controls, we delay hiding on isMouseOut (see below) so the right-edge
// button stays visible when the user moves from the block toward the button (e.g. in edit/live
// pages), avoiding flicker as the mouse crosses boundaries.
var hideOnMouseOut = isMouseOut;
// When forceVisibleOnMouseOut is true (e.g. drag handle focused via keyboard Shift+Ctrl+H),
// override the mouse-out condition so the control stays visible regardless of mouse position.
var shouldHideWhenMouseOut = forceVisibleOnMouseOut ? false : hideOnMouseOut;
var shouldHideImmediate = isTypeAheadOpen || isEditing || shouldHideWhenMouseOut || userIntent === 'aiStreaming' || sideHidden;
// Delay hiding the right control in view mode to reduce flickering when moving from block
// toward the right-edge button (avoids rapid show/hide as mouse crosses boundaries).
var isRightControlViewMode = isViewMode && rightSideControlsEnabled && controlSide === 'right';
// When in right-control view mode, we delay hiding so start visible; useEffect will update after delay
var _useState = useState(false),
_useState2 = _slicedToArray(_useState, 2),
delayedShouldHide = _useState2[0],
setDelayedShouldHide = _useState2[1];
var hideTimeoutRef = useRef(null);
useEffect(function () {
if (!isRightControlViewMode) {
return;
}
if (!shouldHideImmediate) {
if (hideTimeoutRef.current) {
clearTimeout(hideTimeoutRef.current);
hideTimeoutRef.current = null;
}
setDelayedShouldHide(false);
return;
}
hideTimeoutRef.current = setTimeout(function () {
hideTimeoutRef.current = null;
setDelayedShouldHide(true);
}, RIGHT_CONTROL_HIDE_DELAY_MS);
return function () {
if (hideTimeoutRef.current) {
clearTimeout(hideTimeoutRef.current);
}
};
}, [shouldHideImmediate, isRightControlViewMode]);
var shouldHide = isRightControlViewMode ? delayedShouldHide : shouldHideImmediate;
if (editorExperiment('platform_editor_preview_panel_responsiveness', true, {
exposure: true
})) {
return jsx("div", {
css: [baseStylesCSS, shouldHide ? hiddenStylesCSS : visibleStylesCSS]
}, children);
}
// eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
return jsx(Box, {
xcss: [baseStyles, shouldHide ? hiddenStyles : visibleStyles]
}, children);
};