Editor core - Legacy editor

Note: This component is designed for internal Atlassian development.

External contributors will be able to use this component but will not be able to submit issues.

Note:

Don't forget to add these polyfills to your product build if you're using emoji or mentions in the editor and you want to target older browsers:

Installing the editor package

The dependencies of editor is a complex beast and can confuse some package managers (npm does not seem to result in duplicates, but yarn does).

We have encountered many strange bugs that were caused by duplicated packages in a product codebase. It is highly recommend to deduplicate packages to work around the yarn bug.

Be sure to dedupe your packages after adding or upgrading @atlaskit/editor-core in your package.json file. Our recommendation is to use yarn-deduplicate.

Starting to use the editor

Simplest Editor

The simplest editor in the world is just:

import { Editor } from '@atlaskit/editor-core'; <Editor appearance="comment" />;

This will render the comment editor with only text formatting (bold / italics / underline / superscript/subscript) enabled.

You can enable more functionality in the editor via passing extra props.

Editor with mentions

To add mention capabilities to the editor, you will need to pass in a "Mention Provider". At a high level, this is simply an object that will allow us to interface whatever mention source you want to use with the editor. This looks like:

import { Editor } from '@atlaskit/editor-core'; import mentionProvider from './mentionProvider'; <Editor appearance="comment" mentionProvider={mentionProvider.get()} />;

Collapsed Editor

Sometimes we don't want to show the whole editor at the start and instead show a collapsed state for a user to click on to start typing. This looks like:

import { Editor, CollapsedEditor } from '@atlaskit/editor-core'; class CollapsibleEditor extends React.Component { state = { isExpanded: false }; expandEditor = () => this.setState({ isExpanded: true }); collapseEditor = () => this.setState({ isExpanded: false }); onSave = () => { /* do something */ }; render() { return ( <CollapsedEditor placeholder="What would you like to say?" isExpanded={this.state.isExpanded} onFocus={this.expandEditor} assistiveLabel="What would you like to say?" > <Editor appearance="comment" onSave={this.onSave} onCancel={this.collapseEditor} /> </CollapsedEditor> ); } }

What is EditorContext?!?!

EditorContext allows you, in conjunction with WithEditorActions, to manipulate the editor from anywhere inside the EditorContext. In the example below, notice that no reference is kept to the editor instance.

New assistiveLabel prop(optional)

assistiveLabel prop allosws you to set an aria-label for ChromeCollapsed to improve a11y

import { EditorContext, WithEditorActions } from '@atlaskit/editor-core'; import { CollapsibleEditor } from 'previous-example'; <EditorContext> <div> <CollapsibleEditor /> <WithEditorActions render={actions => ( <ButtonGroup> <Button onClick={() => actions.clear()}>Clear Editor</Button> <Button onClick={() => actions.focus()}>Focus Editor</Button> </ButtonGroup> )} /> </div> </EditorContext>;

How can I set the content of the editor?

There's two ways at the moment. It depends on whether the editor is mounted yet or not.

If the editor is not mounted

You can just pass through the value you want to set the editor to, as the defaultValue prop

If the Editor is Mounted

You can use WithEditorActions and actions.replaceDocument(documentValueHere) together

Using a non-'Atlassian Document Format' storage format

Using a custom storage format is fairly straightforward - you simply have to import the relevant transformer and pass it through to the editor. That's all!

import { Editor, BitbucketTransformer } from '@atlaskit/editor-core'; <Editor appearance="comment" contentTransformerProvider={schema => new BitbucketTransformer(schema)} />;

Example saving content

If you want an example of actually using WithEditorActions to save content, you've got it!

