Hooks and components for consuming remirror with your fave framework React.
Overall
score
36%
Evaluation — 36%
↑ 1.09xAgent success when using this tile
Extended hooks for sophisticated editor interactions including positioning, suggestions, keyboard handling, and event management.
Hooks for managing floating UI elements and positioning.
/**
* Hook for managing a single positioned element with floating UI
* @param options - Positioning configuration options
* @returns Positioning state and control functions
*/
function usePositioner(options?: PositionerOptions): UsePositionerReturn;
interface UsePositionerReturn {
/** Whether the positioner is currently active */
active: boolean;
/** Current position coordinates */
position: { x: number; y: number };
/** Show the positioned element */
show: () => void;
/** Hide the positioned element */
hide: () => void;
/** Toggle visibility */
toggle: () => void;
/** Update position */
update: () => void;
}
interface PositionerOptions {
/** Placement preference */
placement?: Placement;
/** Offset from reference element */
offset?: number;
/** Whether to flip when space is limited */
flip?: boolean;
}
/**
* Hook for managing multiple positioned elements
* @returns Multi-positioner management interface
*/
function useMultiPositioner(): MultiPositionerReturn;
interface MultiPositionerReturn {
/** Create a new positioner */
create: (id: string, options?: PositionerOptions) => UsePositionerReturn;
/** Remove a positioner */
remove: (id: string) => void;
/** Get a specific positioner */
get: (id: string) => UsePositionerReturn | undefined;
/** Hide all positioners */
hideAll: () => void;
}Usage Example:
import React, { useState } from 'react';
import { usePositioner } from '@remirror/react';
function FloatingMenu() {
const [visible, setVisible] = useState(false);
const positioner = usePositioner({
placement: 'top',
offset: 10,
});
return (
<div>
<button
onClick={() => {
setVisible(!visible);
positioner.toggle();
}}
>
Toggle Menu
</button>
{positioner.active && (
<div style={{
position: 'absolute',
left: positioner.position.x,
top: positioner.position.y,
}}>
Floating menu content
</div>
)}
</div>
);
}Hooks for implementing suggestion systems like mentions, emoji, and custom suggestions.
/**
* General-purpose suggestion hook for autocomplete functionality
* @param options - Suggestion configuration
* @returns Suggestion state and control functions
*/
function useSuggest<T = any>(options: SuggestOptions<T>): SuggestReturn<T>;
interface SuggestOptions<T> {
/** Trigger character(s) */
char: string | string[];
/** Function to fetch suggestions */
items: (query: string) => T[] | Promise<T[]>;
/** Function to render each suggestion */
render: (item: T) => React.ReactNode;
/** Function to handle selection */
onSelect: (item: T) => void;
}
interface SuggestReturn<T> {
/** Current suggestions */
items: T[];
/** Currently highlighted index */
index: number;
/** Whether suggestions are active */
active: boolean;
/** Current query string */
query: string;
/** Select highlighted item */
selectHighlighted: () => void;
/** Navigate suggestions */
next: () => void;
previous: () => void;
}
/**
* Hook for mention functionality
* @param options - Mention configuration
* @returns Mention state and handlers
*/
function useMention(options?: MentionOptions): MentionState;
interface MentionOptions {
/** Mention trigger character */
char?: string;
/** Function to fetch mention suggestions */
items?: (query: string) => MentionItem[] | Promise<MentionItem[]>;
/** Custom mention matcher */
matcher?: RegExp;
}
interface MentionState {
/** Current mention query */
query: string;
/** Available mention items */
items: MentionItem[];
/** Currently active mention */
active: boolean;
/** Highlighted item index */
index: number;
/** Insert a mention */
insertMention: (item: MentionItem) => void;
}
interface MentionItem {
/** Unique identifier */
id: string;
/** Display label */
label: string;
/** Optional avatar URL */
avatar?: string;
/** Additional data */
data?: any;
}
/**
* Hook for atomic mention handling (indivisible mentions)
* @param options - Atomic mention options
* @returns Atomic mention interface
*/
function useMentionAtom(options?: MentionAtomOptions): MentionAtomState;
interface MentionAtomOptions {
/** Mention character trigger */
char?: string;
/** Mention data provider */
items?: (query: string) => MentionItem[] | Promise<MentionItem[]>;
}
interface MentionAtomState {
/** Create new mention */
createMention: (item: MentionItem) => void;
/** Update existing mention */
updateMention: (id: string, data: Partial<MentionItem>) => void;
/** Remove mention */
removeMention: (id: string) => void;
/** Get all mentions in document */
getMentions: () => MentionItem[];
}
/**
* Hook for emoji suggestion functionality
* @param options - Emoji configuration
* @returns Emoji suggestion state
*/
function useEmoji(options?: EmojiOptions): EmojiState;
interface EmojiOptions {
/** Emoji trigger character */
char?: string;
/** Custom emoji dataset */
emojiData?: EmojiData[];
}
interface EmojiState {
/** Current emoji query */
query: string;
/** Matching emoji results */
results: EmojiData[];
/** Insert selected emoji */
insertEmoji: (emoji: EmojiData) => void;
/** Whether emoji picker is active */
active: boolean;
}
interface EmojiData {
/** Emoji unicode character */
emoji: string;
/** Emoji name/description */
name: string;
/** Category */
category: string;
/** Keywords for searching */
keywords: string[];
}Usage Example:
import React from 'react';
import { useMention } from '@remirror/react';
function MentionSupport() {
const mention = useMention({
char: '@',
items: async (query) => {
// Fetch users matching query
const users = await fetchUsers(query);
return users.map(user => ({
id: user.id,
label: user.name,
avatar: user.avatar,
}));
},
});
return mention.active ? (
<div className="mention-popup">
{mention.items.map((item, index) => (
<div
key={item.id}
className={index === mention.index ? 'highlighted' : ''}
onClick={() => mention.insertMention(item)}
>
{item.avatar && <img src={item.avatar} alt="" />}
{item.label}
</div>
))}
</div>
) : null;
}Hooks for managing keyboard shortcuts and navigation.
/**
* Hook for binding a single keymap
* @param keymap - Key binding configuration
*/
function useKeymap(keymap: ProsemirrorKeyBindings): void;
/**
* Hook for binding multiple keymaps
* @param keymaps - Array of key binding configurations
*/
function useKeymaps(keymaps: ProsemirrorKeyBindings[]): void;
interface ProsemirrorKeyBindings {
[key: string]: (state: EditorState, dispatch?: any) => boolean;
}
/**
* Hook for keyboard navigation in menus and lists
* @param options - Navigation configuration
* @returns Navigation state and handlers
*/
function useMenuNavigation(options: MenuNavigationOptions): MenuNavigationReturn;
interface MenuNavigationOptions {
/** Total number of items */
items: number;
/** Initial selected index */
initialIndex?: number;
/** Whether to loop at ends */
loop?: boolean;
/** Custom key mappings */
keys?: {
up?: string;
down?: string;
select?: string;
escape?: string;
};
}
interface MenuNavigationReturn {
/** Currently selected index */
index: number;
/** Move to next item */
next: () => void;
/** Move to previous item */
previous: () => void;
/** Select current item */
select: () => void;
/** Reset to initial state */
reset: () => void;
/** Set specific index */
setIndex: (index: number) => void;
}Usage Example:
import React, { useEffect } from 'react';
import { useKeymap, useMenuNavigation } from '@remirror/react';
function CustomDropdown({ items, onSelect }) {
const navigation = useMenuNavigation({
items: items.length,
loop: true,
});
useKeymap({
'ArrowUp': () => {
navigation.previous();
return true;
},
'ArrowDown': () => {
navigation.next();
return true;
},
'Enter': () => {
onSelect(items[navigation.index]);
return true;
},
});
return (
<div className="dropdown">
{items.map((item, index) => (
<div
key={index}
className={index === navigation.index ? 'selected' : ''}
onClick={() => onSelect(item)}
>
{item.label}
</div>
))}
</div>
);
}Hooks for handling various editor events and interactions.
/**
* Hook for handling general editor events
* @param event - Event name to listen for
* @param handler - Event handler function
* @param options - Event options
*/
function useEditorEvent<T = any>(
event: string,
handler: (params: T) => void,
options?: EventOptions
): void;
interface EventOptions {
/** Event priority */
priority?: number;
/** Whether to capture the event */
capture?: boolean;
/** Event filter function */
filter?: (params: any) => boolean;
}
/**
* Hook for managing editor focus state
* @param options - Focus configuration
* @returns Focus state and control functions
*/
function useEditorFocus(options?: FocusOptions): EditorFocusReturn;
interface FocusOptions {
/** Auto focus on mount */
autoFocus?: boolean;
/** Focus delay in milliseconds */
delay?: number;
/** Callback when focus changes */
onFocusChange?: (focused: boolean) => void;
}
interface EditorFocusReturn {
/** Whether editor is currently focused */
focused: boolean;
/** Focus the editor */
focus: () => void;
/** Blur the editor */
blur: () => void;
/** Toggle focus state */
toggle: () => void;
}
/**
* Hook for handling hover interactions
* @param options - Hover configuration
* @returns Hover state and handlers
*/
function useHover(options?: HoverOptions): HoverReturn;
interface HoverOptions {
/** Hover delay in milliseconds */
delay?: number;
/** Element selector to monitor */
selector?: string;
/** Callback when hover state changes */
onHoverChange?: (hovering: boolean) => void;
}
interface HoverReturn {
/** Whether currently hovering */
hovering: boolean;
/** Hover event handlers */
handlers: {
onMouseEnter: () => void;
onMouseLeave: () => void;
};
}
/**
* Hook for managing editor history (undo/redo)
* @returns History state and control functions
*/
function useHistory(): HistoryReturn;
interface HistoryReturn {
/** Whether undo is available */
canUndo: boolean;
/** Whether redo is available */
canRedo: boolean;
/** Perform undo */
undo: () => void;
/** Perform redo */
redo: () => void;
/** Clear history */
clearHistory: () => void;
}Usage Example:
import React from 'react';
import { useEditorFocus, useHistory, useHover } from '@remirror/react';
function EditorControls() {
const { focused, focus, blur } = useEditorFocus();
const { canUndo, canRedo, undo, redo } = useHistory();
const { hovering, handlers } = useHover({
delay: 200,
});
return (
<div className="editor-controls" {...handlers}>
<div>
Editor focused: {focused ? 'Yes' : 'No'}
<button onClick={focused ? blur : focus}>
{focused ? 'Blur' : 'Focus'}
</button>
</div>
<div>
<button onClick={undo} disabled={!canUndo}>
Undo
</button>
<button onClick={redo} disabled={!canRedo}>
Redo
</button>
</div>
{hovering && <div>Hovering over controls</div>}
</div>
);
}Additional utility hooks for common operations.
/**
* Calculate index from arrow key navigation
* @param current - Current index
* @param total - Total items
* @param direction - Navigation direction
* @param loop - Whether to loop at boundaries
* @returns New index after navigation
*/
function indexFromArrowPress(
current: number,
total: number,
direction: 'up' | 'down',
loop?: boolean
): number;type Placement =
| 'top'
| 'top-start'
| 'top-end'
| 'bottom'
| 'bottom-start'
| 'bottom-end'
| 'left'
| 'left-start'
| 'left-end'
| 'right'
| 'right-start'
| 'right-end';
interface Position {
x: number;
y: number;
}
interface Bounds {
top: number;
left: number;
bottom: number;
right: number;
width: number;
height: number;
}docs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10