Skip to main content

Plugin

The main interface for creating React Grab plugins. Plugins can extend functionality, customize appearance, add actions, and hook into lifecycle events.

Properties

name
string
required
Unique identifier for the plugin. Used for registration and unregistration.
theme
DeepPartial<Theme>
Theme customizations applied when the plugin is active. See Theme for available options.
options
SettableOptions
Configuration options that modify React Grab behavior. See Options.
actions
PluginAction[]
Custom actions to add to context menus or toolbar. Array of ContextMenuAction or ToolbarMenuAction.
hooks
PluginHooks
Lifecycle hooks and event handlers. See PluginHooks below.
setup
(api: ReactGrabAPI, hooks: ActionContextHooks) => PluginConfig | void
Optional setup function called when the plugin is registered. Receives the React Grab API and action hooks. Can return a PluginConfig object for dynamic configuration.

PluginConfig

Configuration object returned by the plugin’s setup function or used for runtime configuration.

Properties

theme
DeepPartial<Theme>
Theme customizations to apply.
options
SettableOptions
Runtime options to apply.
actions
PluginAction[]
Actions to register.
hooks
PluginHooks
Event hooks to register.
cleanup
() => void
Optional cleanup function called when the plugin is unregistered or when React Grab is disposed.

PluginHooks

Lifecycle hooks and event handlers for plugins. All hooks are optional.

Activation Hooks

onActivate
() => void
Called when React Grab is activated (enters selection mode).
onDeactivate
() => void
Called when React Grab is deactivated (exits selection mode).
cancelPendingToolbarActions
() => void
Called to cancel any pending toolbar actions. Useful for cleanup.

Element Interaction Hooks

onElementHover
(element: Element) => void
Called when the user hovers over an element during selection.
onElementSelect
(element: Element) => boolean | void | Promise<boolean>
Called when an element is selected. Return false to prevent the default selection behavior.
onDragStart
(startX: number, startY: number) => void
Called when the user starts dragging to select multiple elements. Receives starting coordinates.
onDragEnd
(elements: Element[], bounds: DragRect) => void
Called when drag selection ends. Receives selected elements and drag bounds.

Copy Hooks

onBeforeCopy
(elements: Element[]) => void | Promise<void>
Called before copying elements to clipboard. Use for validation or preparation.
transformCopyContent
(content: string, elements: Element[]) => string | Promise<string>
Transform the content before copying to clipboard. Return modified content string.
onAfterCopy
(elements: Element[], success: boolean) => void
Called after copy operation completes, regardless of success.
onCopySuccess
(elements: Element[], content: string) => void
Called when copy succeeds. Receives elements and copied content.
onCopyError
(error: Error) => void
Called when copy fails. Receives the error.

State & UI Hooks

onStateChange
(state: ReactGrabState) => void
Called whenever React Grab state changes. Receives the new state.
onPromptModeChange
(isPromptMode: boolean, context: PromptModeContext) => void
Called when prompt mode is toggled. Receives mode state and context with cursor position and target element.
onSelectionBox
(visible: boolean, bounds: OverlayBounds | null, element: Element | null) => void
Called when selection box visibility or bounds change.
onDragBox
(visible: boolean, bounds: OverlayBounds | null) => void
Called when drag box visibility or bounds change.
onGrabbedBox
(bounds: OverlayBounds, element: Element) => void
Called when a grabbed box (success flash) is shown.
onElementLabel
(visible: boolean, variant: ElementLabelVariant, context: ElementLabelContext) => void
Called when element label visibility or content changes. Variant can be “hover”, “processing”, or “success”.
onCrosshair
(visible: boolean, context: CrosshairContext) => void
Called when crosshair visibility or position changes.
onContextMenu
(element: Element, position: { x: number; y: number }) => void
Called when context menu is opened. Receives target element and menu position.

File & Navigation Hooks

onOpenFile
(filePath: string, lineNumber?: number) => boolean | void
Called when a file should be opened in the editor. Return false to prevent default behavior.
transformOpenFileUrl
(url: string, filePath: string, lineNumber?: number) => string
Transform the URL used for opening files. Return modified URL.

Transform Hooks

transformHtmlContent
(html: string, elements: Element[]) => string | Promise<string>
Transform HTML content before it’s used. Return modified HTML string.
transformAgentContext
(context: AgentContext, elements: Element[]) => AgentContext | Promise<AgentContext>
Transform agent context before sending to agent provider. Return modified context.
transformActionContext
(context: ActionContext) => ActionContext
Transform action context before actions execute. Return modified context.
transformSnippet
(snippet: string, element: Element) => string | Promise<string>
Transform code snippet for an element. Return modified snippet.