class SaveExample extends React.Component { onSubmit = actions => editorView => { actions.getValue().then(value => { if (value != null) { dispatch({ type: 'SAVE_COMMENT', payload: value }); } }) } render() { return ( <EditorContext> <WithEditorActions render={actions => ( <Editor appearance="comment" onSave={this.onSubmit(actions)} /> )} /> </EditorContext> ) }

alternatively

class EditorWrapper extends React.Component { propTypes = { actions: PropTypes.object }; onSubmit = () => { this.props.actions.getValue().then(value => { if (value != null) { dispatch({ type: 'SAVE_COMMENT', payload: value }); } }); }; render() { return ( <Editor appearance="comment" onSave={this.onSubmit} /> ); } } class SaveExample extends React.Component { render() { return ( <EditorContext> <WithEditorActions render={actions => <EditorWrapper actions={actions} />} /> </EditorContext> ); } }

We’d love to hear your feedback.

Theming and dark mode support

To render certain ADF content correctly in different color themes, such as light and dark mode, this package utilise the @atlaskit/editor-palette package, which converts colors stored in ADF to Atlassian Design Tokens. Learn more about this utility in the Editor Palette docs.

Full light and dark mode support for the Editor is a work in progress. Currently, the following experiences do not yet support theming:

  • Custom table backgrounds

Tab indexing / focus

If you are displaying a title you may need to listen for a tab event to explicitly enable and focus the editor.

Shift + Tab will move from the title bar to the toolbar preserving tab order.

See the Full Page Example code for a complete implementation.

For example:

<WithEditorActions render={actions => ( <TitleInput placeholder="Give this page a title..." onKeyDown={(e: KeyboardEvent) => this.onKeyPressed(e, actions) } /> )} />
private onKeyPressed = (e: KeyboardEvent, actions: EditorActions) => { if (e.key === 'Tab' && !e.shiftKey) { actions.focus(); return false; } };

Basic

A basic example of the Composable Editor which has basic text formatting, analytics, headings, and lists.

import { ComposableEditor } from '@atlaskit/editor-core/composable-editor'; import { usePreset } from '@atlaskit/editor-core/use-preset'; import { basePlugin } from '@atlaskit/editor-plugins/base'; import { blockTypePlugin } from '@atlaskit/editor-plugins/block-type'; import { listPlugin } from '@atlaskit/editor-plugins/list'; import { analyticsPlugin } from '@atlaskit/editor-plugins/analytics'; function Editor() { const { preset } = usePreset( (builder) => builder .add(basePlugin) .add(analyticsPlugin) .add(blockTypePlugin) .add(listPlugin), [], ); return <ComposableEditor preset={preset} />; }


Props

initialPluginConfiguration export

InitialPluginConfiguration

dangerouslyAppendPlugins object deprecated

Do not use outside of Editor team. This has subtle side effects - you WILL break functionality without implementer knowledge of editor-core internals

__plugins arrayType required Array
@atlaskit/editor-common/types.EditorPlugin

assistiveDescribedBy string

Editor assitive describedby. Set aria-describedby to make the editor announcement to include the information the associated component's content

appearance import = "comment"

Note: this comment is replicated in packages/editor/renderer/src/ui/Renderer/types.ts any changes should be made in both locations Configure the display mode of the editor. Different modes may have different feature sets supported.

