4.1.1 • Published 3 years ago

react-shape-editor v4.1.1

Weekly downloads
126
License
MIT
Repository
github
Last release
3 years ago

React Shape Editor npm version CircleCI

Basic yet flexible shape editor component

shape-editorshape-editor

Other projects using react-shape-editor:

Installation

npm i react-shape-editor

Usage / CodeSandbox Examples

Components

ShapeEditor

The wrapper for the entire editor component. Contains the <svg> element.

PropTypeDefaultDescription
children(required)renderable elementsWill include components such as wrapShape-wrapped shapes, other library components (SelectionLayer/ImageLayer/DrawLayer) or arbitrary SVG elements
vectorHeight(required)numberHeight of the <svg> element viewBox (minus padding), in user units.
vectorWidth(required)numberWidth of the <svg> element viewBox (minus padding), in user units.
paddingnumber|object0Padding inside the <svg>, in px. Useful for displaying SVG content that would normally get clipped off by the edge of the SVG element. Can also help when providing contextual information (e.g., the surrounding parts of an image) while keeping the 0,0 coordinates on the part of the image you are focused on, avoiding having to convert the coordinates back-and-forth. Can be set via a number to apply to all edges, or as an object in the form: { top: number, right: number, bottom: number, left: number } to apply per-side.
scalenumber1Scale factor of the svg contents. For example, given a vectorWidth of 100 and a scale of 0.5, the rendered DOM element will be 50 px wide.
focusOnAddbooltrueIf true, focus on newly created elements.
focusOnDeletebooltrueIf true, focus on the next-closest element after a shape is deleted.
styleobject{}Style to apply to the <svg> element.

wrapShape (Higher-Order Component)

When used to wrap an SVG element, adds resize handles and enables resize and movement functionality.

Usage

const WrappedRect = wrapShape(({ height, width /* ... "wrapShape Props Received" */ }) => (
  <rect fill="blue" height={height} width={width} />
))

// later, in render()

<WrappedRect
  shapeId={myId}
  x={12}
  y={56}
  width={20}
  /* ... "WrappedShape Props" */
/>

wrapShape Props Received

PropTypeDescription
heightnumberHeight of the shape.
widthnumberWidth of the shape.
scalenumberScale of the parent <svg> element, provided so you can render strokes or other components that maintain a constant size at every zoom level.
shapeIdstringUnique identifier for the shape.
xnumberx-axis offset of the shape. NOTE: You should not use this to set the position of your shape, because the <g> that wraps the shape already includes this offset.
ynumbery-axis offset of the shape. NOTE: You should not use this to set the position of your shape, because the <g> that wraps the shape already includes this offset.
disabledboolIf true, the shape cannot be moved or resized, and shows no resize handles.
isBeingChangedboolIf true, the shape is currently being moved or scaled.
activeboolIf true, the shape has HTML-native focus or is selected via a SelectionLayer.
nativeActiveboolIf true, the shape has HTML-native focus (keyboard events will get applied to it).
isInSelectionGroupboolIf you assigned it via a prop on the WrappedShape, this will be available to tell whether or not the shape is in a group of two or more selected shapes (when using the SelectionLayer component). Useful for hiding the resize handles when selected in a group, or adding an outline.
extraShapePropsobjectContains all props passed in via the extraShapeProps prop on the wrapped shape.

WrappedShape Props

