@mocanvas/editor 4.0.2 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/ARCHITECTURE.md CHANGED
@@ -18,9 +18,15 @@ document model, tools, and UI live in TypeScript.
18
18
 
19
19
  ## Non-goals (v1)
20
20
 
21
- - Wire compatibility with tldraw's sync protocol.
22
- - Slot-compatible UI components.
21
+ - Wire compatibility with tldraw's sync protocol. `@mocanvas/sync` is a
22
+ transport of its own; it does not speak tldraw's wire format.
23
23
  - Pixel-identical rendering of every built-in shape.
24
+ - Shipping message catalogues. The translation seam exists
25
+ (`TLUiOverrides.translations`); the strings are the host's.
26
+
27
+ Slot-compatible UI components were a non-goal here and are no longer: the
28
+ `TLComponents` and `TLUiOverrides` surfaces are implemented. See
29
+ [MIGRATION.md §7](MIGRATION.md).
24
30
 
25
31
  ## Clean-room rule
26
32
 
package/MIGRATION.md CHANGED
@@ -10,7 +10,8 @@ The short version: your **documents, records, ids and `.tldr` files carry over
10
10
  untouched**, most of your **`Editor` calls carry over untouched**, your
11
11
  **`ShapeUtil` / `StateNode` / `BindingUtil` subclasses keep their shape**, and
12
12
  the real work is (a) imports, (b) teaching custom shapes about the GPU
13
- renderer, and (c) rebuilding UI, which has no slot compatibility yet.
13
+ renderer, and (c) UI, where the slots are compatible but the message
14
+ catalogues are yours to supply (§7).
14
15
 
15
16
  ---
16
17
 
@@ -237,6 +238,21 @@ the `export * from "@mocanvas/mocanvas"` at the top of the package.
237
238
  Everything `@mocanvas/editor` exports is re-exported by `@mocanvas/mocanvas`, so in app
238
239
  code you can import from `@mocanvas/mocanvas` alone.
239
240
 
241
+ ### Step 1b — the stylesheet
242
+
243
+ | Old import | New import |
244
+ | ------------------------ | --------------------------------- |
245
+ | `"tldraw/tldraw.css"` | `"@mocanvas/mocanvas/mocanvas.css"` |
246
+
247
+ Same arrangement, same one line, wherever you had it. The default UI is
248
+ unstyled without it.
249
+
250
+ `@mocanvas/compat` does not re-export the stylesheet — a package can only
251
+ export files it contains — so this import names `@mocanvas/mocanvas` even
252
+ during the zero-rename step. Under pnpm's strict `node_modules` that means
253
+ adding `@mocanvas/mocanvas` to your own dependencies alongside
254
+ `@mocanvas/compat`.
255
+
240
256
  ### Step 2 — drop the prefixes
241
257
 
242
258
  Once the app builds and runs against `@mocanvas/compat`, rename `TLFoo` →
@@ -499,26 +515,35 @@ returns both and `putContentOntoCurrentPage` accepts both.
499
515
 
500
516
  ## 7. UI
501
517
 
502
- **There is no slot compatibility yet**, and it is an explicit v1 non-goal. Do
503
- not expect your existing overrides of tldraw's UI components to compile.
518
+ **Slot compatibility exists.** This section used to say it did not and that it
519
+ was a v1 non-goal; both stopped being true before 4.0. Your existing overrides
520
+ of tldraw's UI components are the shape mocanvas expects.
504
521
 
505
522
  What you have:
506
523
 
