Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/aidenybai/react-grab/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The ReactGrabAPI interface provides programmatic control over React Grab. It’s returned by the init() function and includes methods to activate/deactivate React Grab, manage state, register plugins, and more.

Type Definition

interface ReactGrabAPI {
  activate: () => void;
  deactivate: () => void;
  toggle: () => void;
  comment: () => void;
  isActive: () => boolean;
  isEnabled: () => boolean;
  setEnabled: (enabled: boolean) => void;
  getToolbarState: () => ToolbarState | null;
  setToolbarState: (state: Partial<ToolbarState>) => void;
  onToolbarStateChange: (callback: (state: ToolbarState) => void) => () => void;
  dispose: () => void;
  copyElement: (elements: Element | Element[]) => Promise<boolean>;
  getSource: (element: Element) => Promise<SourceInfo | null>;
  getStackContext: (element: Element) => Promise<string>;
  getState: () => ReactGrabState;
  setOptions: (options: SettableOptions) => void;
  registerPlugin: (plugin: Plugin) => void;
  unregisterPlugin: (name: string) => void;
  getPlugins: () => string[];
  getDisplayName: (element: Element) => string | null;
}

Methods

activate()

Activates React Grab, allowing element selection.
api.activate(): void
Example:
const api = init();
api.activate();
Notes:
  • Only activates if React Grab is currently enabled
  • Clears any pending comment mode
  • Does nothing if already active

deactivate()

Deactivates React Grab, stopping element selection.
api.deactivate(): void
Example:
const api = init();
api.deactivate();
Notes:
  • Works even if currently in a copying state
  • Cleans up all active selections and overlays
  • Restores previously focused elements

toggle()

Toggles React Grab between active and inactive states.
api.toggle(): void
Example:
const api = init();
api.toggle(); // Activates
api.toggle(); // Deactivates

comment()

Activates comment mode, which allows adding a text prompt to copied elements.
api.comment(): void
Example:
const api = init();
api.comment();
// Now when you select an element, you'll be prompted for a comment
Notes:
  • If already in comment mode and active, deactivates React Grab
  • Sets pending comment mode flag if not already active

isActive()

Checks if React Grab is currently active.
api.isActive(): boolean
Example:
const api = init();
if (api.isActive()) {
  console.log('React Grab is active');
}
Returns:
  • true if React Grab is active and element selection is enabled
  • false otherwise

isEnabled()

Checks if React Grab is enabled.
api.isEnabled(): boolean
Example:
const api = init();
if (api.isEnabled()) {
  console.log('React Grab is enabled');
}
Returns:
  • true if React Grab is enabled
  • false if disabled
Notes:
  • Enabled state is separate from active state
  • When disabled, React Grab cannot be activated

setEnabled()

Enables or disables React Grab.
api.setEnabled(enabled: boolean): void
enabled
boolean
required
Whether to enable or disable React Grab
Example:
const api = init();
api.setEnabled(false); // Disable React Grab
api.setEnabled(true);  // Enable React Grab
Notes:
  • Disabling React Grab also deactivates it if currently active
  • The enabled state persists in toolbar state

getToolbarState()

Gets the current toolbar state.
api.getToolbarState(): ToolbarState | null
Returns:
interface ToolbarState {
  edge: 'top' | 'bottom' | 'left' | 'right';
  ratio: number; // 0-1, position along the edge
  collapsed: boolean;
  enabled: boolean;
}
Example:
const api = init();
const state = api.getToolbarState();
console.log(`Toolbar is on ${state?.edge} edge`);

setToolbarState()

Updates the toolbar state.
api.setToolbarState(state: Partial<ToolbarState>): void
state
Partial<ToolbarState>
required
Partial toolbar state to update
Example:
const api = init();
api.setToolbarState({
  edge: 'top',
  collapsed: true
});
Notes:
  • Only provided properties are updated
  • Changes are saved to localStorage
  • Triggers toolbar state change callbacks

onToolbarStateChange()

Subscribes to toolbar state changes.
api.onToolbarStateChange(callback: (state: ToolbarState) => void): () => void
callback
(state: ToolbarState) => void
required
Function to call when toolbar state changes
Returns:
  • Unsubscribe function
Example:
const api = init();
const unsubscribe = api.onToolbarStateChange((state) => {
  console.log('Toolbar state changed:', state);
});

// Later: unsubscribe()

dispose()

Cleans up all React Grab resources, event listeners, and state.
api.dispose(): void
Example:
const api = init();
// ... use React Grab ...
api.dispose(); // Clean up when done
Notes:
  • Removes all event listeners
  • Clears all timers and intervals
  • Removes overlay elements from DOM
  • After calling dispose(), a new init() call will work

copyElement()

Programmatically copies one or more elements.
api.copyElement(elements: Element | Element[]): Promise<boolean>
elements
Element | Element[]
required
Element or array of elements to copy
Returns:
  • Promise<boolean> - Resolves to true if copy succeeded, false otherwise
Example:
const api = init();
const button = document.querySelector('button');
if (button) {
  const success = await api.copyElement(button);
  console.log(success ? 'Copied!' : 'Failed');
}
Example - Multiple Elements:
const api = init();
const items = Array.from(document.querySelectorAll('.item'));
const success = await api.copyElement(items);

