UNPKG

@atlaskit/editor-common

Version:

A package that contains common classes and components for editor and renderer

266 lines (265 loc) • 9.36 kB
import type React from 'react'; import type { IntlShape } from 'react-intl-next'; import type { Node, NodeType } from '@atlaskit/editor-prosemirror/model'; import type { EditorState } from '@atlaskit/editor-prosemirror/state'; import type { EditorView } from '@atlaskit/editor-prosemirror/view'; import type { EmojiId } from '@atlaskit/emoji/types'; import type { DispatchAnalyticsEvent } from '../analytics/types/dispatch-analytics-event'; import type { ProviderFactory } from '../provider-factory'; import type { PaletteColor } from '../ui-color/ColorPalette/Palettes/type'; import type { Command, CommandDispatch } from './command'; import type { MarkOptions, NodeOptions } from './copy-button'; export interface RenderOptionsPropsT<T extends {}> { hide: () => void; dispatchCommand: (command: T) => void; } export interface DropdownOptionT<T extends {}> { id?: string; title: string; onClick: T; onMouseDown?: T; onMouseOver?: T; onMouseEnter?: T; onMouseLeave?: T; onMouseOut?: T; onFocus?: T; onBlur?: T; selected?: boolean; disabled?: boolean; hidden?: boolean; testId?: string; tooltip?: string; elemAfter?: React.ReactNode; } export type DropdownOptions<T extends {}> = Array<DropdownOptionT<T>> | { render: (props: RenderOptionsPropsT<T>) => React.ReactElement<any> | null; height: number; width: number; }; export interface SelectOption<T extends {} = {}> { value: string; label: string; selected?: boolean; disabled?: boolean; hidden?: boolean; data?: T; } export type ButtonAppearance = 'subtle' | 'danger'; export type Icon = React.ComponentType<React.PropsWithChildren<{ label: string; }>>; export type RenderOptionsProps = RenderOptionsPropsT<Command>; export type AlignType = 'left' | 'center' | 'right'; interface Position { top?: number; right?: number; bottom?: number; left?: number; } type PositionOffset = Position; export type ConfirmDialogChildInfo = { id: string; name: string | null; amount: number; }; export interface ConfirmDialogOptions { title?: string; message: string; okButtonLabel?: string; cancelButtonLabel?: string; isReferentialityDialog?: boolean; checkboxLabel?: string; messagePrefix?: string; getChildrenInfo?: () => ConfirmDialogChildInfo[]; onConfirm?: (...args: any[]) => Command; } export type ConfirmationDialogProps = { onConfirm: (isCheck?: boolean) => void; /** * onClose is called every time when the dialog is closed. * Either clicking on 'Confirm' button or 'Cancel' button, * which means it is being called after onConfirm, or by itself when clicking 'Cancel' button. */ onClose: () => void; options?: ConfirmDialogOptions; testId?: string; }; export type FloatingToolbarCopyButton = { type: 'copy-button'; items: Array<FloatingToolbarSeparator | MarkOptions | NodeOptions>; hidden?: boolean; }; export type FloatingToolbarButton<T extends {}> = { id?: string; type: 'button'; isRadioButton?: boolean; title: string; onClick: T; showTitle?: boolean; onMouseEnter?: T; onMouseLeave?: T; onFocus?: T; onBlur?: T; icon?: Icon; selected?: boolean; disabled?: boolean; hidden?: boolean; appearance?: ButtonAppearance; href?: string; target?: string; className?: string; tooltipContent?: React.ReactNode; testId?: string; hideTooltipOnClick?: boolean; confirmDialog?: ConfirmDialogOptions | (() => ConfirmDialogOptions); metadata?: { [key: string]: string; }; ariaHasPopup?: boolean | 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid' | undefined; tabIndex?: number | null | undefined; focusEditoronEnter?: boolean; supportsViewMode?: boolean; }; export type FloatingToolbarInput<T extends {}> = { id: string; type: 'input'; title?: string; description?: string; onSubmit: (...args: any[]) => T; onBlur: (...args: any[]) => T; defaultValue?: string; placeholder?: string; hidden?: boolean; }; export type FloatingToolbarCustom<T extends {}> = { type: 'custom'; /** * By default -- the floating toolbar supports navigating between * items using arrow keys (to meet aria guidelines). * In some cases the floating toolbar is being used to present * non toolbar content -- such as the link editing experience. * In these cases you can opt out of arrow navigation using the * this property. * * @default false */ disableArrowNavigation?: boolean; fallback: Array<FloatingToolbarFallbackItem<T>>; render: (view?: EditorView, idx?: number, dispatchAnalyticsEvent?: DispatchAnalyticsEvent) => React.ReactNode; hidden?: boolean; }; type FloatingToolbarSelectBase<T extends {}, V = SelectOption> = { id: string; type: 'select'; selectType: 'list' | 'emoji' | 'date' | 'color'; title?: string; isAriaExpanded?: boolean; options: V[]; hidden?: boolean; hideExpandIcon?: boolean; defaultValue?: V | null; placeholder?: string; onChange: (selected: V) => T; filterOption?: ((option: V, rawInput: string) => boolean) | null; }; export type FloatingToolbarListPicker<T extends {}> = FloatingToolbarSelectBase<T> & { selectType: 'list'; }; export type FloatingToolbarColorPicker<T extends {}> = FloatingToolbarSelectBase<T, PaletteColor> & { selectType: 'color'; }; export type FloatingToolbarEmojiPicker<T extends {}> = FloatingToolbarSelectBase<T, EmojiId> & { selectType: 'emoji'; selected?: boolean; options: never[]; }; export type FloatingToolbarDatePicker<T extends {}> = FloatingToolbarSelectBase<T, number> & { selectType: 'date'; options: never[]; }; export type FloatingToolbarSelect<T extends {}> = FloatingToolbarEmojiPicker<T> | FloatingToolbarColorPicker<T> | FloatingToolbarListPicker<T> | FloatingToolbarDatePicker<T>; export type FloatingToolbarSeparator = { type: 'separator'; hidden?: boolean; }; export type FloatingToolbarDropdown<T extends {}> = { testId?: string; id?: string; type: 'dropdown'; title: string; icon?: Icon; options: DropdownOptions<T>; hidden?: boolean; hideExpandIcon?: boolean; disabled?: boolean; tooltip?: string; dropdownWidth?: number; showSelected?: boolean; alignDropdownWithToolbar?: boolean; onToggle?: (state: EditorState, dispatch: CommandDispatch | undefined) => boolean; }; type FloatingToolbarExtensionsPlaceholder = { type: 'extensions-placeholder'; hidden?: boolean; separator?: 'start' | 'end' | 'both'; }; /** * This additional type is introduced in order to prevent infinite loop due to * `extract-react-types-loader`. The issue occurs when custom type `fallback` field * is an array of FloatingToolbarItem. Since FloatingToolbarItem is a FloatingToolbarCustom * type, it stucks in an infinite loop. Custom - Item -> Custom .... go on. * * This type is restricted with the items that can be used for fallback. * Make sure that this type is not a FloatingToolbarCustom type. */ export type FloatingToolbarFallbackItem<T extends {}> = FloatingToolbarButton<T> | FloatingToolbarCopyButton | FloatingToolbarDropdown<T> | FloatingToolbarSelect<T> | FloatingToolbarInput<T> | FloatingToolbarSeparator; export type FloatingToolbarItem<T extends {}> = FloatingToolbarButton<T> | FloatingToolbarCopyButton | FloatingToolbarDropdown<T> | FloatingToolbarSelect<T> | FloatingToolbarInput<T> | FloatingToolbarCustom<T> | FloatingToolbarSeparator | FloatingToolbarExtensionsPlaceholder; export interface FloatingToolbarConfig { /** Used for the ariaLabel on the <Popup /> component */ title: string; /** * Override the DOM reference used to apply as the target for the * floating toolbar, if the config matches. * * By default, it will find the DOM reference of the node from the * head of the current selection. */ getDomRef?: (view: EditorView) => HTMLElement | undefined; /** Can prevent the Toolbar from rendering */ visible?: boolean; /** * nodeType or list of `nodeType`s this floating toolbar should be shown for. **/ nodeType: NodeType | NodeType[]; /** Items that will populate the Toolbar. * * See: `FloatingToolbarItem` */ items: Array<FloatingToolbarItem<Command>> | ((node: Node) => Array<FloatingToolbarItem<Command>>); align?: AlignType; /** Class added to Toolbar wrapper */ className?: string; /** Toolbar height */ height?: number; /** Toolbar width */ width?: number; zIndex?: number; /** Offset the position of the toolbar. */ offset?: [ number, number ]; /** Absolute offset of the toolbar */ absoluteOffset?: PositionOffset; forcePlacement?: boolean; onPositionCalculated?: (editorView: EditorView, nextPos: Position) => Position; scrollable?: boolean; /** * Enable Popup component's focus trap */ focusTrap?: boolean; preventPopupOverflow?: boolean; mediaAssistiveMessage?: string; } export type FloatingToolbarHandler = (state: EditorState, intl: IntlShape, providerFactory: ProviderFactory) => FloatingToolbarConfig | undefined; export {};