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:
- Promise (polyfill, browser support)
- Fetch API (polyfill, browser support)
- Element.closest (polyfill, browser support)
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 buttonsfull-page
- should be used for a full page editor where it is the user focus of the pagechromeless
- is essentially thecomment
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, Arrayreact.ReactElementafter required One of react.ReactElement, Arrayreact.ReactElement, One of react.ReactElement, Arrayreact.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, Arrayreact.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, Arrayreact.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 ArrayOne of @atlaskit/editor-common/extensions.ExtensionProvider, Promise@atlaskit/editor-common/extensions.ExtensionProvider, editorActions => ArrayOne 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
- cased in kebab-case (match [a-z-])
- 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
smartLinks
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, Arrayreact.ReactElementafter required One of react.ReactElement, Arrayreact.ReactElement, One of react.ReactElement, Arrayreact.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