PropTypeDefaultDescription
height(required)numberHeight of the shape.
shapeId(required)stringUnique identifier for the shape, to aid in data handling.
width(required)numberWidth of the shape.
x(required)numberx-axis offset of the shape.
y(required)numbery-axis offset of the shape.
onChangefunc()=>{}Listener for transformation of this shape triggered by interactions with resize handles, panning, or keyboard shortcuts. Required for user-triggered shape transformations to work. Signature: (newRect: { x: number, y: number, height: number, width: number }, WrappedShapeProps: object) => void
onDeletefunc()=>{}Listener for the deletion of this shape via backspace or delete keys. Required for user-triggered shape deletion to work. Signature: (event: Event, WrappedShapeProps: object) => void
activeboolfalseIf true, the shape is rendered as focused (particularly important when using a SelectionLayer). When not using a selection layer, this prop can be left unset, as native HTML focus will handle focus state.
constrainMovefuncnon-constraining functionA callback for restricting movement during shape transformations (e.g., to lock movement to one axis, keeping the shape inside a predefined boundary or snapping it to a grid). Signature: ({ originalX: number, originalY: number, x: number, y: number, width: number, height: number }) => ({ x: number, y: number })
constrainResizefuncnon-constraining functionA callback for restricting resizing during shape transformations (e.g., to lock resizing to one axis, keeping the shape inside a predefined boundary or snapping it to a grid). Signature: ({ originalMovingCorner: { x: number, y: number }, startCorner: { x: number, y: number }, movingCorner: { x: number, y: number }, lockedDimension: one of "x" or "y" }) => ({ x: number, y: number })
disabledboolfalseIf true, the shape cannot be moved or resized, and shows no resize handles.
isInSelectionGroupboolfalseWhether or not the shape is in a group of two or more selected shapes (when using the SelectionLayer component). Prop is merely forwarded to the wrapped component to be used in customized rendering, e.g., hiding the resize handles when selected in a group, or adding an outline.
keyboardTransformMultipliernumber1Multiplier for keyboard-triggered transforms, such as ↑↓←→ keys to move or shift+↑↓←→ keys to resize. For example, with the default setting of 1, pressing would move the shape 1 px to the right. With a setting of 5, it would move 5px.
onKeyDownfunc()=>{}Listener for shape keydown event. If event.preventDefault() is called inside, it will override the default keyboard shortcut behavior. Signature: (event: Event, WrappedShapeProps: object) => void
onBlurfunc()=>{}Listener for shape blur event. Signature: (event: Event, WrappedShapeProps: object) => void
onFocusfunc()=>{}Listener for shape focus event. Signature: (event: Event, WrappedShapeProps: object) => void
ResizeHandleComponentComponentDefaultResizeHandleComponentThe component to use for shape handles.
wrapperPropsobject{}Extra props to add to the SVG <g> element wrapping the shape.
extraShapePropsobject{}A way to pass props down as-is to the shape component being wrapped.

ImageLayer

Renders an svg image element.

PropTypeDefaultDescription
src(required)stringURL for the image to display.
onLoadfunc()=>{}Callback for the image load. Signature: ({ naturalWidth: number, naturalHeight: number }) => void

DrawLayer

Creates an invisible layer of the SVG that allows users to draw shapes via mouse click-and-drag.

PropTypeDefaultDescription
onAddShape(required)funcCallback for when a shape has finished being drawn. Use it to add the new shape to your data. Signature: (newRect: { x: number, y: number, height: number, width: number }) => void
constrainMovefuncnon-constraining functionA callback for restricting the initial starting location for the drawing (e.g., to lock movement to one axis, keeping the shape inside a predefined boundary or snapping it to a grid). Signature: ({ originalX: number, originalY: number, x: number, y: number, width: number, height: number }) => ({ x: number, y: number })
constrainResizefuncnon-constraining functionA callback for restricting the dragged corner when drawing a shape (e.g., to lock resizing to one axis, keeping the shape inside a predefined boundary or snapping it to a grid). Signature: ({ originalMovingCorner: { x: number, y: number }, startCorner: { x: number, y: number }, movingCorner: { x: number, y: number }, lockedDimension: one of "x" or "y" }) => ({ x: number, y: number })
DrawPreviewComponentwrapShape(Component)DefaultDrawPreviewComponentThe component to preview the shape while dragging. Must be wrapped with wrapShape.
onDrawStartfunc()=>{}Called when a draw action begins. Signature: ({ startCorner: { x: number, y: number } }) => void
onDrawfunc()=>{}Called mid-draw. Signature: ({ startCorner: { x: number, y: number }, movingCorner: { x: number, y: number } }) => void
onDrawEndfunc()=>{}Called when a draw action ends. canceled indicates if it ended due to being canceled via the Escape key. Signature: ({ startCorner: { x: number, y: number }, movingCorner: { x: number, y: number }, canceled: boolean }) => void