Usage

Basic Plugin

import { Plugin } from 'react-grab';

const myPlugin: Plugin = {
  name: 'my-plugin',
  theme: {
    hue: 200
  },
  hooks: {
    onActivate: () => {
      console.log('React Grab activated');
    },
    onCopySuccess: (elements, content) => {
      console.log(`Copied ${elements.length} elements`);
    }
  }
};

Plugin with Setup Function

const analyticsPlugin: Plugin = {
  name: 'analytics',
  setup: (api, hooks) => {
    let copyCount = 0;
    
    return {
      hooks: {
        onCopySuccess: (elements) => {
          copyCount++;
          console.log(`Total copies: ${copyCount}`);
        }
      },
      cleanup: () => {
        console.log(`Plugin cleanup - ${copyCount} copies made`);
      }
    };
  }
};

Plugin with Transform Hooks

const formatterPlugin: Plugin = {
  name: 'formatter',
  hooks: {
    transformCopyContent: async (content, elements) => {
      // Add custom formatting
      const formatted = await prettify(content);
      return `/* Grabbed ${elements.length} elements */\n${formatted}`;
    },
    transformSnippet: (snippet, element) => {
      // Add metadata comment
      const tag = element.tagName.toLowerCase();
      return `/* <${tag}> */\n${snippet}`;
    }
  }
};

Plugin Registration

import { useReactGrab } from 'react-grab';

function App() {
  const reactGrab = useReactGrab();
  
  useEffect(() => {
    // Register plugin
    reactGrab.registerPlugin(myPlugin);
    
    // Cleanup on unmount
    return () => {
      reactGrab.unregisterPlugin('my-plugin');
    };
  }, []);
  
  return <div>{/* Your app */}</div>;
}

Type Definitions

export interface Plugin {
  name: string;
  theme?: DeepPartial<Theme>;
  options?: SettableOptions;
  actions?: PluginAction[];
  hooks?: PluginHooks;
  setup?: (api: ReactGrabAPI, hooks: ActionContextHooks) => PluginConfig | void;
}

export interface PluginConfig {
  theme?: DeepPartial<Theme>;
  options?: SettableOptions;
  actions?: PluginAction[];
  hooks?: PluginHooks;
  cleanup?: () => void;
}

export interface PluginHooks {
  onActivate?: () => void;
  onDeactivate?: () => void;
  cancelPendingToolbarActions?: () => void;
  onElementHover?: (element: Element) => void;
  onElementSelect?: (element: Element) => boolean | void | Promise<boolean>;
  onDragStart?: (startX: number, startY: number) => void;
  onDragEnd?: (elements: Element[], bounds: DragRect) => void;
  onBeforeCopy?: (elements: Element[]) => void | Promise<void>;
  transformCopyContent?: (content: string, elements: Element[]) => string | Promise<string>;
  onAfterCopy?: (elements: Element[], success: boolean) => void;
  onCopySuccess?: (elements: Element[], content: string) => void;
  onCopyError?: (error: Error) => void;
  onStateChange?: (state: ReactGrabState) => void;
  onPromptModeChange?: (isPromptMode: boolean, context: PromptModeContext) => void;
  onSelectionBox?: (visible: boolean, bounds: OverlayBounds | null, element: Element | null) => void;
  onDragBox?: (visible: boolean, bounds: OverlayBounds | null) => void;
  onGrabbedBox?: (bounds: OverlayBounds, element: Element) => void;
  onElementLabel?: (visible: boolean, variant: ElementLabelVariant, context: ElementLabelContext) => void;
  onCrosshair?: (visible: boolean, context: CrosshairContext) => void;
  onContextMenu?: (element: Element, position: { x: number; y: number }) => void;
  onOpenFile?: (filePath: string, lineNumber?: number) => boolean | void;
  transformHtmlContent?: (html: string, elements: Element[]) => string | Promise<string>;
  transformAgentContext?: (context: AgentContext, elements: Element[]) => AgentContext | Promise<AgentContext>;
  transformActionContext?: (context: ActionContext) => ActionContext;
  transformOpenFileUrl?: (url: string, filePath: string, lineNumber?: number) => string;
  transformSnippet?: (snippet: string, element: Element) => string | Promise<string>;
}

See Also

  • Actions - Define custom actions for plugins
  • Agent - Configure AI agent providers
  • Theme - Theme customization options

Build docs developers (and LLMs) love