  • comment - should be used for things like comments where you have a field input but require a toolbar & save/cancel buttons
  • full-page - should be used for a full page editor where it is the user focus of the page
  • chromeless - is essentially the comment editor but without the editor chrome, like toolbar & save/cancel buttons
@atlaskit/editor-common/types.EditorAppearance

contentComponents union

React components declared in this prop will be inserted into the editor content area

One of
before required One of
react.ReactElement,
Array
react.ReactElement
after required One of
react.ReactElement,
Array
react.ReactElement
,
One of
react.ReactElement,
Array
react.ReactElement

primaryToolbarIconBefore import

Optionally adds an element (eg: an icon) at the start of the editor's primary toolbar. If not specified, the primary toolbar spans the entire width.

react.ReactElement

secondaryToolbarComponents union

React components declared in this prop will be inserted into the secondary toolbar area

One of
react.ReactElement,
Array
react.ReactElement

persistScrollGutter boolean

quickInsert import = true

Set to enable the quick insert menu i.e. '/' key trigger. You can also provide your own insert menu options that will be shown in addition to the enabled editor features e.g. Confluence uses this to provide its macros.

@atlaskit/editor-common/types.QuickInsertOptions

shouldFocus boolean

Set if the editor should be focused.

disabled boolean = false

Set if the editor should be disabled.

contextPanel union

Content to appear in the context panel. Displays as a right sidebar in the full-page appearance. You'll want to pass it a ContextPanel component from this package, and your content as its children.

One of
react.ReactElement,
Array
react.ReactElement

errorReporterHandler import

@atlaskit/editor-common/error-reporter.ErrorReportingHandler

contentTransformerProvider function

schema => @atlaskit/editor-common/types.Transformerstring

maxHeight number

Set to configure the maximum editor height in pixels for comment and chromeless editor modes.

minHeight number

Set to configure the minimum editor height in pixels for comment, chromeless editor modes.

defaultValue union

Set the default editor content.

One of
@atlaskit/editor-prosemirror/model.Node,
string,
Object

assistiveLabel string

Editor assitive label. Assistive label is hard coded to "Main content area, start typing to enter text.", defined in "packages/editor/editor-core/src/create-editor/messages.ts" When this prop is set, it will override default one.

popupsMountPoint HTMLElement

Set the DOM element for attaching popup menus

HTMLElement

popupsBoundariesElement HTMLElement

DOM element used to help calculate correct positioning of popup menus to make sure they dont go offscreen.

HTMLElement

popupsScrollableElement HTMLElement

Specify when mount point is different from scrollable element so popup menus can be positioned according the scrollable element.

HTMLElement

editorActions import

../actions.EditorActions

onEditorReady function

Set a callback for the editor when users are able to interact. Also provides access to EditorActions for controlling editor.

editorActions => undefined

onDestroy function

Called when editor is being unmounted

() => undefined

onChange function

Set for an on change callback. meta.source === 'remote' means that a change is coming from remote source, e.g. collab editing session.

function
editorView,
meta
=> undefined

onCancel function

Set for an on cancel callback.

editorView => undefined

inputSamplingLimit number deprecated

do not use, value is hardcoded. Can be mocked for tests. Config exists here: platform/packages/editor/editor-plugin-base/src/pm-plugins/utils/inputTrackingConfig.ts @description The nth keystroke after which an input time taken event is sent, 0 to disable it @default 100

extensionProviders union

New extension API This eventually is going to replace quickInsert.provider, extensionHandlers, macroProvider.

One of
Array
One of
@atlaskit/editor-common/extensions.ExtensionProvider,
Promise@atlaskit/editor-common/extensions.ExtensionProvider
,
editorActions => Array
One of
@atlaskit/editor-common/extensions.ExtensionProvider,
Promise@atlaskit/editor-common/extensions.ExtensionProvider

UNSAFE_useAnalyticsContext boolean

Experimental support for modern React Context for @atlaskit/analytics-next. Enables re-providing of AnalyticsContext for all ReactNodeViews.

useStickyToolbar import

@default undefined @description Enables the sticky toolbar in the comment/standard editor. If a boolean is specified and it's true, the sticky toolbar will be enabled, sticking to the top of the scroll parent. Instead a reference can be specified to an existing sticky toolbar on the page that the editor toolbar should stay below (experimental). if {offsetTop: number} is passed in, the toolbar is sticky and the toolbar's 'top' will be set to the offsetTop so the toolbar will sticks to {offsetTop} below the scroll parent.

@atlaskit/editor-common/ui.UseStickyToolbarType

featureFlags object

  • @default undefined
  • @description
  • Short lived feature flags for experiments and gradual rollouts
  • Flags are expected to follow these rules or they are filtered out
    1. cased in kebab-case (match [a-z-])
    1. have boolean values
  • @example
  • (<Editor featureFlags={{ 'my-feature': true }} />);
  • getFeatureFlags()?.myFeature === true;
  • @example
  • (<Editor featureFlags={{ 'my-feature': 'thing' }} />);
  • getFeatureFlags()?.myFeature === undefined;
  • @example
  • (<Editor featureFlags={{ 'product.my-feature': false }} />);
  • getFeatureFlags()?.myFeature === undefined;
  • getFeatureFlags()?.productMyFeature === undefined;
[featureFlag: string] union required One of
string,
boolean

__livePage boolean

