Hooks and components for consuming remirror with your fave framework React.
Overall
score
36%
Evaluation — 36%
↑ 1.09xAgent success when using this tile
Extensions and utilities for integrating React components as ProseMirror node views and managing the portal system.
Main extension for integrating React components as node views in the editor.
/**
* Extension for integrating React components as ProseMirror node views
*/
class ReactComponentExtension extends Extension<ReactComponentOptions> {
/** Extension name */
static readonly name = 'reactComponent';
/** Create node view for React components */
createNodeViews(): NodeViewMethod | {};
/** Create plugin for managing React components */
createPlugin(): ProsemirrorPlugin;
}
interface ReactComponentOptions {
/** Default component environment */
defaultEnvironment?: ReactComponentEnvironment;
/** Whether to use strict mode */
strict?: boolean;
/** Custom portal container */
portalContainer?: HTMLElement;
}
type ReactComponentEnvironment = 'ssr' | 'dom' | 'both';Usage Example:
import React from 'react';
import { ReactComponentExtension, useRemirror } from '@remirror/react';
// Custom node component
function CustomNode({ node, updateAttributes }) {
return (
<div className="custom-node">
<h3>{node.attrs.title}</h3>
<button onClick={() => updateAttributes({ title: 'Updated!' })}>
Update Title
</button>
</div>
);
}
function MyEditor() {
const { manager, state } = useRemirror({
extensions: () => [
new ReactComponentExtension({
defaultEnvironment: 'dom',
}),
// Your other extensions that use React components
],
});
return <Remirror manager={manager} initialContent={state} />;
}Advanced React portal management for rendering components in specific locations within the editor.
/**
* Container for managing React portals within the editor
*/
class PortalContainer {
/** Render a React component in a portal */
render(Component: ComponentType, props?: any, key?: string): string;
/** Remove a portal by key */
remove(key: string): void;
/** Update a portal with new props */
update(key: string, props: any): void;
/** Clear all portals */
clear(): void;
/** Get all mounted portals */
getPortals(): PortalMap;
}
/**
* Component that renders all active portals into the DOM
*/
interface RemirrorPortals extends React.Component<RemirrorPortalsProps> {}
interface RemirrorPortalsProps {
/** Portal container instance */
container?: PortalContainer;
/** Custom render function */
renderPortal?: (portal: MountedPortal) => React.ReactNode;
}
/**
* Hook to subscribe to portal container updates
* @param container - Portal container to subscribe to
* @returns Current portal map and update trigger
*/
function usePortals(container?: PortalContainer): {
portals: PortalMap;
updateCount: number;
};Usage Example:
import React, { useEffect } from 'react';
import {
usePortalContainer,
RemirrorPortals,
useRemirror,
ReactComponentExtension
} from '@remirror/react';
function FloatingComponent({ position }: { position: { x: number; y: number } }) {
return (
<div
style={{
position: 'absolute',
left: position.x,
top: position.y,
background: 'white',
border: '1px solid #ccc',
padding: '8px',
}}
>
Floating content!
</div>
);
}
function EditorWithPortals() {
const { manager, state } = useRemirror({
extensions: () => [new ReactComponentExtension()],
});
const portalContainer = usePortalContainer();
useEffect(() => {
// Render a floating component
const key = portalContainer.render(FloatingComponent, {
position: { x: 100, y: 100 }
});
// Clean up on unmount
return () => portalContainer.remove(key);
}, [portalContainer]);
return (
<Remirror manager={manager} initialContent={state}>
<RemirrorPortals />
</Remirror>
);
}Utilities and interfaces for creating React-based node views.
/**
* Props passed to React node view components
*/
interface NodeViewComponentProps {
/** The ProseMirror node */
node: ProsemirrorNode;
/** Node view instance */
view: EditorView;
/** Function to get current position */
getPos: () => number;
/** Node decorations */
decorations: readonly Decoration[];
/** Whether node is selected */
selected: boolean;
/** Update node attributes */
updateAttributes: (attrs: ProsemirrorAttributes) => void;
/** Forward ref to DOM element */
forwardRef?: React.Ref<HTMLElement>;
}
/**
* Properties for creating node views with React components
*/
interface CreateNodeViewProps {
/** Node name */
name: string;
/** React component to render */
component: ComponentType<NodeViewComponentProps>;
/** Environment where component should render */
environment?: ReactComponentEnvironment;
/** Whether content is editable */
contentEditable?: boolean;
/** Custom wrapper element */
wrapper?: string;
}/**
* A mounted portal with render props and key
*/
interface MountedPortal {
/** Unique portal key */
key: string;
/** Component to render */
Component: ComponentType;
/** Props to pass to component */
props: any;
/** Portal container element */
container: HTMLElement;
}
/**
* Array of portal container/component tuples
*/
type PortalList = Array<[HTMLElement, ComponentType]>;
/**
* Map of HTML elements to mounted portals
*/
type PortalMap = Map<HTMLElement, MountedPortal[]>;
/**
* Props containing Component to render
*/
interface RenderProps {
/** Component to render in portal */
Component: ComponentType;
/** Props to pass to component */
props?: any;
}
/**
* Props for individual render methods
*/
interface SingleRenderMethodProps extends RenderProps {
/** Unique key for the render */
key?: string;
}/**
* Create a node extension that uses React components
* @param config - Configuration for the React node extension
* @returns Configured node extension
*/
function createReactNodeExtension<T extends ProsemirrorAttributes = {}>(
config: ReactNodeExtensionConfig<T>
): NodeExtension<ReactNodeOptions<T>>;
interface ReactNodeExtensionConfig<T extends ProsemirrorAttributes = {}> {
/** Extension name */
name: string;
/** React component for the node */
component: ComponentType<NodeViewComponentProps & { attrs: T }>;
/** Node schema */
schema: NodeSpec;
/** Default attributes */
defaults?: T;
/** Environment configuration */
environment?: ReactComponentEnvironment;
}
interface ReactNodeOptions<T extends ProsemirrorAttributes = {}>
extends ReactComponentOptions {
/** Node-specific options */
nodeOptions?: {
/** Default attributes */
defaults?: T;
/** Custom node view factory */
createNodeView?: (props: CreateNodeViewProps) => NodeView;
};
}Usage Example:
import React from 'react';
import { createReactNodeExtension, NodeViewComponentProps } from '@remirror/react';
// Define your React component
function ImageNode({ node, updateAttributes }: NodeViewComponentProps) {
const { src, alt, width } = node.attrs;
return (
<div className="image-node">
<img
src={src}
alt={alt}
width={width}
style={{ maxWidth: '100%' }}
/>
<div className="image-controls">
<input
type="range"
min="100"
max="800"
value={width}
onChange={(e) => updateAttributes({ width: parseInt(e.target.value) })}
/>
<span>{width}px</span>
</div>
</div>
);
}
// Create the extension
const ImageExtension = createReactNodeExtension({
name: 'image',
component: ImageNode,
schema: {
attrs: {
src: { default: null },
alt: { default: '' },
width: { default: 400 },
},
parseDOM: [{
tag: 'img',
getAttrs: (element) => ({
src: element.getAttribute('src'),
alt: element.getAttribute('alt'),
width: parseInt(element.getAttribute('width') || '400'),
}),
}],
toDOM: (node) => ['img', {
src: node.attrs.src,
alt: node.attrs.alt,
width: node.attrs.width,
}],
},
defaults: {
src: '',
alt: '',
width: 400,
},
});/**
* Utilities for handling different rendering environments
*/
interface EnvironmentHandler {
/** Check if running in browser */
isBrowser: () => boolean;
/** Check if running in Node.js/SSR */
isServer: () => boolean;
/** Get appropriate renderer for environment */
getRenderer: (environment: ReactComponentEnvironment) => ComponentType;
/** Handle environment-specific initialization */
initialize: (environment: ReactComponentEnvironment) => void;
}
/**
* HOC for environment-aware component rendering
* @param Component - Component to wrap
* @param environment - Target environment
* @returns Environment-aware component
*/
function withEnvironment<P extends {}>(
Component: ComponentType<P>,
environment: ReactComponentEnvironment
): ComponentType<P>;/**
* Server-side rendering utilities for React components
*/
interface SSRRenderer {
/** Render component to string for SSR */
renderToString: (component: ReactElement) => string;
/** Render component to static markup */
renderToStaticMarkup: (component: ReactElement) => string;
/** Hydrate server-rendered content */
hydrate: (component: ReactElement, container: HTMLElement) => void;
}
/**
* Configuration for SSR-compatible node views
*/
interface SSRNodeViewConfig {
/** Whether to render on server */
serverRender: boolean;
/** Whether to hydrate on client */
clientHydrate: boolean;
/** Fallback content for non-JS environments */
fallback?: string | ComponentType;
}docs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10