@atlaskit/editor-plugin-block-menu
Version:
BlockMenu plugin for @atlaskit/editor-core
126 lines (125 loc) • 4.96 kB
TypeScript
import type { EditorCommand, NextEditorPlugin, OptionalPlugin } from '@atlaskit/editor-common/types';
import type { AnalyticsPlugin } from '@atlaskit/editor-plugin-analytics';
import type { BlockControlsPlugin } from '@atlaskit/editor-plugin-block-controls';
import type { DecorationsPlugin } from '@atlaskit/editor-plugin-decorations';
import type { SelectionPlugin } from '@atlaskit/editor-plugin-selection';
import type { UserIntentPlugin } from '@atlaskit/editor-plugin-user-intent';
import type { NodeType } from '@atlaskit/editor-prosemirror/model';
import type { TransformNodeMetadata } from './editor-commands/types';
export declare enum FLAG_ID {
LINK_COPIED_TO_CLIPBOARD = "link-copied-to-clipboard"
}
type TransformNodeCommand = (targetType: NodeType, metadata?: TransformNodeMetadata) => EditorCommand;
export type BlockMenuPlugin = NextEditorPlugin<'blockMenu', {
actions: {
getBlockMenuComponents: () => Array<RegisterBlockMenuComponent>;
isTransformOptionDisabled: (optionNodeTypeName: string, optionNodeTypeAttrs?: Record<string, unknown>) => boolean;
registerBlockMenuComponents: (blockMenuComponents: Array<RegisterBlockMenuComponent>) => void;
};
commands: {
transformNode: TransformNodeCommand;
};
dependencies: [
OptionalPlugin<BlockControlsPlugin>,
OptionalPlugin<UserIntentPlugin>,
OptionalPlugin<SelectionPlugin>,
OptionalPlugin<DecorationsPlugin>,
OptionalPlugin<AnalyticsPlugin>
];
pluginConfiguration?: BlockMenuPluginOptions;
sharedState: BlockMenuSharedState;
}>;
export type BlockMenuPluginOptions = {
/**
* Optional hash prefix used for block-specific URL to create a deep link to specific block
* Default value from DEFAULT_BLOCK_LINK_HASH_PREFIX in @atlaskit/editor-common/block-menu
*/
blockLinkHashPrefix?: string;
/**
* Optional function to retrieve the current link path for the editor context.
* @returns The current link path as a string, or null if no path is available
*/
getLinkPath?: () => string | null;
/**
* When true, nodes maintain their standard width without negative margins
* for block menu compatibility. Used in contexts like Jira issue descriptions
* where block menu controls need consistent spacing.
* @default false
*/
useStandardNodeWidth?: boolean;
};
export type BlockMenuSharedState = {
/**
* The name of the currently selected node type that triggered the block menu
* This exposes the menuTriggerBy value from blockControls plugin
*/
currentSelectedNodeName: string | undefined;
/**
* Whether to show a flag (e.g. for copy confirmation)
*/
showFlag: FLAG_ID | false;
/**
* When true, nodes maintain their standard width without negative margins
* for block menu compatibility.
*/
useStandardNodeWidth?: boolean;
} | undefined;
type WithRank<T> = T & {
rank: number;
};
export type Parent<T> = WithRank<T>;
type ComponentType = BlockMenuSection | BlockMenuItem | BlockMenuNested;
export type ComponentTypes = Array<ComponentType>;
/**
* The relationship between BlockMenuItem, BlockMenuSection, BlockMenuNested
* BlockMenuSection can have BlockMenuItem or BlockMenuNested as children
* BlockMenuNested can have BlockMenuSection as children,
* BlockMenuNested, with BlockMenuSection and BlockMenuItem, is a nested menu
* _______________________________________
* | Block menu (no typing)
* | |BlockMenuSection
* | | |BlockMenuItem
* | | |BlockMenuNested
* | | | |BlockMenuSection
* | | | | |BlockMenuItem
*/
type BlockMenuItem = {
key: string;
type: 'block-menu-item';
};
type BlockMenuSection = {
key: string;
type: 'block-menu-section';
};
type BlockMenuNested = {
key: string;
type: 'block-menu-nested';
};
export type BlockMenuNestedComponent = (props: {
children: React.ReactNode;
}) => React.ReactNode;
export type BlockMenuSectionComponent = (props: {
children: React.ReactNode;
}) => React.ReactNode;
export type BlockMenuNestedSectionComponent = (props: {
children: React.ReactNode;
}) => React.ReactNode;
export type BlockMenuItemComponent = () => React.ReactNode;
export type RegisterBlockMenuNested = BlockMenuNested & {
component?: BlockMenuNestedComponent;
isHidden?: () => boolean;
parent: Parent<BlockMenuSection>;
};
export type RegisterBlockMenuSection = BlockMenuSection & {
component?: BlockMenuSectionComponent;
parent?: Parent<BlockMenuNested>;
rank?: number;
};
export type RegisterBlockMenuItem = BlockMenuItem & {
component?: BlockMenuItemComponent;
isHidden?: () => boolean;
parent: Parent<BlockMenuSection>;
};
export type RegisterBlockMenuComponent = RegisterBlockMenuNested | RegisterBlockMenuSection | RegisterBlockMenuItem;
export type RegisterBlockMenuComponentType = RegisterBlockMenuComponent['type'];
export {};