507
- - `hideUi` on `<Mocanvas />` turns off the default toolbar and zoom bar
508
- entirely, leaving you the canvas and your `children`.
509
- - `components` (passed through to `<Canvas>`) lets you replace the canvas-level
510
- render slots.
524
+ - `components` the `TLComponents` map, at both the canvas level and the
525
+ chrome level. Pass a component to replace a slot, `null` to remove it.
526
+ - `overrides` `TLUiOverrides`, with `tools`, `actions` and `translations`.
527
+ The tool and action lists are what the toolbar, the menus and the keyboard
528
+ bindings are all built from, so rewriting an entry changes all three
529
+ together rather than only what is drawn.
530
+ - The default chrome as named exports — `TldrawUi`, `DefaultUi`,
531
+ `DefaultToolbar`, `DefaultMainMenu` and the rest — so you can render one
532
+ piece of it inside chrome of your own.
533
+ - `useTools()` and `useActions()` return those lists after overrides, which is
534
+ what a toolbar of your own should render from.
535
+ - `hideUi` on `<Mocanvas />` still turns the chrome off entirely, leaving you
536
+ the canvas and your `children`.
511
537
  - `useEditor()` inside any descendant of `<Canvas>` / `<EditorProvider>`
512
538
  returns the `Editor` (`useMaybeEditor()` returns `Editor | null`).
513
539
  - `track(Component)` and `useValue` from `@mocanvas/state/react` — re-exported
514
- from `@mocanvas/editor` and `@mocanvas/mocanvas` — make a component re-render when the
515
- signals it reads change.
540
+ from `@mocanvas/editor` and `@mocanvas/mocanvas` — make a component re-render
541
+ when the signals it reads change.
516
542
 
517
- The practical migration is: `hideUi`, then rebuild your chrome as ordinary
518
- React inside `<Mocanvas>`, reading and driving the editor through `useEditor`
519
- and `track`. Because the default UI is still being reworked, treat its internals
520
- as unstable and build against `useEditor` rather than against specific UI
521
- components.
543
+ One real difference remains: mocanvas ships **no message catalogues**, so
544
+ `overrides.translations` is where UI strings come from. The language menu lists
545
+ only the locales you supply a non-empty dictionary for, and renders nothing at
546
+ all if you supply none see the note in `UI.md`.
522
547
 
523
548
  ---
524
549
 
@@ -626,19 +651,18 @@ before.
626
651
 
627
652
  ## 10. Known gaps
628
653
 
629
- Taken from the "phase 3" and "later" rows of [COMPAT.md](COMPAT.md), plus what
630
- the code confirms today.
654
+ Every row below was re-checked against the built package rather than carried
655
+ forward from the roadmap. Rows that used to sit here and no longer belong —
656
+ `editor.resizeShape` and `stretchShapes`, `editor.getSvgString` and `toImage`,
657
+ `editor.textMeasure`/`user`/`menus`, presence records, and slot-compatible UI —
658
+ are all present, and the entries claiming otherwise were stale rather than
659
+ aspirational.
631
660
 
632
661
  | Gap | Status |
633
662
  | --- | ------ |
634
- | `editor.resizeShape`, `editor.stretchShapes` | phase 3. Interactive resize lives in the select tool; `ShapeUtil.onResize` and `BaseBoxShapeUtil` work, but there is no imperative resize entry point on `Editor`. |
635
- | `editor.getSvgString`, `editor.toImage` | Not `Editor` methods. Export is a set of free functions in `@mocanvas/mocanvas`: `getSvgString(editor, ids?, opts?)`, `exportToBlob(editor, opts)`, `downloadBlob(blob, filename)`, `copyBlobToClipboard(blob)`. |
636
663
  | `ShapeUtil.toSvg`, `ShapeUtil.toBackgroundSvg` | Not `ShapeUtil` members. Custom shapes contribute to SVG export through `registerShapeSvgRenderer(type, renderer)`; without one they fall back to `geometryFallbackSvg`. |