getSource()

Gets source information for an element.
api.getSource(element: Element): Promise<SourceInfo | null>
element
Element
required
The element to get source info for
Returns:
interface SourceInfo {
  filePath: string;
  lineNumber: number | null;
  componentName: string | null;
}
Example:
const api = init();
const button = document.querySelector('button');
if (button) {
  const source = await api.getSource(button);
  if (source) {
    console.log(`Component: ${source.componentName}`);
    console.log(`File: ${source.filePath}:${source.lineNumber}`);
  }
}
Notes:
  • Returns null if source information cannot be determined
  • Requires React DevTools fiber information to be available

getStackContext()

Gets the stack context for an element.
api.getStackContext(element: Element): Promise<string>
element
Element
required
The element to get stack context for
Returns:
  • Promise<string> - A formatted string with the element’s component stack
Example:
const api = init();
const div = document.querySelector('.container');
if (div) {
  const context = await api.getStackContext(div);
  console.log(context);
  // Output: "App > Layout > Container > div"
}

getState()

Gets the current React Grab state.
api.getState(): ReactGrabState
Returns:
interface ReactGrabState {
  isActive: boolean;
  isDragging: boolean;
  isCopying: boolean;
  isPromptMode: boolean;
  isCrosshairVisible: boolean;
  isSelectionBoxVisible: boolean;
  isDragBoxVisible: boolean;
  targetElement: Element | null;
  dragBounds: DragRect | null;
  grabbedBoxes: Array<{
    id: string;
    bounds: OverlayBounds;
    createdAt: number;
  }>;
  labelInstances: Array<{
    id: string;
    status: SelectionLabelStatus;
    tagName: string;
    componentName?: string;
    createdAt: number;
  }>;
  selectionFilePath: string | null;
  toolbarState: ToolbarState | null;
}
Example:
const api = init();
const state = api.getState();
if (state.isActive && state.targetElement) {
  console.log('Currently hovering:', state.targetElement);
}

setOptions()

Updates React Grab options after initialization.
api.setOptions(options: SettableOptions): void
options
SettableOptions
required
Options to update. Same as Options but without the enabled property.
Example:
const api = init();
api.setOptions({
  activationMode: 'hold',
  keyHoldDuration: 300,
  maxContextLines: 5
});
Notes:
  • Cannot change the enabled option - use setEnabled() instead
  • Changes take effect immediately
  • Affects all registered plugins

registerPlugin()

Registers a new plugin with React Grab.
api.registerPlugin(plugin: Plugin): void
plugin
Plugin
required
The plugin to register
Example:
import { init } from 'react-grab';

const api = init();

api.registerPlugin({
  name: 'my-plugin',
  setup: (api, hooks) => {
    return {
      actions: [{
        id: 'custom-action',
        label: 'Custom Action',
        target: 'context-menu',
        onAction: (context) => {
          console.log('Custom action!', context.element);
        }
      }]
    };
  }
});
Notes:
  • Plugins can add custom actions, hooks, and theme overrides
  • See Plugin API for details

unregisterPlugin()

Unregisters a plugin by name.
api.unregisterPlugin(name: string): void
name
string
required
The name of the plugin to unregister
Example:
const api = init();
api.unregisterPlugin('my-plugin');
Notes:
  • Built-in plugins cannot be unregistered
  • Plugin cleanup methods are called automatically

getPlugins()

Gets a list of registered plugin names.
api.getPlugins(): string[]
Returns:
  • string[] - Array of plugin names
Example:
const api = init();
const plugins = api.getPlugins();
console.log('Registered plugins:', plugins);
// Output: ['copy', 'comment', 'copyHtml', 'copyStyles', 'open', 'my-plugin']

getDisplayName()

Gets the display name (component name or tag name) for an element.
api.getDisplayName(element: Element): string | null
element
Element
required
The element to get the display name for
Returns:
  • Component name if available (e.g., 'Button', 'MyComponent')
  • Tag name if no component name found (e.g., 'div', 'button')
  • null if neither can be determined
Example:
const api = init();
const button = document.querySelector('button');
if (button) {
  const name = api.getDisplayName(button);
  console.log('Display name:', name);
  // Output: "Button" or "button"
}

Usage Example

Here’s a comprehensive example using multiple API methods:
import { init } from 'react-grab';

// Initialize with custom options
const api = init({
  activationMode: 'toggle',
  maxContextLines: 5
});

// Subscribe to state changes
const unsubscribe = api.onToolbarStateChange((state) => {
  console.log('Toolbar moved to:', state.edge);
});

// Programmatically copy an element
const copyButton = async () => {
  const button = document.querySelector('.my-button');
  if (button) {
    const success = await api.copyElement(button);
    if (success) {
      const source = await api.getSource(button);
      console.log('Copied from:', source?.filePath);
    }
  }
};

// Check state
const checkState = () => {
  const state = api.getState();
  console.log('Active:', state.isActive);
  console.log('Target:', api.getDisplayName(state.targetElement));
};

// Cleanup when done
window.addEventListener('beforeunload', () => {
  unsubscribe();
  api.dispose();
});