{"_id":"@anjunar/scalajs-ui-editor","_rev":"6-00c7e14cac70c0f7010676cd0cc20bad","name":"@anjunar/scalajs-ui-editor","dist-tags":{"latest":"1.1.0"},"versions":{"1.0.0":{"name":"@anjunar/scalajs-ui-editor","version":"1.0.0","author":{"name":"Patrick Bittner"},"license":"MIT","_id":"@anjunar/scalajs-ui-editor@1.0.0","maintainers":[{"name":"anjunar","email":"anjunar@gmx.de"}],"homepage":"https://github.com/anjunar/scalajs-ui#readme","bugs":{"url":"https://github.com/anjunar/scalajs-ui/issues"},"dist":{"shasum":"ffd4a4a8149cc9cba8221e84594035fba8391d9a","tarball":"https://registry.npmjs.org/@anjunar/scalajs-ui-editor/-/scalajs-ui-editor-1.0.0.tgz","fileCount":14,"integrity":"sha512-1fUMWNIiGAtHMIEx6D4JoorCuupA1RlN7nA8MvoNt3RRWkd5XD35QiIKS1UGMbWYIHShisDKa2akSxyito9NwQ==","signatures":[{"sig":"MEQCIQDtFAu0ItIsGPByUjtmid2lBrLxL8TSc5RQWysaiKhaLQIffc9ux1GWcl7hB7XBZTYMCAUABzAMOOmtoCgACFa0cg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":26398},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"a9312d1aa728764c037b016ba66b703e003d6d50","scripts":{"test":"vitest run","build":"tsc -p tsconfig.json","verify":"npm run typecheck && npm run test && npm run test:consumer","prepack":"npm run build","typecheck":"npm run build && tsc -p tsconfig.test.json","test:watch":"vitest","test:consumer":"vitest run --config vitest.consumer.config.ts"},"_npmUser":{"name":"anjunar","email":"anjunar@gmx.de"},"repository":{"url":"git+https://github.com/anjunar/scalajs-ui.git","type":"git","directory":"npm/scalajs-ui-editor"},"_npmVersion":"11.17.0","description":"The TypeScript editor API of UI 3: a Lexical-backed rich-text control, bound by name like input, projected onto the ui.editor components that run in the Scala.js runtime published as @anjunar/scalajs-ui-bridge.","directories":{},"sideEffects":false,"_nodeVersion":"26.4.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^30.0.1","vitest":"^3.2.7","typescript":"^5.6.0","@types/node":"^22.0.0","@anjunar/scalajs-ui":"*","@anjunar/scalajs-ui-core":"*","@anjunar/scalajs-ui-forms":"*","@anjunar/scalajs-ui-bridge":"*","@anjunar/scalajs-ui-router":"*","@anjunar/scalajs-ui-viewport":"*"},"peerDependencies":{"@anjunar/scalajs-ui":"^1.0.0","@anjunar/scalajs-ui-core":"^1.0.0","@anjunar/scalajs-ui-forms":"^1.0.0","@anjunar/scalajs-ui-bridge":"^1.0.0","@anjunar/scalajs-ui-viewport":"^1.0.0"},"_npmOperationalInternal":{"tmp":"tmp/scalajs-ui-editor_1.0.0_1789143256545_0.2111964177677914","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@anjunar/scalajs-ui-editor","version":"1.0.2","author":{"name":"Patrick Bittner"},"license":"MIT","_id":"@anjunar/scalajs-ui-editor@1.0.2","maintainers":[{"name":"anjunar","email":"anjunar@gmx.de"}],"homepage":"https://github.com/anjunar/scalajs-ui#readme","bugs":{"url":"https://github.com/anjunar/scalajs-ui/issues"},"dist":{"shasum":"f364868a17d6169a51e48fbc9ad2d7ead8ae5f6b","tarball":"https://registry.npmjs.org/@anjunar/scalajs-ui-editor/-/scalajs-ui-editor-1.0.2.tgz","fileCount":14,"integrity":"sha512-3qagUQipAq/Q4IrwSoRXFS7lj117vJEPI1o5ZRoDxAaqEOVa5wVRR2+KGVn7ENRXjaFBDaj7GnvVCVU/+IGiKQ==","signatures":[{"sig":"MEUCIQDbWGugmaeDGSwP0Q8QN0NM0XDvxWR4jAkh2q/WctBIJgIgAmUnh0FRaKGJXfKvpx8hImn74aFMjUytPVUicJJSELY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":23042},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"192dd9f15ce1652b461173756defb0046fbd9ac4","scripts":{"test":"vitest run","build":"tsc -p tsconfig.json","verify":"npm run typecheck && npm run test && npm run test:consumer","prepack":"npm run build","typecheck":"npm run build && tsc -p tsconfig.test.json","test:watch":"vitest","test:consumer":"vitest run --config vitest.consumer.config.ts"},"_npmUser":{"name":"anjunar","email":"anjunar@gmx.de"},"repository":{"url":"git+https://github.com/anjunar/scalajs-ui.git","type":"git","directory":"npm/scalajs-ui-editor"},"_npmVersion":"11.17.0","description":"Native Ember rich-text control with a grouped ribbon, direct Viewport dialogs and Markdown form binding in the shared Scala.js UI runtime.","directories":{},"sideEffects":false,"_nodeVersion":"26.4.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^30.0.1","vitest":"^3.2.7","typescript":"^5.6.0","@types/node":"^22.0.0","@anjunar/scalajs-ui":"*","@anjunar/scalajs-ui-core":"*","@anjunar/scalajs-ui-forms":"*","@anjunar/scalajs-ui-bridge":"*","@anjunar/scalajs-ui-router":"*","@anjunar/scalajs-ui-viewport":"*"},"peerDependencies":{"@anjunar/scalajs-ui":"^1.0.2","@anjunar/scalajs-ui-core":"^1.0.2","@anjunar/scalajs-ui-forms":"^1.0.2","@anjunar/scalajs-ui-bridge":"^1.0.2","@anjunar/scalajs-ui-viewport":"^1.0.2"},"_npmOperationalInternal":{"tmp":"tmp/scalajs-ui-editor_1.0.2_1789506038395_0.4429592014286836","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@anjunar/scalajs-ui-editor","version":"1.0.3","author":{"name":"Patrick Bittner"},"license":"MIT","_id":"@anjunar/scalajs-ui-editor@1.0.3","maintainers":[{"name":"anjunar","email":"anjunar@gmx.de"}],"homepage":"https://github.com/anjunar/scalajs-ui#readme","bugs":{"url":"https://github.com/anjunar/scalajs-ui/issues"},"dist":{"shasum":"980b82a670c6e0ea869725401808725781843766","tarball":"https://registry.npmjs.org/@anjunar/scalajs-ui-editor/-/scalajs-ui-editor-1.0.3.tgz","fileCount":14,"integrity":"sha512-uqL49jhdB6qZxjnXyKiVrXYYdQbPGMjKlpWXVJgWM8vDzAEQvioLdjGOv8kouqUGo+TuxRLhpnpB02/FQ+p6/g==","signatures":[{"sig":"MEUCIDfHGBv2DvCpeLDjJcmSbtUlVP+kB3yLSRWtAaEGvIS+AiEArVKW4lARVFCnGS4SZSkSY67+aAY8I3KeFSLNEhxt3wk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":23042},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"81e89fc0d354046d9c9d548e5e1932d7baba0505","scripts":{"test":"vitest run","build":"tsc -p tsconfig.json","verify":"npm run typecheck && npm run test && npm run test:consumer","prepack":"npm run build","typecheck":"npm run build && tsc -p tsconfig.test.json","test:watch":"vitest","test:consumer":"vitest run --config vitest.consumer.config.ts"},"_npmUser":{"name":"anjunar","email":"anjunar@gmx.de"},"repository":{"url":"git+https://github.com/anjunar/scalajs-ui.git","type":"git","directory":"npm/scalajs-ui-editor"},"_npmVersion":"11.17.0","description":"Native Ember rich-text control with a grouped ribbon, direct Viewport dialogs and Markdown form binding in the shared Scala.js UI runtime.","directories":{},"sideEffects":false,"_nodeVersion":"26.4.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^30.0.1","vitest":"^3.2.7","typescript":"^5.6.0","@types/node":"^22.0.0","@anjunar/scalajs-ui":"*","@anjunar/scalajs-ui-core":"*","@anjunar/scalajs-ui-forms":"*","@anjunar/scalajs-ui-bridge":"*","@anjunar/scalajs-ui-router":"*","@anjunar/scalajs-ui-viewport":"*"},"peerDependencies":{"@anjunar/scalajs-ui":"^1.0.3","@anjunar/scalajs-ui-core":"^1.0.3","@anjunar/scalajs-ui-forms":"^1.0.3","@anjunar/scalajs-ui-bridge":"^1.0.3","@anjunar/scalajs-ui-viewport":"^1.0.3"},"_npmOperationalInternal":{"tmp":"tmp/scalajs-ui-editor_1.0.3_1789552911921_0.16331404953960038","host":"s3://npm-registry-packages-npm-production"}},"1.0.5":{"name":"@anjunar/scalajs-ui-editor","version":"1.0.5","author":{"name":"Patrick Bittner"},"license":"MIT","_id":"@anjunar/scalajs-ui-editor@1.0.5","maintainers":[{"name":"anjunar","email":"anjunar@gmx.de"}],"homepage":"https://github.com/anjunar/scalajs-ui#readme","bugs":{"url":"https://github.com/anjunar/scalajs-ui/issues"},"dist":{"shasum":"8518d21af3cd13aa23067e0cacecb404e49de5a3","tarball":"https://registry.npmjs.org/@anjunar/scalajs-ui-editor/-/scalajs-ui-editor-1.0.5.tgz","fileCount":26,"integrity":"sha512-0Ivf0+q6xLMmSuiv00/V3CCGN/jsxglxFKQTO5jkDwVH5wwv3sozEpJ7ZO5tz8HF/xsbPmmCcj3cKGSuo16JZw==","signatures":[{"sig":"MEQCIBB3KrPAjdznd/wer8UXatN0/8yLWqwNiGmMFmCE4qMJAiB+ENRFqmfB0BFLLZDZrsdeLTqIvxOQwDWGW+b1IkdKqA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIBQxzLHuAGGKXV1i/AeI81BqUPYPw15RbVLjzJaQ/MydAiEAx3PNhnPXNPp3nPBFaY04z+YNe+avDFnL4Bh3QcMwGkA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":66591},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"13988ebfcf64a17c3b7777ef28c3e55e6d48ddca","scripts":{"test":"vitest run","build":"tsc -p tsconfig.json","verify":"npm run typecheck && npm run test && npm run test:consumer","prepack":"npm run build","typecheck":"npm run build && tsc -p tsconfig.test.json","test:watch":"vitest","test:consumer":"vitest run --config vitest.consumer.config.ts"},"_npmUser":{"name":"anjunar","email":"anjunar@gmx.de"},"repository":{"url":"git+https://github.com/anjunar/scalajs-ui.git","type":"git","directory":"npm/scalajs-ui-editor"},"_npmVersion":"11.17.0","description":"Native Ember rich-text control with a grouped ribbon, direct Viewport dialogs and Markdown form binding in the shared Scala.js UI runtime.","directories":{},"sideEffects":false,"_nodeVersion":"26.4.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^30.0.1","vitest":"^3.2.7","typescript":"^5.6.0","@types/node":"^22.0.0","@anjunar/scalajs-ui":"*","@anjunar/scalajs-ui-core":"*","@anjunar/scalajs-ui-forms":"*","@anjunar/scalajs-ui-bridge":"*","@anjunar/scalajs-ui-router":"*","@anjunar/scalajs-ui-viewport":"*"},"peerDependencies":{"@anjunar/scalajs-ui":"^1.0.5","@anjunar/scalajs-ui-core":"^1.0.5","@anjunar/scalajs-ui-forms":"^1.0.5","@anjunar/scalajs-ui-bridge":"^1.0.5","@anjunar/scalajs-ui-viewport":"^1.0.5"},"_npmOperationalInternal":{"tmp":"tmp/scalajs-ui-editor_1.0.5_1789736155463_0.24253314065458165","host":"s3://npm-registry-packages-npm-production"}},"1.0.6":{"name":"@anjunar/scalajs-ui-editor","version":"1.0.6","author":{"name":"Patrick Bittner"},"license":"MIT","_id":"@anjunar/scalajs-ui-editor@1.0.6","maintainers":[{"name":"anjunar","email":"anjunar@gmx.de"}],"homepage":"https://github.com/anjunar/scalajs-ui#readme","bugs":{"url":"https://github.com/anjunar/scalajs-ui/issues"},"dist":{"shasum":"1be09299b899618149fb77197e1780f1df1f6b77","tarball":"https://registry.npmjs.org/@anjunar/scalajs-ui-editor/-/scalajs-ui-editor-1.0.6.tgz","fileCount":26,"integrity":"sha512-IM/jSWaSBcumEO4laguIXYk6WZDLO/qdeMnutwUzLzjXMOJdoMaP3F5l2jNlif2cbQ2oaiMcP7dgUai4Z8p77Q==","signatures":[{"sig":"MEUCIQDTBN4sCfV9jmImZDaun1pMoJPYPXJ+F4CtHHnGcdNdhgIgdQbDU/6PfTFnhFp6iRN/yHadDR5fFribLBblYXo+S5g=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIAy2VqAnZ1mAM1UDo7D+AF6M51iPsEHXhqBwRRagOhrEAiBrknLCMYwaGnTc1YUoU5XKWkY6uutwbEUQgPSag9677g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":67288},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"b5f4e2ac72fff6d18aff21420f18a811c54578e0","scripts":{"test":"vitest run","build":"tsc -p tsconfig.json","verify":"npm run typecheck && npm run test && npm run test:consumer","prepack":"npm run build","typecheck":"npm run build && tsc -p tsconfig.test.json","test:watch":"vitest","test:consumer":"vitest run --config vitest.consumer.config.ts"},"_npmUser":{"name":"anjunar","email":"anjunar@gmx.de"},"repository":{"url":"git+https://github.com/anjunar/scalajs-ui.git","type":"git","directory":"npm/scalajs-ui-editor"},"_npmVersion":"11.17.0","description":"Native Ember rich-text control with a grouped ribbon, direct Viewport dialogs and Markdown form binding in the shared Scala.js UI runtime.","directories":{},"sideEffects":false,"_nodeVersion":"26.4.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^30.0.1","vitest":"^3.2.7","typescript":"^5.6.0","@types/node":"^22.0.0","@anjunar/scalajs-ui":"*","@anjunar/scalajs-ui-core":"*","@anjunar/scalajs-ui-forms":"*","@anjunar/scalajs-ui-bridge":"*","@anjunar/scalajs-ui-router":"*","@anjunar/scalajs-ui-viewport":"*"},"peerDependencies":{"@anjunar/scalajs-ui":"^1.0.6","@anjunar/scalajs-ui-core":"^1.0.6","@anjunar/scalajs-ui-forms":"^1.0.6","@anjunar/scalajs-ui-bridge":"^1.0.6","@anjunar/scalajs-ui-viewport":"^1.0.6"},"_npmOperationalInternal":{"tmp":"tmp/scalajs-ui-editor_1.0.6_1789958602842_0.7200335162017075","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"_id":"@anjunar/scalajs-ui-editor@1.1.0","bugs":{"url":"https://github.com/anjunar/scalajs-ui/issues"},"dist":{"shasum":"e853739e2d04e1956a73fd6eed51fb7b394fccb0","tarball":"https://registry.npmjs.org/@anjunar/scalajs-ui-editor/-/scalajs-ui-editor-1.1.0.tgz","fileCount":26,"integrity":"sha512-HpkgE8XOjRN61l5sJL16kceUwfOIhYTQ+HAWFnSLd3PHw6Qxdl6CbVChSZ4Wk9J+/be4sy72zVBQr/LxvN7i8g==","signatures":[{"sig":"MEQCIAa6H7Nf5G9IkW/NvIYpLsDlSYzyyOn3O2GmflEAukjFAiBc6Btr3OVfIiVv4143M+q0CYzpCCtWAcXGEnVnrWI3LQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCZhuuf4aC+JWRxUomhU9TCvM1ZHfiLzMg8HJOHO9fqQQIgXx0IakPrrM2VYeCAyaPiBLALOghHwORLOi4agpuoRAg="}],"unpackedSize":67288},"main":"./dist/index.js","name":"@anjunar/scalajs-ui-editor","type":"module","types":"./dist/index.d.ts","author":{"name":"Patrick Bittner"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"a054cd17cb7cb398f4be3461b25c2a5df009a442","license":"MIT","scripts":{"test":"vitest run","build":"tsc -p tsconfig.json","verify":"npm run typecheck && npm run test && npm run test:consumer","prepack":"npm run build","typecheck":"npm run build && tsc -p tsconfig.test.json","test:watch":"vitest","test:consumer":"vitest run --config vitest.consumer.config.ts"},"version":"1.1.0","_npmUser":{"name":"anjunar","email":"anjunar@gmx.de"},"homepage":"https://github.com/anjunar/scalajs-ui#readme","repository":{"url":"git+https://github.com/anjunar/scalajs-ui.git","type":"git","directory":"npm/scalajs-ui-editor"},"_npmVersion":"11.17.0","description":"Native Ember rich-text control with a grouped ribbon, direct Viewport dialogs and Markdown form binding in the shared Scala.js UI runtime.","directories":{},"maintainers":[{"name":"anjunar","email":"anjunar@gmx.de"}],"sideEffects":false,"_nodeVersion":"26.4.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^30.0.1","vitest":"^3.2.7","typescript":"^5.6.0","@types/node":"^22.0.0","@anjunar/scalajs-ui":"*","@anjunar/scalajs-ui-core":"*","@anjunar/scalajs-ui-forms":"*","@anjunar/scalajs-ui-bridge":"*","@anjunar/scalajs-ui-router":"*","@anjunar/scalajs-ui-viewport":"*"},"peerDependencies":{"@anjunar/scalajs-ui":"^1.1.0","@anjunar/scalajs-ui-core":"^1.1.0","@anjunar/scalajs-ui-forms":"^1.1.0","@anjunar/scalajs-ui-bridge":"^1.1.0","@anjunar/scalajs-ui-viewport":"^1.1.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/scalajs-ui-editor_1.1.0_1790707723571_0.23984418278326824"}}},"time":{"created":"2026-09-11T16:14:16.384Z","modified":"2026-09-29T18:48:43.835Z","1.0.0":"2026-09-11T16:14:16.664Z","1.0.2":"2026-09-15T21:00:38.527Z","1.0.3":"2026-09-16T10:01:52.052Z","1.0.5":"2026-09-18T12:55:55.559Z","1.0.6":"2026-09-21T02:43:22.927Z","1.1.0":"2026-09-29T18:48:43.667Z"},"bugs":{"url":"https://github.com/anjunar/scalajs-ui/issues"},"author":{"name":"Patrick Bittner"},"license":"MIT","homepage":"https://github.com/anjunar/scalajs-ui#readme","repository":{"url":"git+https://github.com/anjunar/scalajs-ui.git","type":"git","directory":"npm/scalajs-ui-editor"},"description":"Native Ember rich-text control with a grouped ribbon, direct Viewport dialogs and Markdown form binding in the shared Scala.js UI runtime.","maintainers":[{"name":"anjunar","email":"anjunar@gmx.de"}],"readme":"# @anjunar/scalajs-ui-editor\n\nA native Ember rich-text field for Scala JS UI. Markdown is the public value; the session, ribbon and Viewport forms use one Scala.js UI runtime.\n\n## Overview\n\nThe TypeScript package has two entry points into the same linked Scala.js runtime:\n\n- `editor(name, options)` mounts a form-bound field. The Scala `ui.editor.Editor` component owns SSR, hydration, Markdown conversion, browser editing, and form binding. Link and image dialogs use the UI viewport layer.\n- `createEditor({ extensions })` creates a headless Ember session -- no DOM, usable in the browser, in Node and during SSR -- driven by typed commands. A mounted editor lends its own live session of the same type through `onSession`.\n\n## Installation\n\n```bash\nnpm install @anjunar/scalajs-ui-core @anjunar/scalajs-ui-forms @anjunar/scalajs-ui-viewport @anjunar/scalajs-ui-editor @anjunar/scalajs-ui-bridge @anjunar/scalajs-ui\n```\n\nImport `@anjunar/scalajs-ui-bridge/editor` instead of the bare package if you don't also need router/controls -- it pulls in the `scalajs-ember` dependency (about a third of the full bridge bundle) without the rest. See that package's README.\n\n## Quick start\n\n```ts\nimport { property } from \"@anjunar/scalajs-ui-core\";\nimport { form } from \"@anjunar/scalajs-ui-forms\";\nimport { editor } from \"@anjunar/scalajs-ui-editor\";\nimport { viewport } from \"@anjunar/scalajs-ui-viewport\";\n\nconst model = { body: property(\"## Article\\n\\nStart writing here.\") };\n\nviewport(() => form(model, {}, () => {\n  editor(\"body\", {\n    placeholder: \"Write the article...\",\n    plugins: [\"base\", \"heading\", \"list\", \"link\", \"image\", \"table\", \"code\", \"horizontalRule\"],\n  });\n}));\n```\n\n## Markdown and plugins\n\nThe native view supports headings, paragraphs, quotes, lists, emphasis, strong, inline code, links, fenced code, images, horizontal rules and GFM pipe tables. The UI Markdown dialect preserves image titles and `{width=320}`. Raw HTML and extra marks (`++underline++`, `~~strike~~`, `==highlight==`) open in the Markdown source view, so unrelated edits cannot silently change their meaning.\n\n`plugins` selects toolbar and insertion commands: `base`, `heading`, `list`, `link`, `image`, `table`, `code`, and `horizontalRule`. Without plugin configuration the standard toolbar is shown. `table` adds an insert-table command plus row/column/table commands that are enabled only with the caret inside one; a table itself always decodes and renders regardless of `plugins`. Link and image dialogs call Viewport directly. Image resizing is available as a width field in the image dialog.\n\n## Sessions and typed commands\n\n```ts\nimport {\n  createEditor, richText, history, lists, links, code,\n  insertText, setHeading, toggleList, undo,\n} from \"@anjunar/scalajs-ui-editor\";\n\nconst session = createEditor({\n  extensions: [richText(), history(), lists(), code(), links({ schemes: [\"https\"] })],\n  markdown: \"Ada\",\n});\n\nsession.dispatch(insertText, { text: \"Hello \" });      // payload type-checked and validated\nsession.dispatch(setHeading, { level: 2 });\nsession.dispatch(undo);                                  // commands without payload take none\nconst subscription = session.subscribe((commit) => console.log(commit.revision, commit.origin));\n\nconst markdown = session.toMarkdown();                   // { ok: true, value, losses } | { ok: false, error }\nconst json = session.toJson();                           // the Ember JSON envelope as a plain value\nsubscription.dispose();\nsession.dispose();\n```\n\nHandles are opaque values of the linked runtime. A look-alike object, or a handle of a second,\nseparately bundled copy of the bridge, is refused -- as is every call on a disposed session.\n\n- **Extensions** are factories, not a name list: `richText()`, `history()`, `lists()`, `code()`,\n  `links({ schemes?, allowRelative? })`, `images({ schemes?, allowRelative?, hosts? })`. Each call\n  is a recipe; the same handle can configure any number of sessions. The Markdown and JSON formats of\n  a session are exactly what its extensions bring.\n- **Commands**: `insertText`, `insertParagraph`, `deleteBackward`, `deleteForward`, `toggleMark`,\n  `setHeading`, `quote`, `unquote`, `insertThematicBreak`, `toggleList`, `indent`, `outdent`,\n  `toggleCodeBlock`, `setLink`, `removeLink`, `undo`, `redo`. A command whose extension is not\n  installed returns `handled: false` and changes nothing.\n- **Errors**: misuse throws (wrong payload or selection shape, a foreign or disposed handle, extensions\n  that do not resolve). What the document decides is a result: `{ ok: false, error }` for a rejected\n  change, a source that does not import, or an export that would lose content. Exports and imports are\n  strict unless `{ allowLoss: true }` is passed.\n- **Selection**: `session.selection` and `session.select(...)` use node ids and UTF-16 offsets\n  (`{ type: \"range\", anchor: { node, offset }, focus: { node, offset } }` or\n  `{ type: \"node\", nodes }`). A new session starts with a caret at the beginning.\n- **Imports**: `replaceMarkdown` and `replaceJson` replace the document as an import; history resets.\n\nA mounted editor lends its session in the browser, once per visual surface:\n\n```ts\nlet session: EditorSession | null = null;\neditor(\"body\", { onSession: (lent) => { session = lent; } });\n// later: session?.dispatch(undo)\n```\n\nChanges made through it flow into the form value. `toMarkdown` there uses the form's own Markdown\ndialect. `dispose()` ends only the handle; the handle stops working when the surface closes (unmount,\nor switching to the Markdown view -- switching back lends a new one). `onSession` is never called\nduring SSR.\n\n`plugins` stays what it is: a list of toolbar capabilities of the mounted editor, not extensions.\n\nThe session API is imported from `@anjunar/scalajs-ui-bridge/editor-api`, which installs nothing.\nImporting this package therefore neither installs a runtime nor conflicts with a test runtime.\n\n## Media uploads\n\nImages contain permanent internal references, never embedded bytes. Configure a storage adapter\nto enable the picker, image-file paste and drop:\n\n```ts\nimport type { MediaUploader } from \"@anjunar/scalajs-ui-editor\";\n\nconst mediaUploader: MediaUploader = {\n  async upload(file, signal) {\n    const form = new FormData();\n    form.append(\"image\", file);\n    // This example route belongs to the consuming application, not the UI library.\n    const response = await fetch(\"/media/upload\", { method: \"POST\", body: form, signal });\n    if (!response.ok) throw new Error(\"Image upload failed\");\n    return await response.json(); // { mediaId: \"4711\", src: \"/media/4711\" }\n  },\n};\n\neditor(\"body\", {\n  plugins: [\"base\", \"image\"],\n  mediaUploader,\n  mediaUrlPolicy: {\n    resolve: src => src.startsWith(\"/media/\")\n      ? { src, mediaId: src.slice(\"/media/\".length) }\n      : null,\n  },\n  onMediaStatus: ({ pending, error }) => {\n    // Reflect pending uploads and errors in application UI / save controls.\n  },\n});\n```\n\nThe adapter resolves only after durable storage succeeds. Its result must include a nonempty\n`mediaId` and a usable internal `src`; external, `data:` and `blob:` results are rejected.\nThe URL policy is synchronous, deterministic and shared with SSR. It can restrict internal media\nroutes and recover IDs from canonical URLs. It cannot allow external URLs. Without a policy, all\nunambiguous paths starting with a single `/` are eligible. Absolute URLs, including same-origin\nones, are not the persisted representation. Keep expiring storage URLs behind a stable internal\nendpoint. Static internal image references may omit `mediaId`.\n\nAlt text, title and width describe a document occurrence, independently of the stored asset:\n\n```md\n![Katze](/media/4711 \"Im Garten\"){width=320}\n```\n\nWidth is an optional positive integer in CSS pixels (1–100000 in the native view; larger existing values stay in source view). Explicit widths, including\n680, survive export. Omission means natural width constrained by the container. Percentages,\nCSS expressions and other units are not supported. The renderer uses the chosen width with\n`max-width: 100%` and automatic height. Reference-style images are expanded to inline Markdown;\nstandard code examples are preserved. The backend must support the same `{width=N}` extension.\n\nClipboard HTML and the native clipboard format are validated against the selected profile.\nImage files use the uploader; loaded data/blob image references are discarded. Embedded HTML\nimage bytes are not a transport contract of the new editor. Upload errors do not create image\nnodes. Multi-file uploads retain input order. Document replacement, readonly mode and unmount\nabort pending insertions; composition temporarily defers insertion.\nThe editor never deletes stored media on its own; orphan cleanup belongs to the backend.\n\nThere is no built-in storage service. The demo therefore exposes the missing upload configuration\ninstead of simulating persistence. Without an uploader, existing image metadata remains editable.\n\n## SSR and non-JavaScript behavior\n\n`editable: false` renders semantic readonly HTML. `editable: true` renders a Markdown textarea on the server. Pass a `Property<boolean>` to control the mode from outside the editor and keep both sides synchronized. `editUrl` and `readonlyUrl` provide ordinary mode-switch links; without overrides they use `<name>.editor=editable|readonly`. Hydration claims the fallback and enhances supported documents to Ember.\n\nThe textarea stays synchronized after rich-text changes. A future HTML-only upload handler can\nuse an ordinary multipart POST with a separate file field and the same Markdown/reference\ncontract. UI forms intercept submit in JavaScript; configure the actual action, storage and\nserver validation in the consuming application. Document validation rejects invalid image URLs\nand widths, including values assigned externally: applications must validate before saving.\nThe backend must enforce the same rule for REST and no-JavaScript submissions.\n\nLink and image forms use `Viewport.WindowConf` directly. The Lexical dialog-service hooks were removed; a Viewport ancestor supplies the application window context.\n\n## API overview\n\n- `editor(name, options?)`\n- `Markdown` — the public string value alias.\n- `EditorPluginName` — supported plugin names.\n- `EditorToolbarMode` — `ribbon`, `menu`, or `floating`.\n- `EditorOptions` — value, binding, SSR mode, URLs, toolbar, plugins, and `onSession`.\n- `createEditor(options)`, `CreateEditorOptions`, `EditorSession` — headless sessions and the lent session type.\n- `Command<P>` and the command constants listed above.\n- `EditorExtension` and the factories `richText`, `history`, `lists`, `code`, `links`, `images`.\n- Result and DTO types: `EditorResult`, `DispatchResult`, `MarkdownResult`, `JsonResult`, `RevisionResult`, `EditorCommit`, `EditorSelection`, `EditorPoint`, `EditorJson`.\n\n## Related modules\n\n- [`@anjunar/scalajs-ui-forms`](../scalajs-ui-forms/README.md) supplies model binding.\n- [`@anjunar/scalajs-ui-viewport`](../scalajs-ui-viewport/README.md) supplies plugin dialogs.\n","readmeFilename":"README.md"}