637
- | `pointer` and `instance_presence` records | later collaboration. No presence records, and no `mergeRemoteChanges` transport yet. |
638
- | Sync protocol | Explicit v1 non-goal. Wire compatibility with tldraw's sync protocol is not planned for v1. |
639
- | Slot-compatible UI | Explicit v1 non-goal. See §7. |
664
+ | Sync protocol | Wire compatibility with tldraw's own sync protocol is not planned. `@mocanvas/sync` is a working transport of its own — presence records, `store.mergeRemoteChanges`, and a relay but it does not speak tldraw's wire format. |
640
665
  | `image` shape on the GPU | The texture path exists in the engine (`StyleWords.texture` + `uploadTexture`) but the `image` shape still draws an `<img>` in the DOM overlay. |
641
- | `editor.textMeasure`, `editor.user`, `editor.menus` | Not implemented. Text measurement is DOM-backed inside the text layer; `editor.inputs` and `editor.sideEffects` do exist. |
642
666
  | Text rendering | DOM overlay. Glyph-atlas text in WASM is phase 3. |
643
667
  | GPU frame clipping | The `CLIP` flag and `isClipShape` hook are wired end to end, but no built-in shape enables it yet (phase 3). |
644
668
  | WebGPU backend | Phase 3. WebGL2 is the only backend today, behind `RenderBackend`. |
package/README.md CHANGED
@@ -16,6 +16,11 @@ npm install @mocanvas/editor react react-dom
16
16
 
17
17
  `react` and `react-dom` (>= 18) are peer dependencies.
18
18
 
19
+ This package ships no stylesheet: `<Canvas />` carries its own fallbacks for
20
+ the theme custom properties, so it renders correctly on its own. The default
21
+ UI theme is `@mocanvas/mocanvas/mocanvas.css`, and you import it only if you
22
+ also render that package's UI.
23
+
19
24
  ## Use
20
25
 
21
26
  ```tsx
package/UI.md CHANGED
@@ -4,6 +4,27 @@
4
4
  style panel, an optional statistics chip, and the chrome the editor draws on the
5
5
  canvas itself. All of it is optional and all of it is themeable from CSS.
6
6
 
7
+ ## Loading the stylesheet
8
+
9
+ The theme is published as `@mocanvas/mocanvas/mocanvas.css` and your app
10
+ imports it:
11
+
12
+ ```ts
13
+ import "@mocanvas/mocanvas/mocanvas.css"
14
+ ```
15
+
16
+ The package's JavaScript entry does not import it. That is deliberate: Node has
17
+ no loader for `.css`, so a CSS import inside `dist/index.js` makes
18
+ `import "@mocanvas/mocanvas"` throw `ERR_UNKNOWN_FILE_EXTENSION` anywhere there
19
+ is no bundler — vitest, SSR, a plain script. Up to and including 4.0.2 it did,
20
+ and the emitted file was content-hashed (`dist/ui-4C5V5GYT.css`) so there was no
21
+ stable name to import instead. Both are fixed; the cost is this one line in your
22
+ app.
23
+
24
+ `<Canvas />` from `@mocanvas/editor` carries fallback values for the canvas
25
+ chrome tokens, so an editor mounted without the stylesheet still renders
26
+ legibly — but the toolbar, panels, menus and dialogs need it.
27
+
7
28
  Source lives in `packages/mocanvas/src/ui/`:
8
29
 
9
30
  | File | What it holds |
@@ -122,8 +143,9 @@ so inline marks like the "mixed" badge keep the size they ask for.
122
143
  <Mocanvas hideUi />
123
144
  ```
124
145
 
125
- This drops the toolbar, zoom bar, style panel and stats chip. `ui.css` still
126
- loads, so the canvas chrome tokens above keep working. Default keyboard
146
+ This drops the toolbar, zoom bar, style panel and stats chip. The stylesheet is
147
+ imported by your app, not by the component, so the canvas chrome tokens above
148
+ keep working. Default keyboard
127
149
  shortcuts are wired by `<Mocanvas />` itself and are unaffected; call
128
150
  `useKeyboardShortcuts(editor)` yourself if you build on `<Canvas />` directly.
129
151