{"id":13422215,"url":"https://github.com/react-designer/react-designer","last_synced_at":"2025-05-15T17:06:00.752Z","repository":{"id":3871479,"uuid":"51185253","full_name":"react-designer/react-designer","owner":"react-designer","description":"It's not art","archived":false,"fork":false,"pushed_at":"2022-12-09T22:34:34.000Z","size":1083,"stargazers_count":1872,"open_issues_count":42,"forks_count":229,"subscribers_count":40,"default_branch":"master","last_synced_at":"2025-04-07T22:08:33.738Z","etag":null,"topics":["action-strategies","bezier-curves","react","svg","vector"],"latest_commit_sha":null,"homepage":"https://react-designer.github.io/react-designer/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/react-designer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-02-06T01:56:56.000Z","updated_at":"2025-03-26T09:42:37.000Z","dependencies_parsed_at":"2023-01-13T12:48:03.660Z","dependency_job_id":null,"html_url":"https://github.com/react-designer/react-designer","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react-designer%2Freact-designer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react-designer%2Freact-designer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react-designer%2Freact-designer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react-designer%2Freact-designer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/react-designer","download_url":"https://codeload.github.com/react-designer/react-designer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254384988,"owners_count":22062422,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["action-strategies","bezier-curves","react","svg","vector"],"created_at":"2024-07-30T23:00:39.384Z","updated_at":"2025-05-15T17:05:55.729Z","avatar_url":"https://github.com/react-designer.png","language":"JavaScript","funding_links":[],"categories":["UI Components","JavaScript"],"sub_categories":["Form Components"],"readme":"*This project is **back to being maintained**, redirect any new PRs and issues to [@wassgha](https://github.com/wassgha/)*\n\nReact-designer\n==============\n\n[![Join the chat at https://gitter.im/fatiherikli/react-designer](https://badges.gitter.im/fatiherikli/react-designer.svg)](https://gitter.im/fatiherikli/react-designer?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n\nEasy to configure, lightweight, editable vector graphics in your react components.\n\n- Supports polygon and shape designing (with bezier curves)\n- Implemented default scale, rotate, drag, and arrange actions\n- Custom object types and custom panels\n\n\nExamples and demonstration:\n\u003chttps://react-designer.github.io/react-designer/\u003e\n\n![bezier editor](http://i.imgur.com/cqTleWB.gif)\n\n## Keymap\n\n| Parameter                  | Default                         |\n| :-------------             |:-------------------------------\n| `del` or `back`            | Removes the current object      |\n| `arrows`                   | Move the current object by 1px  |\n| `shift` + `arrows`         | Move the currnet object by 10px |\n| `enter`                    | Close the drawing path          |\n\n\n## Usage\nAll the entities are pure react components except action strategies in react-designer. I have tried to explain that. I'm starting with components.\n\n### Component: Designer\n\nThis is the main canvas component which holds the all toolset and manages all drawing data. You could use this component to create drawing canvas.\n\nAn example with default configuration:\n\n```javascript\nimport Designer, {Text, Rectangle} from 'react-designer';\n\nclass App() {\n  state = {\n    objects: [\n      {type: \"text\", x: 10, y: 20, text: \"Hello!\", fill: \"red\"},\n      {type: \"rect\", x: 50, y: 70, fill: \"red\"}\n    ]\n  }\n\n  render() {\n    return (\n      \u003cDesigner width={250} height={350}\n        objectTypes={{\n          'text': Text,\n          'rect': Rect\n        }}\n        onUpdate={(objects) =\u003e this.setState({objects})}\n        objects={this.state.objects} /\u003e\n    )\n  }\n}\n```\n\nThe `Designer` component expects the following parameters:\n\n| Parameter        | Default                        |        |\n| :-------------    |:------------------------------- | :-----  |\n| width            | 300                            | The width of document  |\n| height           | 300                            | The height of document  |\n| canvasWidth      | null                           | The width of canvas. Same with document if it's null.  |\n| canvasHeight     | null                           | The height of canvas. Same with document if it's null. |\n| objects          | []                             | Your object set.  |\n| onUpdate         | []                             | Your update callback.  |\n| objectTypes      |  Text, Circle, Rectangle, Path | Mapping of object types. |\n| insertMenu       |  \u003cInsertMenu\u003e                  | Insert menu component. You can set null for hiding\n| snapToGrid       |  1                             | Snaps the objects accordingly this multipier. |\n| rotator          | rotate({object, mouse})        | The rotating strategy of objects\n| scale            | scale({object, mouse})         | The scaling strategy of objects\n| drag             | drag({object, mouse})          | The dragging strategy of objects\n\n\nObject types are pure react components which are derived from `Vector`.\n\n### Component: Vector\n\nYou can create an object type by subclassing `Vector` component. Each object types have static `meta` object which contains `icon` and `initial`, and optionally `editor` value.\n\nExample implementation:\n\n```javascript\nclass MyRectangle extends Vector {\n  static meta = {\n    icon: \u003cIcon icon={'rectangle'} size={30} /\u003e,\n    initial: {\n      width: 5,\n      height: 5,\n      strokeWidth: 0,\n      fill: \"yellow\",\n      radius: 5,\n      blendMode: \"normal\"\n    }\n  };\n\n  render() {\n    let {object, index} = this.props;\n    return (\n      \u003crect style={this.getStyle()}\n         {...this.getObjectAttributes()}\n         rx={object.radius}\n         width={object.width}\n         height={object.height} /\u003e\n    );\n  }\n}\n```\n\nYou can register this object type in your `Designer` instance.\n\n```javascript\n\u003cDesigner\n    objectTypes={{rectangle: MyRectangle}}\n    width={500}\n    height={500}\n    onUpdate={...}\n    objects={...}\n    onUpdate={...} /\u003e\n```\n\nApart from meta options, the vectors have `panels` static definition which contains the available panels of their.\n\nHere are default panels in Vector component:\n\n```javascript\nstatic panels = [\n    SizePanel,\n    TextPanel,\n    StylePanel,\n    ArrangePanel\n];\n```\n\n### Component: Preview\n\nYou can use `Preview` component to disable editing tool set and controllers. This component just renders the SVG output of your data. It may be useful for presenting edited or created graphic, instead of building a SVG file.\n\nThe parameters are same with Designer component, except for two: the onUpdate callback is not necessary and an additional `responsive` option can be added, which given the original `width` and `height` will expand the preview to cover the width and height of its parent component, scaling its SVG while keeping the original aspect ratio of elements. Note that the original `width` and `height` still need to be provided in order for the responsive `Preview` to work.\n\n```javascript\n\u003cPreview\n  objectTypes={{rectangle: MyRectangle}}\n  objects={this.state.objects}\n  height={500}\n  width={500}\n  responsive /\u003e\n```\n\n### Action strategies\n\nThe actions of `rotate`, `scale`, `drag` are pure functions. You can change this actions by passing your strategy. The action functions calling with the following object bundle.\n\n```javascript\n{\n  object, // the current object\n  mouse, // mouse coordinates bundle. it have x and y attribtues\n  startPoint, // starting points of mouse and object bundles.\n  objectIndex, // the index of the object in the documen,\n  objectRefs, // DOM references of objects in the document\n}\n```\n\nHere are default action strategies:\n\n#### Dragger\nMoves the object to mouse bundle by the center of object.\n\n```javascript\n// dragger.js\nexport default ({object, startPoint, mouse}) =\u003e {\n  return {\n    ...object,\n    x: mouse.x - (startPoint.clientX - startPoint.objectX),\n    y: mouse.y - (startPoint.clientY - startPoint.objectY)\n  };\n};\n```\n\n#### Scaler\nScales the object by the difference with startPoint and current mouse bundle. If the difference lower than zero, changes the position of object.\n\n```javascript\n// scale.js\nexport default ({object, startPoint, mouse}) =\u003e {\n  let {objectX, objectY, clientX, clientY} = startPoint;\n  let width = startPoint.width + mouse.x - clientX;\n  let height = startPoint.height + mouse.y - clientY;\n\n  return {\n    ...object,\n    x: width \u003e 0 ? objectX: objectX + width,\n    y: height \u003e 0 ? objectY: objectY + height,\n    width: Math.abs(width),\n    height: Math.abs(height)\n  };\n};\n```\n\n#### Rotator\nChanges the rotation as degree of object. This action may needs some improvement, I'm calculating with a base value (45 degree) because of the rotator anchor is on the upper right corner of object.\n\n```javascript\n// rotate.js\nexport default ({object, startPoint, mouse}) =\u003e {\n  let angle = Math.atan2(\n    startPoint.objectX + (object.width || 0) / 2 - mouse.x,\n    startPoint.objectY + (object.height || 0) / 2 - mouse.y\n  );\n\n  let asDegree = angle * 180 / Math.PI;\n  let rotation = (asDegree + 45) * -1;\n\n  return {\n    ...object,\n    rotate: rotation\n  };\n};\n```\n\n\n### To-do\n\nI built this project to create user-designed areas in my side project. So, this was just a hobby project, there may be things missing for a svg editor. I'm open to pull requests and feedback, and I need help to maintain.\n\nHere is a todo list that in my mind. You could extend this list.\n\n- Implement `Export` panel\n    - Export selected object\n    - Export document\n- Write initial tests and setup test environment\n- Add a key map to keep the ratio of objects when scaling\n- Implement theme support for UI\n\n## Release Notes\n\n### 1.0.8\n\n  - Move React-dom dependency to dev-dependencies\n\n### 1.0.6\n\n  - `Designer` component exported as default now.\n  - Added `insertMenu` prop to `Designer` component.\n\n### Contributors (You can add your name here in your pull-request)\n\n- Fatih Erikli \u003cfatiherikli@gmail.com\u003e - [fatiherikli](https://github.com/fatiherikli/)\n- Wassim Gharbi \u003cwassgha@gmail.com\u003e - [wassgha](https://github.com/wassgha/)\n- [iamraffe](https://github.com/iamraffe/)\n- [thatneat](https://github.com/thatneat/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freact-designer%2Freact-designer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freact-designer%2Freact-designer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freact-designer%2Freact-designer/lists"}