@atlaskit/editor-core
Version:
A package contains Atlassian editor core functionality
159 lines (155 loc) • 6.53 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
/**
* @jsxRuntime classic
* @jsx jsx
*/
import { useCallback, useMemo, useRef, Fragment } from 'react';
// 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
import { jsx } from '@emotion/react';
import isEqual from 'lodash/isEqual';
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
import uuid from 'uuid/v4';
import { FabricEditorAnalyticsContext } from '@atlaskit/analytics-namespaced-context';
import { useAnalyticsEvents } from '@atlaskit/analytics-next/useAnalyticsEvents';
import { ACTION, fireAnalyticsEvent } from '@atlaskit/editor-common/analytics';
import { startMeasure, stopMeasure } from '@atlaskit/editor-common/performance-measures';
import { getAnalyticsAppearance } from '@atlaskit/editor-common/utils/analytics';
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
import EditorActions from '../actions';
import { useEditorContext } from '../ui/EditorContext';
import { createFeatureFlagsFromProps } from '../utils/feature-flags-from-props';
import measurements from '../utils/performance/measure-enum';
import { name, version } from '../version-wrapper';
import { EditorINPMetrics } from './editor-inp-metrics';
import { EditorInternal } from './editor-internal';
import useMeasureEditorMountTime from './hooks/useMeasureEditorMountTime';
// Ignored via go/ees005
// eslint-disable-next-line import/no-named-as-default
import useMemoEditorProps from './hooks/useMemoEditorProps';
import useProviderFactory from './hooks/useProviderFactory';
import sendDurationAnalytics from './utils/sendDurationAnalytics';
/**
* Editor wrapper that deals with the lifecycle logic of the editor
* @param passedProps
* @example
*/
function Editor(passedProps) {
const propsRef = useRef(passedProps);
const props = useMemoEditorProps(passedProps);
useMemo(() => {
propsRef.current = props;
}, [props]);
const editorContext = useEditorContext();
const editorActionsPlaceholderInstance = useMemo(() => new EditorActions(), []);
const editorActions = editorContext.editorActions || editorActionsPlaceholderInstance;
const {
createAnalyticsEvent
} = useAnalyticsEvents();
const handleAnalyticsEvent = useCallback(data => {
fireAnalyticsEvent(createAnalyticsEvent)(data);
}, [createAnalyticsEvent]);
const getFeatureFlagsFromRef = useCallback(() => {
var _propsRef$current$col, _propsRef$current$col2;
return {
...createFeatureFlagsFromProps(propsRef.current.featureFlags),
useNativeCollabPlugin: Boolean(typeof ((_propsRef$current$col = propsRef.current.collabEdit) === null || _propsRef$current$col === void 0 ? void 0 : _propsRef$current$col.useNativePlugin) === 'boolean' ? !!((_propsRef$current$col2 = propsRef.current.collabEdit) !== null && _propsRef$current$col2 !== void 0 && _propsRef$current$col2.useNativePlugin) : false)
};
}, []);
const onEditorCreated = useCallback(instance => {
const {
contextIdentifierProvider,
onEditorReady,
featureFlags
} = propsRef.current;
editorActions._privateRegisterEditor(instance.view, instance.eventDispatcher, instance.transformer, getFeatureFlagsFromRef);
if (onEditorReady) {
startMeasure(measurements.ON_EDITOR_READY_CALLBACK);
onEditorReady(editorActions);
stopMeasure(measurements.ON_EDITOR_READY_CALLBACK, sendDurationAnalytics(ACTION.ON_EDITOR_READY_CALLBACK, {
contextIdentifierProvider,
featureFlags
}, createAnalyticsEvent));
}
}, [editorActions, createAnalyticsEvent, getFeatureFlagsFromRef, propsRef]);
const onEditorDestroyed = useCallback(_instance => {
const {
onDestroy
} = propsRef.current;
editorActions._privateUnregisterEditor();
if (onDestroy) {
onDestroy();
}
}, [editorActions, propsRef]);
useMeasureEditorMountTime(props, createAnalyticsEvent);
const providerFactory = useProviderFactory(props, editorActions, createAnalyticsEvent);
const {
onSave: onSaveFromProps
} = props;
const handleSave = useCallback(view => {
if (onSaveFromProps) {
onSaveFromProps(view);
}
}, [onSaveFromProps]);
const isFullPageAppearance = Boolean(props.appearance && ['full-page', 'full-width', ...(editorExperiment('platform_synced_block', true) ? ['max'] : [])].includes(props.appearance));
return jsx(Fragment, null, isFullPageAppearance ? jsx(EditorINPMetrics, null) : null, jsx(EditorInternal, {
props: props,
handleAnalyticsEvent: handleAnalyticsEvent,
createAnalyticsEvent: createAnalyticsEvent,
preset: props.preset,
handleSave: handleSave,
editorActions: editorActions,
onEditorCreated: onEditorCreated,
onEditorDestroyed: onEditorDestroyed,
providerFactory: providerFactory,
AppearanceComponent: props.AppearanceComponent
}));
}
const useMemoEditorFeatureFlags = featureFlags => {
const ffRef = useRef(featureFlags);
if (!isEqual(ffRef.current, featureFlags)) {
ffRef.current = featureFlags;
}
return ffRef.current;
};
/**
*
* @param props
* @example
*/
export function CoreEditor(props) {
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
const editorSessionId = useRef(uuid());
const data = useMemo(() => {
return {
packageName: name,
packageVersion: version,
componentName: 'editorCore',
appearance: getAnalyticsAppearance(props.appearance),
editorSessionId: editorSessionId.current
};
}, [props.appearance]);
const memodEditorFeatureFlags = useMemoEditorFeatureFlags(props.featureFlags);
return jsx(FabricEditorAnalyticsContext
// @ts-expect-error Type 'string' is not assignable to type '"editorCore" | "renderer"'.
, {
data: data
}, jsx(Editor
// Ignored via go/ees005
// eslint-disable-next-line react/jsx-props-no-spreading
, _extends({}, props, {
featureFlags: memodEditorFeatureFlags
})));
}
// eslint-disable-next-line @typescript-eslint/no-namespace
CoreEditor.propTypes = {
minHeight: ({
appearance,
minHeight
}) => {
if (minHeight && appearance && !['comment', 'chromeless'].includes(appearance)) {
return new Error('minHeight only supports editor appearance chromeless and comment for Editor');
}
return null;
}
};
export default CoreEditor;