UNPKG

suneditor

Version:

Vanilla JavaScript based WYSIWYG web editor

263 lines (262 loc) 9.57 kB
import type {} from '../../typedef'; /** * @description Resolve an icon spec to an HTML string. Accepts a key from `$.icons`, * a raw HTML snippet (anything starting with `<`), or empty. * @param {string} icon * @param {Object} icons * @returns {string} */ export function resolveIconHTML(icon: string, icons: any): string; /** * @description Build the canonical command-menu row HTML. Single source of truth for the * BlockHandle action menu and the SlashCommand menu, so they look identical. * @param {string} label * @param {string} iconHTML * @returns {string} */ export function buildRowHTML(label: string, iconHTML: string): string; export default CommandMenu; export type CommandMenuItem = { /** * - Optional identifier. */ key?: string; /** * - Display label. */ title: string; /** * - `$.icons` key or raw HTML snippet. */ icon?: string; /** * - Extra search terms (used by the filter). */ keywords?: string[]; /** * - Custom callback. The second * argument is the host-supplied context (e.g. `{block}` for BlockHandle, `{triggerChar, query}` for SlashCommand). */ action: (arg0: SunEditor.Deps, arg1: any) => void | Promise<void>; }; export type SubmenuChild = { /** * - Owning plugin key. */ pluginName: string; /** * - The original toolbar dropdown button element. Passed to `plugin.action(element)` on click. */ element: HTMLElement; }; export type ResolvedItem = { kind: 'custom' | 'plugin' | 'submenu' | 'dropdownFree'; title: string; iconHTML: string; /** * - Lower-cased haystack for substring filtering. */ search: string; raw?: CommandMenuItem; /** * - Plugin key. */ name?: string; /** * - Plugin type (`'modal'`, `'command'`, etc.). */ type?: string; command?: string; /** * - For `kind: 'submenu'` — clickable child rows (one per dropdown item). */ children?: SubmenuChild[]; /** * - For `kind: 'submenu'` — HTML for each child row. */ childMenus?: string[]; }; export type CommandMenuParams = { /** * - Raw menu entries. */ items: Array<string | CommandMenuItem>; /** * Caller-provided plugin/button resolver. Inject `ResolveButton` from `core/section/constructor`. * Injected (not imported) because this module lives under `src/modules/` and cannot import from `src/core/*`. */ resolveButton: ( arg0: string, arg1: any, arg2: any, arg3: any, arg4: any, ) => { title: string; icon: string; type: string; command: string; } | null; /** * - Base SelectMenu params (`position`, `minWidth`, `keydownTarget`, etc.). */ selectMenuParams: any; /** * - Optional renderer * applied to custom (object) items only. Plugin-string items always render with `buildRowHTML`. */ renderCustomItem?: ( arg0: CommandMenuItem, arg1: { icons: any; }, ) => string; }; /** * @typedef {Object} CommandMenuItem * @property {string} [key] - Optional identifier. * @property {string} title - Display label. * @property {string} [icon] - `$.icons` key or raw HTML snippet. * @property {string[]} [keywords] - Extra search terms (used by the filter). * @property {function(SunEditor.Deps, *): void | Promise<void>} action - Custom callback. The second * argument is the host-supplied context (e.g. `{block}` for BlockHandle, `{triggerChar, query}` for SlashCommand). */ /** * @typedef {Object} SubmenuChild * @property {string} pluginName - Owning plugin key. * @property {HTMLElement} element - The original toolbar dropdown button element. Passed to `plugin.action(element)` on click. */ /** * @typedef {Object} ResolvedItem * @property {'custom'|'plugin'|'submenu'|'dropdownFree'} kind * @property {string} title * @property {string} iconHTML * @property {string} search - Lower-cased haystack for substring filtering. * @property {CommandMenuItem} [raw] * @property {string} [name] - Plugin key. * @property {string} [type] - Plugin type (`'modal'`, `'command'`, etc.). * @property {string} [command] * @property {SubmenuChild[]} [children] - For `kind: 'submenu'` — clickable child rows (one per dropdown item). * @property {string[]} [childMenus] - For `kind: 'submenu'` — HTML for each child row. */ /** * @typedef {Object} CommandMenuParams * @property {Array<string | CommandMenuItem>} items - Raw menu entries. * @property {function(string, Object, *, Object, Object): ({title: string, icon: string, type: string, command: string} | null)} resolveButton * Caller-provided plugin/button resolver. Inject `ResolveButton` from `core/section/constructor`. * Injected (not imported) because this module lives under `src/modules/` and cannot import from `src/core/*`. * @property {Object} selectMenuParams - Base SelectMenu params (`position`, `minWidth`, `keydownTarget`, etc.). * @property {function(CommandMenuItem, { icons: Object }): string} [renderCustomItem] - Optional renderer * applied to custom (object) items only. Plugin-string items always render with `buildRowHTML`. */ /** * @class * @description Shared command-menu module used by BlockHandle and SlashCommand. * - Owns the underlying `SelectMenu`, renders rows with the canonical BlockHandle row HTML. * - Supports four item kinds: * - `'custom'` — user-defined `{title, icon?, action}` invoked with `($, hostContext)`. * - `'plugin'` — plain plugin (modal/browser/command/popup) dispatched via `plugin.open/show/action`. * - `'submenu'` — dropdown plugin auto-expanded inline (children come from `$.menu.itemsMap`). * - `'dropdownFree'` — dropdown-free plugin (e.g. `fontColor`, `table`) shown with a submenu arrow * and an attached hover flyout that reuses the plugin's toolbar dropdown DOM. * - Handles blur prevention on mousedown, hover flyout lifecycle, and click-to-toggle for dropdown-free. * * Host responsibilities (kept outside this module): * - Pre-dispatch side effects (BlockHandle: `expandRangeToFullLines`; SlashCommand: delete trigger text). * - Anchor element selection (BlockHandle anchors to the drag button; SlashCommand to a Controller wrapper). * - Context object for custom-item actions. */ declare class CommandMenu { /** * @constructor * @param {*} _host - Reserved for future host-aware behavior (kept for API symmetry with `Modal`/`Controller`). * @param {SunEditor.Deps} $ - Deps bag. * @param {CommandMenuParams} params */ constructor(_host: any, $: SunEditor.Deps, params: CommandMenuParams); /** @type {SelectMenu} */ selectMenu: SelectMenu; /** * @description Bind the menu to a reference element and register the click handler. * @param {HTMLElement} referElement * @param {(item: ResolvedItem|null) => void} onSelect - Called with the resolved item picked by the user. * Hosts run their pre-dispatch hook here (delete trigger, etc.) and then call `dispatch(item, ctx)`. * @param {{ class?: string, style?: string }} [attr] */ attach( referElement: HTMLElement, onSelect: (item: ResolvedItem | null) => void, attr?: { class?: string; style?: string; }, ): void; /** * @description Replace the items list (e.g. when host options change). Invalidates the resolved cache. * @param {Array<string | CommandMenuItem>} items */ setItems(items: Array<string | CommandMenuItem>): void; /** * @description Lazily normalize raw items. Lazy because plugin instances (`$.plugins`) may not * be available during the host's constructor. * @returns {ResolvedItem[]} */ getItems(): ResolvedItem[]; /** * @description Case-insensitive substring filter on `title + keywords + plugin name`. * Empty query returns all items (up to `limit`). * @param {string} query * @param {number} [limit=Infinity] * @returns {ResolvedItem[]} */ filter(query: string, limit?: number): ResolvedItem[]; /** * @description Build row HTML for a list of resolved items. * @param {ResolvedItem[]} items * @returns {string[]} */ renderRows(items: ResolvedItem[]): string[]; /** * @description Populate the SelectMenu rows. * @param {ResolvedItem[]} items */ createRows(items: ResolvedItem[]): void; /** * @description Open the SelectMenu. Lazily (re-)registers menu rows into * `commandDispatcher.targets` so `selectionState.update` paints the `active` class on them through * @param {string} [position] */ open(position?: string): void; /** * @description Close the SelectMenu. Also unregisters menu rows from `commandDispatcher.targets` */ close(): void; /** * @description Whether a sub-panel (native submenu or dropdown-free flyout) is currently open. * Lets an owning Controller keep the menu open on ESC and close only the sub-panel. * @returns {boolean} */ hasOpenSubPanel(): boolean; /** * @description Highlight a row. * @param {number} index */ setItem(index: number): void; /** * @description Soft-hide / soft-show without changing open state. Pass-through. * @param {boolean} hidden */ setHidden(hidden: boolean): void; get isOpen(): boolean; /** * @description Dispatch a resolved item. For custom items, calls `raw.action($, ctx)`. For plugin * items, routes to `plugin.open/show/action` or `commandDispatcher.run` (built-ins). For dropdown-free * items, toggles the hover flyout * @param {ResolvedItem | SubmenuChild | null} item * @param {*} [ctx] - Context passed to custom-item `action` (host-specific shape). * @returns {boolean} `true` if a plugin was dispatched */ dispatch(item: ResolvedItem | SubmenuChild | null, ctx?: any): boolean; #private; } import SelectMenu from './SelectMenu.js';