{"id":13880836,"url":"https://github.com/ponymessenger/use-prosemirror","last_synced_at":"2025-07-16T17:31:09.143Z","repository":{"id":45007804,"uuid":"291178889","full_name":"ponymessenger/use-prosemirror","owner":"ponymessenger","description":"ProseMirror + React made easy","archived":false,"fork":false,"pushed_at":"2023-01-30T14:31:12.000Z","size":73,"stargazers_count":356,"open_issues_count":1,"forks_count":21,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-07-01T06:49:28.658Z","etag":null,"topics":["hooks-api-react","javascript","prosemirror","react","react-hook","react-hooks","reactjs","rich-text-editor","typescript","wysiwyg-editor","wysiwym"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ponymessenger.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":"2020-08-29T01:31:39.000Z","updated_at":"2025-05-26T16:25:24.000Z","dependencies_parsed_at":"2023-02-16T08:30:51.262Z","dependency_job_id":null,"html_url":"https://github.com/ponymessenger/use-prosemirror","commit_stats":null,"previous_names":["dminkovsky/use-prosemirror"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/ponymessenger/use-prosemirror","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ponymessenger%2Fuse-prosemirror","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ponymessenger%2Fuse-prosemirror/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ponymessenger%2Fuse-prosemirror/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ponymessenger%2Fuse-prosemirror/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ponymessenger","download_url":"https://codeload.github.com/ponymessenger/use-prosemirror/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ponymessenger%2Fuse-prosemirror/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265527545,"owners_count":23782480,"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":["hooks-api-react","javascript","prosemirror","react","react-hook","react-hooks","reactjs","rich-text-editor","typescript","wysiwyg-editor","wysiwym"],"created_at":"2024-08-06T08:03:31.938Z","updated_at":"2025-07-16T17:31:08.835Z","avatar_url":"https://github.com/ponymessenger.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# use-prosemirror\n\n_ProseMirror + React made easy_\n\n**NOTE**: This library is in production at [Pony\nMessenger](https://www.ponymessenger.com/). It was open\nsourced to contribute to the incredible ProseMirror\necosystem, and to ensure the best possible experience for\nPony users.\n\n- [Example](#example)\n- [Installation](#installation)\n- [Usage](#usage)\n  - [`useProseMirror(config)`](#useprosemirrorconfig)\n  - [`\u003cProseMirror /\u003e`](#prosemirror-)\n- [More Info](#more-info)\n\n[ProseMirror](https://prosemirror.net/) is one of the best rich\ntext editors out there. Although it is not written in React, its\nrender model is very similar to React's. It is therefore a great\nfit for your React project.\n\nThis package lets you bootstrap a minimal, unopinionated React\nintegration quickly, using modern React best practices.\n\nUnlike other integrations, it:\n\n-   Separates state and presentation so you can keep your state\n    as high up as necessary.\n-   Allows using [`EditorView` props](https://prosemirror.net/docs/ref/#view.Props)\n    as React props.\n-   Is written in TypeScript.\n\n## Example\n\nA simple example is available on\n[CodeSandbox](https://codesandbox.io/s/use-prosemirror-basic-example-nie7f?file=/src/App.tsx).\nPlease join [this discussion](https://github.com/dminkovsky/use-prosemirror/discussions/8) if\nyou are interested in further usage examples.\n\n## Installation\n\n```\nnpm install --save use-prosemirror\n```\n\nor\n\n```\nyarn add use-prosemirror\n```\n\nThis package specifies React and ProseMirror as peer dependencies,\nso make sure you have them installed, too.\n\n## Usage\n\nThis is all you need to get started:\n\n```javascript\nimport 'prosemirror-view/style/prosemirror.css';\n\nimport React from 'react';\nimport {schema} from 'prosemirror-schema-basic';\nimport {useProseMirror, ProseMirror} from 'use-prosemirror';\n\nexport function MyEditor() {\n    const [state, setState] = useProseMirror({schema});\n    return \u003cProseMirror state={state} onChange={setState} /\u003e;\n};\n```\n\n### `useProseMirror(config)`\n\nThis hook maintains editor state. It accepts one argument: the\n[same object as\n`EditorState.create`](https://prosemirror.net/docs/ref/#state.EditorState%5Ecreate).\nIt follows the same convention as React's `useState` and creates\nthe initial state and returns it along with an update function.\n\n### `\u003cProseMirror /\u003e`\n\nThis component wraps ProseMirror's `EditorView`. It displays the\neditor state provided by `useProseMirror()` and dispatches state\nupdates using the update function. It accepts the following props:\n\n-   `state` — the `EditorState` created by `useProseMirror`.\n-   `onChange` — a function that accepts the next state. This can be\n    the update function returned by `useProseMirror`, or some function\n    that accepts the next state and eventually calls the update\n    function. Provide this if you do not provide\n    [`dispatchTransaction`](https://prosemirror.net/docs/ref/#view.DirectEditorProps.dispatchTransaction).\n-   `style` — (optional) a React style object to pass to the `div` containing ProseMirror.\n-   `className` — (optional) a string of classes you want to pass to the `div` containing ProseMirror.\n-   `editorViewFactory` — (optional) a function that accepts the root\n    DOM node where the editor will be mounted, `DirectEditorProps` and\n    component props, and returns an `EditorView`. Use this if you extend\n    `EditorView` or want to instantiate the `EditorView` in some special way.\n\nIt also accepts any\n[`EditorProps`](https://prosemirror.net/docs/ref/#view.EditorProps).\nSo you can, for example, set\n[`transformPastedHTML`](https://prosemirror.net/docs/ref/#view.EditorProps.transformPastedHTML)\ndirectly on the component:\n\n```javascript\n\u003cProseMirror\n    state={props.state}\n    onChange={props.onChange}\n    transformPastedHTML={string =\u003e {\n        console.log('transformPastedHTML', string);\n        return string;\n    }}\n/\u003e\n```\n\n\u003cblockquote\u003e\n\n**Note**: If passing a value for the `nodeViews` prop, its identity\nshould be stable. If it changes on every render, the editor will\nnot work correctly. This issue is described in\n[#1](https://github.com/dminkovsky/use-prosemirror/issues/1#issue-696086919)\nand an example of using `nodeViews` with React is given in\n[#5](https://github.com/dminkovsky/use-prosemirror/issues/5#issuecomment-769510937).\n\n\u003c/blockquote\u003e\n\nIf you pass\n[`dispatchTransaction`](https://prosemirror.net/docs/ref/#view.DirectEditorProps.dispatchTransaction)\nto `\u003cProseMirror /\u003e`, you are responsible for applying dispatched\ntransactions to the existing state and calling the update function\nreturned by `useProseMirror()`. `dispatchTransaction` takes\nprecedence over `onChange`, which will not be called if\n`dispatchTransaction` is provided.\n\nIf you pass a `ref`, `\u003cProseMirror /\u003e` exposes a `view` getter to retrieve the underlying [`EditorView`](https://prosemirror.net/docs/ref/#view.EditorView) instance:\n\n```javascript\nconst [state, setState] = useProseMirror({schema});\nconst viewRef = useRef();\nreturn (\n    \u003cProseMirror\n        ref={viewRef}\n        state={state}\n        onChange={state =\u003e {\n            setState(state);\n            console.log(viewRef.current.view.hasFocus());\n        }}\n    /\u003e\n);\n```\n\n## More Info\n\nReact and ProseMirror follow the same data flow model. Even though\nProseMirror is not written in React, it fits nicely into a React\nproject.\n\nFrom the [ProseMirror documentation](https://prosemirror.net/docs/guide/#view):\n\n\u003e So the editor view displays a given editor state, and when\n\u003e something happens, it creates a transaction and broadcasts this.\n\u003e This transaction is then, typically, used to create a new state,\n\u003e which is given to the view using its updateState method.\n\u003e\n\u003e \u003cimg src=\"./prosemirror-data-flow.png\"\u003e\n\u003e\n\u003e This creates a straightforward, cyclic data flow, as opposed to\n\u003e the classic approach (in the JavaScript world) of a host of\n\u003e imperative event handlers, which tends to create a much more\n\u003e complex web of data flows.\n\nSound familiar? It continues:\n\n\u003e It is possible to ‘intercept’ transactions as they are dispatched\n\u003e with the dispatchTransaction prop, in order to wire this cyclic\n\u003e data flow into a larger cycle—if your whole app is using a data\n\u003e flow model like this, as with Redux and similar architectures, you\n\u003e can integrate ProseMirror's transactions in your main\n\u003e action-dispatching cycle, and keep ProseMirror's state in your\n\u003e application ‘store’.\n\nWhich is exactly what [this module does](src/ProseMirror.tsx).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fponymessenger%2Fuse-prosemirror","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fponymessenger%2Fuse-prosemirror","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fponymessenger%2Fuse-prosemirror/lists"}