UNPKG

@atlaskit/editor-core

Version:

A package contains Atlassian editor core functionality

159 lines (155 loc) 6.53 kB
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;