UNPKG

js-draw

Version:

Draw pictures using a pen, touchscreen, or mouse! JS-draw is a drawing library for JavaScript and TypeScript.

220 lines (219 loc) 8.16 kB
import Editor from '../Editor'; import { ToolbarLocalization } from './localization'; import { ActionButtonIcon } from './types'; import BaseWidget, { ToolbarWidgetTag } from './widgets/BaseWidget'; import { DispatcherEventListener } from '../EventDispatcher'; import { BaseTool } from '../lib'; export interface SpacerOptions { grow: number; minSize: string; maxSize: string; } export type ToolbarActionButtonOptions = { mustBeToplevel?: boolean; autoDisableInReadOnlyEditors?: boolean; }; /** * Abstract base class for js-draw editor toolbars. * * See {@link Editor.addToolbar}, {@link makeDropdownToolbar}, and {@link makeEdgeToolbar}. */ export default abstract class AbstractToolbar { #private; protected editor: Editor; private static colorisStarted; protected localizationTable: ToolbarLocalization; /** @internal */ constructor(editor: Editor, localizationTable: ToolbarLocalization); private closeColorPickerOverlay; private setupCloseColorPickerOverlay; setupColorPickers(): void; protected closeColorPickers(): void; protected getWidgetUniqueId(widget: BaseWidget): string; protected getWidgetFromId(id: string): BaseWidget | undefined; /** Do **not** modify the return value. */ protected getAllWidgets(): Array<BaseWidget>; /** * Adds a spacer. * * **Toolbars can choose to ignore calls to `addSpacer`**. * * @example * Adding a save button that moves to the very right edge of the toolbar * while keeping the other buttons centered: * ```ts * const toolbar = editor.addToolbar(false); * * toolbar.addSpacer({ grow: 1 }); * toolbar.addDefaults(); * toolbar.addSpacer({ grow: 1 }); * * toolbar.addActionButton({ * label: 'Save', * icon: editor.icons.makeSaveIcon(), * }, () => { * saveCallback(); * }); * ``` */ abstract addSpacer(options?: Partial<SpacerOptions>): void; /** * Adds an `ActionButtonWidget` or `BaseToolWidget`. The widget should not have already have a parent * (i.e. its `addTo` method should not have been called). * * @example * ```ts * const toolbar = editor.addToolbar(); * const insertImageWidget = new InsertImageWidget(editor); * toolbar.addWidget(insertImageWidget); * ``` */ addWidget(widget: BaseWidget): void; /** Called by `addWidget`. Implement this to add a new widget to the toolbar. */ protected abstract addWidgetInternal(widget: BaseWidget): void; /** Removes the given `widget` from this toolbar. */ removeWidget(widget: BaseWidget): void; /** Called by `removeWidget`. Implement this to remove a new widget from the toolbar. */ protected abstract removeWidgetInternal(widget: BaseWidget): void; private static rootToolbarId; /** Returns a snapshot of the state of widgets in the toolbar. */ serializeState(): string; /** * Deserialize toolbar widgets from the given state. * Assumes that toolbar widgets are in the same order as when state was serialized. */ deserializeState(state: string): void; /** * Called by `serializeState` to attach any additional JSONifyable data * to the serialized result. * * @returns an object that can be converted to JSON with `JSON.stringify`. */ protected serializeInternal(): any; /** * Called by `deserializeState` with a version of the JSON outputted * previously by `serializeInternal`. */ protected deserializeInternal(_json: any): void; /** * Creates, but does not add, an action button to this container. * * @see * {@link addActionButton} */ protected makeActionButton(title: string | ActionButtonIcon, command: () => void, options?: ToolbarActionButtonOptions | boolean): BaseWidget; /** * Adds an action button with `title` to this toolbar (or to the given `parent` element). * * `options` can either be an object with properties `mustBeToplevel` and/or * `autoDisableInReadOnlyEditors` or a boolean value. If a boolean, it is interpreted * as being the value of `mustBeToplevel`. * * @return The added button. * * **Example**: * ```ts,runnable * import { Editor } from 'js-draw'; * const editor = new Editor(document.body); * const toolbar = editor.addToolbar(); * * function makeTrashIcon() { * const container = document.createElement('div'); * container.textContent = '🗑️'; * return container; * } * * toolbar.addActionButton({ * icon: makeTrashIcon(), // can be any Element not in the DOM * label: 'Delete all', * }, () => { * alert('to-do!'); * }); */ addActionButton(title: string | ActionButtonIcon, command: () => void, options?: ToolbarActionButtonOptions | boolean): BaseWidget; /** * Like {@link addActionButton}, except associates `tags` with the button that allow * different toolbar styles to give the button tag-dependent styles. */ addTaggedActionButton(tags: (ToolbarWidgetTag | string)[], title: string | ActionButtonIcon, command: () => void, options?: ToolbarActionButtonOptions | boolean): BaseWidget; /** * Adds a save button that, when clicked, calls `saveCallback`. * * @example * ```ts,runnable * import { Editor, makeDropdownToolbar } from 'js-draw'; * * const editor = new Editor(document.body); * const toolbar = makeDropdownToolbar(editor); * * toolbar.addDefaults(); * toolbar.addSaveButton(() => alert('save clicked!')); * ``` * * `labelOverride` can optionally be used to change the `label` or `icon` of the button. */ addSaveButton(saveCallback: () => void, labelOverride?: Partial<ActionButtonIcon>): BaseWidget; /** * Adds an "Exit" button that, when clicked, calls `exitCallback`. * * **Note**: This is *roughly* equivalent to * ```ts * toolbar.addTaggedActionButton([ ToolbarWidgetTag.Exit ], { * label: this.editor.localization.exit, * icon: this.editor.icons.makeCloseIcon(), * * // labelOverride can be used to override label or icon. * ...labelOverride, * }, () => { * exitCallback(); * }); * ``` * with some additional configuration. * * @final */ addExitButton(exitCallback: () => void, labelOverride?: Partial<ActionButtonIcon>): BaseWidget; /** * Adds undo and redo buttons that trigger the editor's built-in undo and redo * functionality. */ addUndoRedoButtons(undoFirst?: boolean): void; /** * Adds widgets for pen/eraser/selection/text/pan-zoom primary tools. * * If `filter` returns `false` for a tool, no widget is added for that tool. * See {@link addDefaultToolWidgets} */ addWidgetsForPrimaryTools(filter?: (tool: BaseTool) => boolean): void; /** * Adds toolbar widgets based on the enabled tools, and additional tool-like * buttons (e.g. {@link DocumentPropertiesWidget} and {@link InsertImageWidget}). */ addDefaultToolWidgets(): void; /** * Adds widgets that don't correspond to tools, but do allow the user to control * the editor in some way. * * By default, this includes {@link DocumentPropertiesWidget} and {@link InsertImageWidget}. */ addDefaultEditorControlWidgets(): void; addDefaultActionButtons(): void; /** * Adds both the default tool widgets and action buttons. */ abstract addDefaults(): void; /** * Remove this toolbar from its container and clean up listeners. * This should only be called **once** for a given toolbar. */ remove(): void; /** * Removes `listener` when {@link remove} is called. */ protected manageListener(listener: DispatcherEventListener): void; /** * Internal logic for {@link remove}. Implementers should remove the toolbar * from its container. */ protected abstract onRemove(): void; }