Resizable
API reference for @platejs/resizable.
@platejs/resizable provides the headless resize wrapper, resize handle primitive,
shared resize stores, and length utilities used by Plate media components. It
owns behavior; registry components own styling.
Installation
pnpm add @platejs/resizablepnpm add @platejs/resizableOwnership
| Surface | Owner | Use |
|---|---|---|
Resizable | @platejs/resizable | Wraps a Plate element, tracks width, clamps resize values, and writes the final width to the node. |
ResizeHandle | @platejs/resizable | Primitive handle that starts mouse/touch resizing and emits ResizeEvent values. |
ResizableProvider | @platejs/resizable | Stores the active width for the current resizable subtree. |
ResizeHandleProvider | @platejs/resizable | Shares the wrapper onResize callback with nested handles. |
| Resize hooks | @platejs/resizable | Split state from DOM props for custom wrappers and handles. |
| Length utilities | @platejs/resizable | Convert and clamp static pixel widths and relative percent widths. |
Media Pattern
Wrap each resizable element with ResizableProvider. Media components use the
provider width for captions and use Resizable plus left/right handles around
the media body.
import type { TImageElement } from 'platejs';
import type { PlateElementProps } from 'platejs/react';
import {
Resizable,
ResizableProvider,
ResizeHandle,
useResizableValue,
} from '@platejs/resizable';
import { PlateElement, withHOC } from 'platejs/react';
export const ImageElement = withHOC(
ResizableProvider,
function ImageElement(props: PlateElementProps<TImageElement>) {
const width = useResizableValue('width');
return (
<PlateElement {...props}>
<figure contentEditable={false}>
<Resizable
options={{
align: 'center',
maxWidth: '100%',
minWidth: 120,
}}
>
<ResizeHandle options={{ direction: 'left' }} />
<img alt="" src={props.element.url as string} />
<ResizeHandle options={{ direction: 'right' }} />
</Resizable>
<figcaption style={{ width }}>Caption</figcaption>
</figure>
{props.children}
</PlateElement>
);
}
);import type { TImageElement } from 'platejs';
import type { PlateElementProps } from 'platejs/react';
import {
Resizable,
ResizableProvider,
ResizeHandle,
useResizableValue,
} from '@platejs/resizable';
import { PlateElement, withHOC } from 'platejs/react';
export const ImageElement = withHOC(
ResizableProvider,
function ImageElement(props: PlateElementProps<TImageElement>) {
const width = useResizableValue('width');
return (
<PlateElement {...props}>
<figure contentEditable={false}>
<Resizable
options={{
align: 'center',
maxWidth: '100%',
minWidth: 120,
}}
>
<ResizeHandle options={{ direction: 'left' }} />
<img alt="" src={props.element.url as string} />
<ResizeHandle options={{ direction: 'right' }} />
</Resizable>
<figcaption style={{ width }}>Caption</figcaption>
</figure>
{props.children}
</PlateElement>
);
}
);The registry resize-handle component imports these primitives and adds the absolute positioning, hover affordance, and alignment classes.
Resizable Wrapper
Resizable composes useResizableState and useResizable. It renders a
relative outer wrapper and a relative inner wrapper, then provides its resize
callback to descendants through ResizeHandleProvider.
Alignment used by resize math.
Maximum width passed to the wrapper style and clamp utility.
Minimum width passed to the wrapper style and clamp utility.
Writes the finished width to the current TResizableElement. If the width is unchanged, it selects the node.
Updates the transient provider width while dragging.
Current provider width. It is synced from element.width ?? '100%'.
Converts a handle delta into a new width, clamps it, stores it while dragging, and writes it to the node when finished is true.
Inner wrapper props with position: 'relative', width, minWidth, and maxWidth.
Outer wrapper props with position: 'relative'.
Measures the static wrapper width for percent-to-pixel conversion.
For centered elements, left and right handles double the delta so the element grows from both sides. Left handles invert the delta before clamping.
Resize Handles
ResizeHandle is a primitive div created with createPrimitiveComponent. It
returns null in read-only mode because useResizeHandle sets hidden from
useReadOnly().
Resize edge. Defaults to left.
Starting width or height. If omitted, the handle reads its parent element on pointer start.
Called on mouse over and touch move.
Called after hover ends or resizing finishes.
Called after the hook records the starting pointer position and size.
Resize callback. Defaults to the nearest ResizeHandleProvider value.
Called after the hook records the starting touch position and size.
Resize handles listen on window while dragging. Mouse and touch move events emit finished: false; mouse up and touch end emit finished: true.
Stores
| API | State | Use |
|---|---|---|
ResizableProvider | { width: React.CSSProperties['width'] } | Wrap a resizable node and expose the active width to captions or overlays. |
useResizableValue('width') | React.CSSProperties['width'] | Read the current width. |
useResizableSet('width') | setter | Set the current width. |
useResizableStore / resizableStore | atom store | Advanced access to the resizable store. |
ResizeHandleProvider | { onResize: (event: ResizeEvent) => void } | Provides the wrapper resize callback to nested handles. |
useResizeHandleValue('onResize') | callback | Read the current resize callback. |
useResizeHandleSet('onResize') | setter | Replace the current resize callback. |
useResizeHandleStore | atom store | Advanced access to the handle store. |
Types
| Type | Value |
|---|---|
ResizeDirection | 'bottom' | 'left' | 'right' | 'top' |
ResizeLength | number | string |
ResizeLengthStatic | number |
ResizeLengthRelative | string |
ResizeEvent | { delta: number; direction: ResizeDirection; finished: boolean; initialSize: number } |
Length Utilities
Clamps a pixel length to pixel min/max values.
Converts length and constraints to pixels, clamps the value, then returns the same length kind as the input.
Converts a pixel length to a percent string. Percent strings pass through unchanged.
Converts a percent string to pixels. Numbers pass through unchanged.
Narrows pointer events by checking for touches.
resizeLengthToStatic parses strings as percentages. Use numeric pixel lengths when the source value is not a percentage.
Related Components
- Media covers the image, video, audio, and embed elements that consume the resizable primitives.
- Resize Handle covers the styled registry wrapper.