import { COLORS, LocationDescriptor, MeatballMenuApi } from "@heydovetail/ui-components"; import { Plugin } from "prosemirror-state"; import { Observable } from "rxjs"; import { AttachmentPlugin } from "./attachment/AttachmentPlugin"; import { AttachmentService } from "./attachment/AttachmentService"; import { BlurSelectionPlugin } from "./blurselection/BlurSelectionPlugin"; import { compose } from "./compose"; import { EditablePlugin } from "./editable/EditablePlugin"; import { HighlightDecorationPlugin } from "./highlight/HighlightDecorationPlugin"; import { HighlightHoverPlugin } from "./highlight/HighlightHoverPlugin"; import { HighlightSidebarPlugin } from "./highlight/HighlightSidebarPlugin"; import { getPluginState as getHighlightWidgetPluginState, HighlightWidgetPlugin, Tag, TagGroup } from "./highlight/HighlightWidgetPlugin"; import { historyPlugin } from "./historyPlugin"; import { keymapPlugin } from "./keymapPlugin"; import { LinkPlugin } from "./link/LinkPlugin"; import { PlaceholderPlugin } from "./placeholder/PlaceholderPlugin"; import { RangePlugin } from "./range/RangePlugin"; import { Range } from "./range/types"; import { TablePlugin } from "./table/TablePlugin"; import { textShortcutsPlugin } from "./textShortcutsPlugin"; import { ToolbarPlugin } from "./toolbar/ToolbarPlugin"; import { PortalProviderApi } from "./util/PortalProvider"; import { WedgePlugin } from "./wedge/WedgePlugin"; export interface HighlightOptions { initialRanges?: ReadonlyArray; initialFocusedRangeId?: string; getTagGroups(): Observable; createTag(args: { groupId: string | null; title: string }): Promise; onCopyHighlightURL?: (rangeId: string) => void; tagQuickEditRenderer?: (tagId: string, menuApi: MeatballMenuApi) => React.ReactNode; generateTagURL: (tagId: string) => LocationDescriptor; } /** * Build the set of plugins needed for an editor. */ export function plugins(options: { portalProviderApi: PortalProviderApi; defaultEditable: boolean; attachmentService?: AttachmentService; placeholderText?: string; highlightOptions?: HighlightOptions; }): Array { const { p, fragment } = compose; return [ new EditablePlugin(options.defaultEditable), historyPlugin, new WedgePlugin(), keymapPlugin, new TablePlugin(), ...(options.highlightOptions !== undefined ? [ new RangePlugin(options.highlightOptions.initialRanges, options.highlightOptions.initialFocusedRangeId), new HighlightWidgetPlugin( options.portalProviderApi, options.highlightOptions.getTagGroups, options.highlightOptions.createTag ), new HighlightDecorationPlugin({ defaultFocusedRangeId: options.highlightOptions.initialFocusedRangeId }), new HighlightHoverPlugin(options.portalProviderApi), new HighlightSidebarPlugin( options.portalProviderApi, options.highlightOptions.generateTagURL, options.highlightOptions.onCopyHighlightURL, options.highlightOptions.tagQuickEditRenderer ) ] : []), new BlurSelectionPlugin({ color: COLORS.i08, skip: state => { const highlightWidgetPluginState = getHighlightWidgetPluginState(state); return highlightWidgetPluginState !== null && highlightWidgetPluginState.widgetState.type === "tagging"; } }), textShortcutsPlugin, new LinkPlugin({ portalProviderApi: options.portalProviderApi }), // The attachment plugin is optional, and is only enabled if its // dependencies are provided. ...(options.attachmentService !== undefined ? [new AttachmentPlugin(options.portalProviderApi, options.attachmentService)] : []), new PlaceholderPlugin({ text: options.placeholderText !== undefined ? options.placeholderText : "Type some text…", isBlank: state => state.doc.content.eq(fragment(p()).fragment) }), new ToolbarPlugin(options.portalProviderApi) ]; }