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.
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.
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.
Example:
const api = init();
api.toggle(); // Activates
api.toggle(); // Deactivates
Activates comment mode, which allows adding a text prompt to copied elements.
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.
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.
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
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
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`);
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
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:
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.
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>
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>
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 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
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
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
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();
});