SelectionLayer

Creates an invisible layer of the SVG that allows users to select shapes via mouse click-and-drag.

PropTypeDefaultDescription
selectedShapeIds(required)string[]shapeIds that belong to the currently selected group. Should be populated with shapeIds passed back from onSelectionChange.
onSelectionChangefunc()=>{}Listener for the addition or removal of shapes from the selection group (e.g., by shift+clicking extra shape or drawing new selection). Required for user-triggered selection to work. Signature: (selectedShapeIds: string[]) => void
onChangefunc()=>{}Listener for transformation of shapes in the selection triggered by interactions with resize handles, panning, or keyboard shortcuts. Required for user-triggered shape transformations on selections to work. Signature: (newRects: { x: number, y: number, height: number, width: number }[], selectedShapesProps: object[]) => void
onDeletefunc()=>{}Listener for the deletion of all shapes in this selection via backspace or delete keys. Required for user-triggered shape deletion to work. Signature: (event: Event, selectedShapesProps: object[]) => void
SelectionDrawComponentwrapShape(Component)DefaultSelectionDrawComponentThe component to preview the selection while dragging. Must be wrapped with wrapShape.
SelectionComponentwrapShape(Component)DefaultSelectionComponentThe component that visually wraps around the selected shapes (i.e., the selection outline). Must be wrapped with wrapShape.
minimumDistanceForSelectionnumber15Minimum height or width that the drawn selection must be in order to perform the selection.
keyboardTransformMultipliernumber1Multiplier for keyboard-triggered transforms, such as ↑↓←→ keys to move or shift+↑↓←→ keys to resize. For example, with the default setting of 1, pressing would move shapes in the selection 1 px to the right. With a setting of 5, they would move 5px.
selectionComponentPropsobject{}Extra props to pass to the SelectionComponent.
childrenrenderable elementsnullwrapShape-wrapped shapes that are targets for selection by this selection group. Can also include other library components (SelectionLayer/ImageLayer/DrawLayer) or arbitrary SVG elements.

Contributing

After cloning the repository and running yarn install inside, you can use the following commands to develop and build the project.

# Starts a dev server that hosts a demo page with the component.
yarn start

# Runs the library tests
yarn test

# Lints the code with eslint
yarn lint

# Lints and builds the code, placing the result in the dist directory.
# This build is necessary to reflect changes if you're
#  `npm link`-ed to this repository from another local project.
yarn build

License

MIT

4.1.1

3 years ago

4.1.0

4 years ago

4.0.0

4 years ago

4.0.0-alpha.1

4 years ago

4.0.0-alpha.2

4 years ago

4.0.0-alpha.0

4 years ago

3.5.3

4 years ago

3.5.2

4 years ago

3.5.0

4 years ago

3.4.0

4 years ago

3.3.1

4 years ago

3.3.0

4 years ago

3.2.1

4 years ago

3.2.0

4 years ago

3.1.0

4 years ago

3.0.0

4 years ago

2.6.1

5 years ago

2.6.0

5 years ago

2.5.2

5 years ago

2.5.1

5 years ago

2.5.0

5 years ago

2.4.2

5 years ago

2.4.1

5 years ago

2.4.0

5 years ago

2.3.0

5 years ago

2.2.2

5 years ago

2.2.1

5 years ago

2.2.0

5 years ago

2.1.2

5 years ago

2.1.1

5 years ago

2.1.0

5 years ago

2.0.1

5 years ago

2.0.0

5 years ago

1.2.1

5 years ago

1.2.0

5 years ago

1.1.1

5 years ago

1.1.0

5 years ago

1.0.1

5 years ago

1.0.0

5 years ago

0.1.0

5 years ago