  • This is required for accessing whether a page is a live page or not when rendering the appearance component.
  • All other consumers should use the editorViewModePlugin to access live page and content mode status.
  • @default false

skipValidation boolean

allowExpand union

One of
boolean,
allowInsertion boolean
allowInteractiveExpand boolean

allowNestedTasks boolean

allowBlockType import

Configure allowed blocks in the editor, currently only supports heading, blockquote, hardBreak and codeBlock.

undefined.BlockTypePluginOptions['allowBlockType']

allowTasksAndDecisions boolean

Whether or not you want to allow Action and Decision elements in the editor. You can currently only enable both or disable both. To enable, you need to also provide a taskDecisionProvider. You will most likely need backend ADF storage for this feature.

allowBreakout boolean

Enables new breakout mark. This mark is being used for making code-blocks breakout.

allowRule boolean

Enables horizontal rules.

allowHelpDialog boolean = true

Enable the editor help dialog.

allowPanel union

Enable panel blocks, the thing that displays a coloured box with icons aka info, warning macros. You will most likely need backend ADF storage for this feature.

One of
boolean,
@atlaskit/editor-plugins/panel.PanelPluginConfig

allowExtension union

Enable extensions. Extensions let products and the ecosystem extend ADF and render their own things. Similar to macros in Confluence. You will most likely need backend ADF storage for this feature.

One of
boolean,
allowBreakout boolean
allowExtendFloatingToolbars boolean

allowConfluenceInlineComment boolean

allowTemplatePlaceholders union

Enable placeholder text which is handy for things like a template editor. Placeholder text is an inline text element that is removed when a user clicks on it. You can also disable the inserts for this feature so users can never insert such placeholder elements in the editor but you could load the initial content in the editor with them.

One of
boolean,
@atlaskit/editor-plugins/placeholder-text.PlaceholderTextOptions

allowDate union

Enable dates. You will most likely need backend ADF storage for this feature. Can use true/false to enable/disable default or can pass in DatePluginConfig object to configure weekStartDay

One of
boolean,
@atlaskit/editor-plugins/date.DatePluginConfig

allowLayouts union

Temporary flag to enable layouts while it's under development Use object form to enable breakout for layouts, and to enable the newer layouts - left sidebar & right sidebar

One of
boolean,
@atlaskit/editor-plugins/layout.LayoutPluginOptions

allowStatus union

Enable status, if menuDisabled is passed then plugin is enabled by default

One of
boolean,
menuDisabled boolean required

allowTextAlignment boolean

Enable text alignment support inside heading and paragraph

allowIndentation boolean

Enable indentation support for heading and paragraph

showIndentationButtons boolean

Enable showing of indentation buttons in editor toolbar

allowFindReplace union

Enable find/replace functionality within the editor. You can use the object form to enable additional individual features e.g. case-matching toggle.

One of
boolean,
@atlaskit/editor-plugins/find-replace.FindReplaceOptions

allowBorderMark boolean

Enable support for the "border" mark. Refer to ADF Change proposal #65 for more details.

allowFragmentMark boolean

Enable support for the "fragment" mark. Refer to ADF Change proposal #60 for more details.

autoScrollIntoView boolean

Set this to false to opt out of the default behaviour of auto scrolling into view whenever the document is changed

elementBrowser object

showModal boolean
replacePlusMenu boolean
helpUrl string
emptyStateHandler @atlaskit/editor-common/types.EmptyStateHandler

maxContentSize number

Set to configure the maximum ADF node document size. Understandably this isn’t the best logical max parameter for content, but its the cheapest for now.

saveOnEnter boolean

Submits on the enter key. Probably useful for an inline comment editor use case.

feedbackInfo import

Information required for editor to display the feedback modal. This is also required to enable quick insert plugin for feedback modal.

@atlaskit/editor-common/types.FeedbackInfo

mention import

@atlaskit/editor-plugins/mentions.MentionPluginConfig

mentionInsertDisplayName boolean deprecated

flag to indicate display name instead of nick name should be inserted for mentions default: false, which inserts the nick name Use mention.mentionInsertDisplayName instead

uploadErrorHandler function

state => undefined

waitForMediaUpload boolean

Set if you want to wait for media file uploads before save.

extensionHandlers import = {}

Set to provide your extensions handlers.

@atlaskit/editor-common/extensions.ExtensionHandlers

allowTextColor union

Enables text colour. Ew are you sure you want to enable this?

One of
boolean,
@atlaskit/editor-plugins/text-color.TextColorPluginConfig

allowTables union

Enables tables. You can enable individual table features like table header rows and cell background colour. You will most likely need backend ADF storage for the advanced table features.

One of
boolean,
@atlaskit/editor-plugins/table/types.PluginConfig

insertMenuItems arrayType

Set to add custom menu items to the insert (plus) menu dropdown.

Array
@atlaskit/editor-common/ui-menu.MenuItem

UNSAFE_cards import deprecated

Use linking.smartLinks prop instead.

@atlaskit/editor-common/card.CardOptions

allowAnalyticsGASV3 boolean

codeBlock import

@atlaskit/editor-plugins/code-block.CodeBlockOptions

textFormatting import

Set to disable text formatting styles. If not specified, they will be all enabled by default. Code here refers to inline code. Smart text completion refers to the auto replacement of characters like arrows, quotes and correct casing of Atlassian product names. This should only be disabled if the user has an OS setting that disables this.

@atlaskit/editor-common/types.TextFormattingOptions

placeholder string

Default placeholder text to be displayed if the document content is empty. e.g. 'Add a comment...'

placeholderBracketHint string

Default placeholder text to be displayed when a bracket '{' is typed and the line is empty e.g. 'Did you mean to use '/' to insert content?'

linking import

Configure and extend editor linking behaviour

@atlaskit/editor-common/types.LinkingOptions

media import

Set to configure media features. Media single refers to the embedded version of media, which is probably what you want. Media group refers to a filmstrip, thumbnail view of media files which was used in Stride.

@atlaskit/editor-plugins/media/types.MediaOptions

onSave function

Set for an on save callback.

editorView => undefined

performanceTracking import deprecated

do not use, value is hardcoded. Can be mocked for tests. Config exists here: platform/packages/editor/editor-plugin-base/src/pm-plugins/utils/inputTrackingConfig.ts @description Control performance metric measurements and tracking

@atlaskit/editor-common/types.PerformanceTracking

sanitizePrivateContent boolean

Flag to remove private content such as mention names

collabEdit import

@atlaskit/editor-common/collab.CollabEditOptions

primaryToolbarComponents union

One of
before required One of
react.ReactElement,
Array
react.ReactElement
after required One of
react.ReactElement,
Array
react.ReactElement
,
One of
react.ReactElement,
Array
react.ReactElement

allowUndoRedoButtons boolean

Enable undo/redo buttons within the editor.

activityProvider Promise<import>

Promise@atlaskit/activity-provider.ActivityProvider

searchProvider Promise<import>

Promise@atlaskit/editor-common/provider-factory.SearchProvider

annotationProviders import

@atlaskit/editor-plugins/annotation.AnnotationProviders

collabEditProvider import

undefined.Providers['collabEditProvider']

presenceProvider Promise<any>

Promiseany

emojiProvider import

undefined.Providers['emojiProvider']

taskDecisionProvider Promise<import>

Promise@atlaskit/task-decision.TaskDecisionProvider

legacyImageUploadProvider import

undefined.Providers['imageUploadProvider']

mentionProvider Promise<import> deprecated

  • pass mentionProvider directly to mentionPlugin via the preset
Promise@atlaskit/mention/resource.MentionProvider

autoformattingProvider import

Allows you to define custom autoformatting rules.

undefined.Providers['autoformattingProvider']

macroProvider import

This is temporary for Confluence. Please do not use.

undefined.Providers['macroProvider']

contextIdentifierProvider Promise<import>

Promise@atlaskit/editor-common/provider-factory.ContextIdentifierProvider