@dxos/plugin-tldraw 0.10.0 → 0.11.1
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/dist/lib/TldrawPlugin.mjs +4 -5
- package/dist/lib/TldrawPlugin.mjs.map +1 -1
- package/dist/lib/capabilities.mjs +2 -2
- package/dist/lib/capabilities.mjs.map +1 -1
- package/dist/lib/chunk-TldrawArticle.mjs +10 -9
- package/dist/lib/chunk-TldrawArticle.mjs.map +1 -1
- package/dist/lib/chunk-TldrawCard.mjs +5 -5
- package/dist/lib/chunk-TldrawCard.mjs.map +1 -1
- package/dist/lib/chunk-drawing-variant.mjs +20 -0
- package/dist/lib/chunk-drawing-variant.mjs.map +1 -0
- package/dist/lib/chunk-meta.mjs +1 -0
- package/dist/lib/chunk-meta.mjs.map +1 -1
- package/dist/lib/chunk-types.mjs +5 -31
- package/dist/lib/chunk-types.mjs.map +1 -1
- package/dist/lib/components.mjs +1 -1
- package/dist/lib/components.mjs.map +1 -1
- package/dist/lib/hooks.mjs +5 -5
- package/dist/lib/hooks.mjs.map +1 -1
- package/dist/lib/index.mjs +1 -1
- package/dist/lib/model.mjs +58 -163
- package/dist/lib/model.mjs.map +1 -1
- package/dist/lib/types.mjs +1 -1
- package/dist/types/src/TldrawPlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/{sketch-variant.d.ts → drawing-variant.d.ts} +1 -1
- package/dist/types/src/capabilities/drawing-variant.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +1 -1
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/components/Canvas/Canvas.d.ts +4 -3
- package/dist/types/src/components/Canvas/Canvas.d.ts.map +1 -1
- package/dist/types/src/components/Canvas/Canvas.stories.d.ts.map +1 -1
- package/dist/types/src/components/Canvas/Mermaid.stories.d.ts +14 -0
- package/dist/types/src/components/Canvas/Mermaid.stories.d.ts.map +1 -0
- package/dist/types/src/components/actions.d.ts +2 -2
- package/dist/types/src/components/actions.d.ts.map +1 -1
- package/dist/types/src/containers/TldrawArticle/TldrawArticle.d.ts +3 -3
- package/dist/types/src/containers/TldrawArticle/TldrawArticle.d.ts.map +1 -1
- package/dist/types/src/containers/TldrawCard/TldrawCard.d.ts +2 -2
- package/dist/types/src/containers/TldrawCard/TldrawCard.d.ts.map +1 -1
- package/dist/types/src/containers/TldrawCard/TldrawCard.stories.d.ts.map +1 -1
- package/dist/types/src/hooks/useStoreAdapter.d.ts +2 -2
- package/dist/types/src/hooks/useStoreAdapter.d.ts.map +1 -1
- package/dist/types/src/model/{TldrawBuilder.d.ts → RecordBuilder.d.ts} +3 -3
- package/dist/types/src/model/{TldrawBuilder.d.ts.map → RecordBuilder.d.ts.map} +1 -1
- package/dist/types/src/model/RecordBuilder.test.d.ts +2 -0
- package/dist/types/src/model/RecordBuilder.test.d.ts.map +1 -0
- package/dist/types/src/model/builder.d.ts +7 -2
- package/dist/types/src/model/builder.d.ts.map +1 -1
- package/dist/types/src/model/index.d.ts +1 -2
- package/dist/types/src/model/index.d.ts.map +1 -1
- package/dist/types/src/model/read.d.ts +1 -1
- package/dist/types/src/model/read.d.ts.map +1 -1
- package/dist/types/src/model/render.d.ts +1 -1
- package/dist/types/src/types/Tldraw.d.ts +3 -22
- package/dist/types/src/types/Tldraw.d.ts.map +1 -1
- package/dist/types/src/types/TldrawCapabilities.d.ts +1 -1
- package/dist/types/src/types/TldrawCapabilities.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/dx.config.ts +1 -0
- package/package.json +33 -32
- package/src/TldrawPlugin.tsx +3 -5
- package/src/capabilities/{sketch-variant.ts → drawing-variant.ts} +7 -8
- package/src/capabilities/index.ts +1 -1
- package/src/components/Canvas/Canvas.stories.tsx +11 -7
- package/src/components/Canvas/Canvas.tsx +3 -2
- package/src/components/Canvas/Mermaid.stories.tsx +68 -0
- package/src/components/actions.ts +2 -3
- package/src/containers/TldrawArticle/TldrawArticle.tsx +8 -7
- package/src/containers/TldrawCard/TldrawCard.stories.tsx +8 -7
- package/src/containers/TldrawCard/TldrawCard.tsx +4 -4
- package/src/hooks/useStoreAdapter.ts +2 -1
- package/src/model/{TldrawBuilder.test.ts → RecordBuilder.test.ts} +8 -8
- package/src/model/{TldrawBuilder.ts → RecordBuilder.ts} +2 -2
- package/src/model/builder.ts +55 -18
- package/src/model/index.ts +1 -2
- package/src/model/read.ts +1 -1
- package/src/model/render.ts +3 -3
- package/src/model/scene.test.ts +1 -1
- package/src/types/Tldraw.ts +3 -30
- package/src/types/TldrawCapabilities.ts +1 -1
- package/src/variant.test.ts +19 -21
- package/dist/lib/chunk-sketch-variant.mjs +0 -23
- package/dist/lib/chunk-sketch-variant.mjs.map +0 -1
- package/dist/types/src/capabilities/sketch-variant.d.ts.map +0 -1
- package/dist/types/src/model/TldrawBuilder.test.d.ts +0 -2
- package/dist/types/src/model/TldrawBuilder.test.d.ts.map +0 -1
- package/dist/types/src/model/apply.d.ts +0 -5
- package/dist/types/src/model/apply.d.ts.map +0 -1
- package/src/model/apply.ts +0 -132
package/dx.config.ts
CHANGED
|
@@ -30,6 +30,7 @@ export default Config2.make({
|
|
|
30
30
|
dependsOn: ['org.dxos.plugin.illustrator'],
|
|
31
31
|
icon: { key: 'ph--compass-tool--regular', hue: 'indigo' },
|
|
32
32
|
spec: 'PLUGIN.mdl',
|
|
33
|
+
tags: ['alpha'],
|
|
33
34
|
screenshots: [{ dark: 'https://dxos.network/plugin-details-sketch-dark.png' }],
|
|
34
35
|
},
|
|
35
36
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/plugin-tldraw",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "tldraw canvas renderer for the DXOS Illustrator plugin.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
],
|
|
93
93
|
"dependencies": {
|
|
94
94
|
"@automerge/automerge": "3.3.0-fragments.2",
|
|
95
|
-
"@effect-atom/atom
|
|
95
|
+
"@effect-atom/atom": "^0.5.3",
|
|
96
96
|
"@tldraw/assets": "^3.0.0",
|
|
97
97
|
"@tldraw/editor": "^3.0.0",
|
|
98
98
|
"@tldraw/state": "^3.0.0",
|
|
@@ -103,29 +103,30 @@
|
|
|
103
103
|
"effect": "3.21.4",
|
|
104
104
|
"lodash.defaultsdeep": "^4.6.1",
|
|
105
105
|
"react-resize-detector": "^11.0.1",
|
|
106
|
-
"@dxos/app-framework": "0.
|
|
107
|
-
"@dxos/
|
|
108
|
-
"@dxos/
|
|
109
|
-
"@dxos/
|
|
110
|
-
"@dxos/
|
|
111
|
-
"@dxos/echo-
|
|
112
|
-
"@dxos/
|
|
113
|
-
"@dxos/
|
|
114
|
-
"@dxos/
|
|
115
|
-
"@dxos/
|
|
116
|
-
"@dxos/
|
|
117
|
-
"@dxos/plugin-illustrator": "0.
|
|
118
|
-
"@dxos/
|
|
119
|
-
"@dxos/
|
|
120
|
-
"@dxos/react-
|
|
121
|
-
"@dxos/react-hooks": "0.
|
|
122
|
-
"@dxos/
|
|
123
|
-
"@dxos/
|
|
124
|
-
"@dxos/react-ui-form": "0.
|
|
125
|
-
"@dxos/schema": "0.
|
|
126
|
-
"@dxos/util": "0.
|
|
106
|
+
"@dxos/app-framework": "0.11.1",
|
|
107
|
+
"@dxos/async": "0.11.1",
|
|
108
|
+
"@dxos/client": "0.11.1",
|
|
109
|
+
"@dxos/compute": "0.11.1",
|
|
110
|
+
"@dxos/app-toolkit": "0.11.1",
|
|
111
|
+
"@dxos/echo-doc": "0.11.1",
|
|
112
|
+
"@dxos/effect": "0.11.1",
|
|
113
|
+
"@dxos/invariant": "0.11.1",
|
|
114
|
+
"@dxos/keys": "0.11.1",
|
|
115
|
+
"@dxos/log": "0.11.1",
|
|
116
|
+
"@dxos/plugin-graph": "0.11.1",
|
|
117
|
+
"@dxos/plugin-illustrator": "0.11.1",
|
|
118
|
+
"@dxos/plugin-space": "0.11.1",
|
|
119
|
+
"@dxos/echo-client": "0.11.1",
|
|
120
|
+
"@dxos/react-client": "0.11.1",
|
|
121
|
+
"@dxos/react-hooks": "0.11.1",
|
|
122
|
+
"@dxos/react-ui-attention": "0.11.1",
|
|
123
|
+
"@dxos/echo": "0.11.1",
|
|
124
|
+
"@dxos/react-ui-form": "0.11.1",
|
|
125
|
+
"@dxos/schema": "0.11.1",
|
|
126
|
+
"@dxos/util": "0.11.1"
|
|
127
127
|
},
|
|
128
128
|
"devDependencies": {
|
|
129
|
+
"@effect-atom/atom-react": "^0.5.0",
|
|
129
130
|
"@effect/vitest": "0.29.0",
|
|
130
131
|
"@types/lodash.defaultsdeep": "^4.6.6",
|
|
131
132
|
"@types/react": "~19.2.17",
|
|
@@ -133,20 +134,20 @@
|
|
|
133
134
|
"react": "~19.2.7",
|
|
134
135
|
"react-dom": "~19.2.7",
|
|
135
136
|
"vite": "^8.1.4",
|
|
136
|
-
"@dxos/
|
|
137
|
-
"@dxos/
|
|
138
|
-
"@dxos/react-ui": "0.
|
|
139
|
-
"@dxos/
|
|
140
|
-
"@dxos/
|
|
141
|
-
"@dxos/
|
|
142
|
-
"@dxos/
|
|
137
|
+
"@dxos/agent-runtime": "0.11.1",
|
|
138
|
+
"@dxos/plugin-testing": "0.11.1",
|
|
139
|
+
"@dxos/react-ui-mosaic": "0.11.1",
|
|
140
|
+
"@dxos/storybook-utils": "0.11.1",
|
|
141
|
+
"@dxos/ui-theme": "0.11.1",
|
|
142
|
+
"@dxos/random": "0.11.1",
|
|
143
|
+
"@dxos/react-ui": "0.11.1"
|
|
143
144
|
},
|
|
144
145
|
"peerDependencies": {
|
|
145
146
|
"effect": "3.21.4",
|
|
146
147
|
"react": "~19.2.7",
|
|
147
148
|
"react-dom": "~19.2.7",
|
|
148
|
-
"@dxos/react-ui": "^0.
|
|
149
|
-
"@dxos/ui-theme": "^0.
|
|
149
|
+
"@dxos/react-ui": "^0.11.1",
|
|
150
|
+
"@dxos/ui-theme": "^0.11.1"
|
|
150
151
|
},
|
|
151
152
|
"publishConfig": {
|
|
152
153
|
"access": "public"
|
package/src/TldrawPlugin.tsx
CHANGED
|
@@ -5,21 +5,19 @@
|
|
|
5
5
|
import { Plugin } from '@dxos/app-framework';
|
|
6
6
|
import { AppActivationEvents, AppPlugin } from '@dxos/app-toolkit';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { DrawingVariant, TldrawSettings } from '#capabilities';
|
|
9
9
|
import { meta } from '#meta';
|
|
10
10
|
import { translations } from '#translations';
|
|
11
|
-
import { Tldraw } from '#types';
|
|
12
11
|
|
|
13
12
|
// eslint-disable-next-line import/no-relative-packages
|
|
14
13
|
import pluginSpec from '../PLUGIN.mdl?raw';
|
|
15
14
|
|
|
16
15
|
export const TldrawPlugin = Plugin.define(meta).pipe(
|
|
17
16
|
Plugin.addModule({
|
|
18
|
-
id: '
|
|
17
|
+
id: 'drawing-variant',
|
|
19
18
|
activatesOn: AppActivationEvents.SetupSchema,
|
|
20
|
-
activate:
|
|
19
|
+
activate: DrawingVariant,
|
|
21
20
|
}),
|
|
22
|
-
AppPlugin.addSchemaModule({ schema: [Tldraw.Canvas] }),
|
|
23
21
|
AppPlugin.addSettingsModule({ activate: TldrawSettings }),
|
|
24
22
|
AppPlugin.addTranslationsModule({ translations }),
|
|
25
23
|
AppPlugin.addPluginAssetModule({
|
|
@@ -5,21 +5,20 @@
|
|
|
5
5
|
import * as Effect from 'effect/Effect';
|
|
6
6
|
|
|
7
7
|
import { Capability } from '@dxos/app-framework';
|
|
8
|
-
import {
|
|
9
|
-
import { IllustratorCapabilities, type SketchVariant } from '@dxos/plugin-illustrator/types';
|
|
8
|
+
import { type DrawingVariant, IllustratorCapabilities } from '@dxos/plugin-illustrator/types';
|
|
10
9
|
|
|
11
10
|
import { TldrawArticle, TldrawCard } from '#containers';
|
|
12
|
-
import {
|
|
11
|
+
import { TldrawBuilder } from '#model';
|
|
13
12
|
|
|
14
13
|
import { Tldraw } from '../types';
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
// No `canvasType`/`createCanvas`: tldraw stores its records in the base `Drawing.Canvas`,
|
|
16
|
+
// discriminated by `schema`.
|
|
17
|
+
const variant: DrawingVariant = {
|
|
18
|
+
id: Tldraw.TLDRAW_SCHEMA,
|
|
18
19
|
label: 'tldraw',
|
|
19
20
|
icon: 'ph--compass-tool--regular',
|
|
20
|
-
|
|
21
|
-
createCanvas: () => Effect.sync(() => Tldraw.makeCanvas()),
|
|
22
|
-
builder: tldrawBuilder,
|
|
21
|
+
builder: TldrawBuilder,
|
|
23
22
|
card: TldrawCard,
|
|
24
23
|
article: TldrawArticle,
|
|
25
24
|
};
|
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
|
|
5
5
|
import { Capability } from '@dxos/app-framework';
|
|
6
6
|
|
|
7
|
-
export const
|
|
7
|
+
export const DrawingVariant = Capability.lazy('DrawingVariant', () => import('./drawing-variant'));
|
|
8
8
|
export const TldrawSettings = Capability.lazy('TldrawSettings', () => import('./settings'));
|
|
@@ -6,10 +6,11 @@ import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
|
6
6
|
import React, { useState } from 'react';
|
|
7
7
|
|
|
8
8
|
import { createObject } from '@dxos/echo-client';
|
|
9
|
+
import { Drawing } from '@dxos/plugin-illustrator/types';
|
|
9
10
|
import { Button, Panel, Toolbar } from '@dxos/react-ui';
|
|
10
11
|
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
11
12
|
|
|
12
|
-
import {
|
|
13
|
+
import { RecordBuilder } from '#model';
|
|
13
14
|
import { data } from '#testing';
|
|
14
15
|
import { Tldraw } from '#types';
|
|
15
16
|
|
|
@@ -17,21 +18,23 @@ import { migrateCanvas } from '../../migrations';
|
|
|
17
18
|
import { CanvasComponent } from './Canvas';
|
|
18
19
|
|
|
19
20
|
const DefaultStory = () => {
|
|
20
|
-
const [canvas, setCanvas] = useState(
|
|
21
|
+
const [canvas, setCanvas] = useState(
|
|
22
|
+
createObject(Drawing.makeCanvas({ schema: Tldraw.TLDRAW_SCHEMA, content: data.v2 })),
|
|
23
|
+
);
|
|
21
24
|
|
|
22
25
|
const handleClear = () => {
|
|
23
|
-
setCanvas(createObject(
|
|
26
|
+
setCanvas(createObject(Drawing.makeCanvas({ schema: Tldraw.TLDRAW_SCHEMA })));
|
|
24
27
|
};
|
|
25
28
|
|
|
26
29
|
const handleCreate = () => {
|
|
27
|
-
const canvas = createObject(
|
|
30
|
+
const canvas = createObject(Drawing.makeCanvas({ schema: Tldraw.TLDRAW_SCHEMA, content: data.v2 }));
|
|
28
31
|
console.log(JSON.stringify(canvas, undefined, 2));
|
|
29
32
|
setCanvas(canvas);
|
|
30
33
|
};
|
|
31
34
|
|
|
32
35
|
const handleMigrate = async () => {
|
|
33
36
|
const content = await migrateCanvas(data.v1);
|
|
34
|
-
setCanvas(createObject(
|
|
37
|
+
setCanvas(createObject(Drawing.makeCanvas({ schema: Tldraw.TLDRAW_SCHEMA, content })));
|
|
35
38
|
};
|
|
36
39
|
|
|
37
40
|
return (
|
|
@@ -74,8 +77,9 @@ export const Default: Story = {};
|
|
|
74
77
|
const BuilderStory = () => {
|
|
75
78
|
const [canvas] = useState(() =>
|
|
76
79
|
createObject(
|
|
77
|
-
|
|
78
|
-
|
|
80
|
+
Drawing.makeCanvas({
|
|
81
|
+
schema: Tldraw.TLDRAW_SCHEMA,
|
|
82
|
+
content: new RecordBuilder()
|
|
79
83
|
.rectangle({ id: 'a', x: 0, y: 0, text: 'DXOS', color: 'blue', fill: 'solid' })
|
|
80
84
|
.ellipse({ id: 'b', x: 360, y: 0, text: 'ECHO', color: 'green' })
|
|
81
85
|
.geo('star', { id: 'c', x: 180, y: 280, text: 'EDGE', color: 'yellow' })
|
|
@@ -13,11 +13,12 @@ import React, { type FC, useEffect, useMemo, useState } from 'react';
|
|
|
13
13
|
import { useResizeDetector } from 'react-resize-detector';
|
|
14
14
|
|
|
15
15
|
import { Obj } from '@dxos/echo';
|
|
16
|
+
import { Drawing } from '@dxos/plugin-illustrator/types';
|
|
16
17
|
import { useMergeRefs } from '@dxos/react-hooks';
|
|
17
18
|
import { composable, composableProps } from '@dxos/react-ui';
|
|
18
19
|
|
|
19
20
|
import { useStoreAdapter } from '#hooks';
|
|
20
|
-
import { type Settings
|
|
21
|
+
import { type Settings } from '#types';
|
|
21
22
|
|
|
22
23
|
import { handleSnap } from '../actions';
|
|
23
24
|
import { CustomMenu, CustomStylePanel, DefaultToolbarContent, DottedGrid, MeshGrid } from '../custom';
|
|
@@ -30,7 +31,7 @@ const gridComponents: Record<Settings.GridType, FC<TLGridProps>> = {
|
|
|
30
31
|
};
|
|
31
32
|
|
|
32
33
|
export type CanvasProps = {
|
|
33
|
-
canvas:
|
|
34
|
+
canvas: Drawing.Canvas;
|
|
34
35
|
readonly?: boolean;
|
|
35
36
|
autoCenter?: boolean;
|
|
36
37
|
hideUi?: boolean;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
|
+
import React, { useState } from 'react';
|
|
7
|
+
|
|
8
|
+
import { createObject } from '@dxos/echo-client';
|
|
9
|
+
import { type ContentMap, Mermaid } from '@dxos/plugin-illustrator/model';
|
|
10
|
+
import { Drawing } from '@dxos/plugin-illustrator/types';
|
|
11
|
+
import { Panel } from '@dxos/react-ui';
|
|
12
|
+
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
13
|
+
|
|
14
|
+
import { applyCommands } from '#model';
|
|
15
|
+
import { Tldraw } from '#types';
|
|
16
|
+
|
|
17
|
+
import { CanvasComponent } from './Canvas';
|
|
18
|
+
|
|
19
|
+
const FLOWCHART = `
|
|
20
|
+
flowchart TB
|
|
21
|
+
X[X]
|
|
22
|
+
|
|
23
|
+
subgraph CORE[" "]
|
|
24
|
+
A[A]
|
|
25
|
+
B[B]
|
|
26
|
+
C[C]
|
|
27
|
+
|
|
28
|
+
A --> B
|
|
29
|
+
A --> C
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
Y[Y]
|
|
33
|
+
|
|
34
|
+
X --> A
|
|
35
|
+
X --> B
|
|
36
|
+
X --> C
|
|
37
|
+
C --> Y
|
|
38
|
+
Y --> C
|
|
39
|
+
`;
|
|
40
|
+
|
|
41
|
+
const DefaultStory = () => {
|
|
42
|
+
const [canvas] = useState(() => {
|
|
43
|
+
const content: ContentMap = {};
|
|
44
|
+
applyCommands(content, Mermaid.compile(FLOWCHART, { scale: 2 }));
|
|
45
|
+
return createObject(Drawing.makeCanvas({ schema: Tldraw.TLDRAW_SCHEMA, content }));
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<Panel.Root>
|
|
50
|
+
<Panel.Content asChild>
|
|
51
|
+
<CanvasComponent classNames='dx-attention-surface' canvas={canvas} assetsBaseUrl={null} autoCenter />
|
|
52
|
+
</Panel.Content>
|
|
53
|
+
</Panel.Root>
|
|
54
|
+
);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const meta = {
|
|
58
|
+
title: 'plugins/plugin-tldraw/components/Mermaid',
|
|
59
|
+
render: DefaultStory,
|
|
60
|
+
decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
|
|
61
|
+
parameters: { layout: 'fullscreen' },
|
|
62
|
+
} satisfies Meta<typeof DefaultStory>;
|
|
63
|
+
|
|
64
|
+
export default meta;
|
|
65
|
+
|
|
66
|
+
type Story = StoryObj<typeof meta>;
|
|
67
|
+
|
|
68
|
+
export const Default: Story = {};
|
|
@@ -6,14 +6,13 @@ import type { TLRecord } from '@tldraw/tldraw';
|
|
|
6
6
|
import { isShape } from '@tldraw/tlschema';
|
|
7
7
|
|
|
8
8
|
import { Doc } from '@dxos/echo-doc';
|
|
9
|
+
import { Drawing } from '@dxos/plugin-illustrator/types';
|
|
9
10
|
import { getDeep } from '@dxos/util';
|
|
10
11
|
|
|
11
|
-
import type { Tldraw } from '#types';
|
|
12
|
-
|
|
13
12
|
/**
|
|
14
13
|
* Snap to grid.
|
|
15
14
|
*/
|
|
16
|
-
export const handleSnap = async (canvas:
|
|
15
|
+
export const handleSnap = async (canvas: Drawing.Canvas) => {
|
|
17
16
|
const snap = (value: number, tolerance = 40) => {
|
|
18
17
|
return Math.round(value / tolerance) * tolerance;
|
|
19
18
|
};
|
|
@@ -8,22 +8,23 @@ import { useAtomCapability } from '@dxos/app-framework/ui';
|
|
|
8
8
|
import { AppSurface, useAppGraph } from '@dxos/app-toolkit/ui';
|
|
9
9
|
import { Obj } from '@dxos/echo';
|
|
10
10
|
import { invariant } from '@dxos/invariant';
|
|
11
|
-
import { useActions } from '@dxos/plugin-graph';
|
|
12
|
-
import { type
|
|
11
|
+
import { useActions } from '@dxos/plugin-graph/hooks';
|
|
12
|
+
import { type DrawingVariantSurfaceProps } from '@dxos/plugin-illustrator/types';
|
|
13
|
+
import { Drawing } from '@dxos/plugin-illustrator/types';
|
|
13
14
|
import { Flex, Panel } from '@dxos/react-ui';
|
|
14
15
|
import { composable, composableProps } from '@dxos/react-ui';
|
|
15
16
|
import { useAttention } from '@dxos/react-ui-attention';
|
|
16
17
|
import { isTauri } from '@dxos/util';
|
|
17
18
|
|
|
18
19
|
import { CanvasComponent } from '#components';
|
|
19
|
-
import {
|
|
20
|
+
import { TldrawCapabilities } from '#types';
|
|
20
21
|
|
|
21
|
-
export type TldrawArticleProps =
|
|
22
|
+
export type TldrawArticleProps = DrawingVariantSurfaceProps;
|
|
22
23
|
|
|
23
|
-
export const TldrawArticle = ({ role, attendableId,
|
|
24
|
-
invariant(Obj.instanceOf(
|
|
24
|
+
export const TldrawArticle = ({ role, attendableId, drawing, canvas, extrinsic }: TldrawArticleProps) => {
|
|
25
|
+
invariant(Obj.instanceOf(Drawing.Canvas, canvas));
|
|
25
26
|
const settings = useAtomCapability(TldrawCapabilities.Settings);
|
|
26
|
-
const id = Obj.getURI(
|
|
27
|
+
const id = Obj.getURI(drawing as Obj.Any);
|
|
27
28
|
const { hasAttention } = useAttention(attendableId);
|
|
28
29
|
const section = role === AppSurface.Section.role;
|
|
29
30
|
|
|
@@ -5,20 +5,21 @@
|
|
|
5
5
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
6
|
import React, { useMemo } from 'react';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { Drawing } from '@dxos/plugin-illustrator/types';
|
|
9
9
|
import { CardContainer } from '@dxos/react-ui-mosaic/testing';
|
|
10
10
|
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
11
11
|
|
|
12
12
|
import { meta as pluginMeta } from '#meta';
|
|
13
|
-
import {
|
|
13
|
+
import { RecordBuilder } from '#model';
|
|
14
14
|
import { Tldraw } from '#types';
|
|
15
15
|
|
|
16
16
|
import { TldrawCard } from './TldrawCard';
|
|
17
17
|
|
|
18
18
|
const CardStory = () => {
|
|
19
|
-
const {
|
|
20
|
-
const canvas =
|
|
21
|
-
|
|
19
|
+
const { drawing, canvas } = useMemo(() => {
|
|
20
|
+
const canvas = Drawing.makeCanvas({
|
|
21
|
+
schema: Tldraw.TLDRAW_SCHEMA,
|
|
22
|
+
content: new RecordBuilder()
|
|
22
23
|
.rectangle({ id: 'a', x: 0, y: 0, text: 'DXOS', color: 'blue', fill: 'solid' })
|
|
23
24
|
.ellipse({ id: 'b', x: 360, y: 0, text: 'ECHO', color: 'green' })
|
|
24
25
|
.geo('star', { id: 'c', x: 180, y: 280, text: 'EDGE', color: 'yellow' })
|
|
@@ -26,12 +27,12 @@ const CardStory = () => {
|
|
|
26
27
|
.arrow({ from: 'b', to: 'c' })
|
|
27
28
|
.build(),
|
|
28
29
|
});
|
|
29
|
-
return {
|
|
30
|
+
return { drawing: Drawing.make({ canvas }), canvas };
|
|
30
31
|
}, []);
|
|
31
32
|
|
|
32
33
|
return (
|
|
33
34
|
<CardContainer role='popover' icon={pluginMeta.profile.icon?.key}>
|
|
34
|
-
<TldrawCard role='card--content'
|
|
35
|
+
<TldrawCard role='card--content' drawing={drawing} canvas={canvas} />
|
|
35
36
|
</CardContainer>
|
|
36
37
|
);
|
|
37
38
|
};
|
|
@@ -6,16 +6,16 @@ import React from 'react';
|
|
|
6
6
|
|
|
7
7
|
import { Obj } from '@dxos/echo';
|
|
8
8
|
import { invariant } from '@dxos/invariant';
|
|
9
|
-
import { type
|
|
9
|
+
import { type DrawingVariantSurfaceProps } from '@dxos/plugin-illustrator/types';
|
|
10
|
+
import { Drawing } from '@dxos/plugin-illustrator/types';
|
|
10
11
|
import { Card } from '@dxos/react-ui';
|
|
11
12
|
|
|
12
13
|
import { CanvasComponent } from '#components';
|
|
13
|
-
import { Tldraw } from '#types';
|
|
14
14
|
|
|
15
|
-
export type TldrawCardProps =
|
|
15
|
+
export type TldrawCardProps = DrawingVariantSurfaceProps;
|
|
16
16
|
|
|
17
17
|
export const TldrawCard = ({ canvas, editable = false }: TldrawCardProps) => {
|
|
18
|
-
invariant(Obj.instanceOf(
|
|
18
|
+
invariant(Obj.instanceOf(Drawing.Canvas, canvas));
|
|
19
19
|
return (
|
|
20
20
|
<Card.Body>
|
|
21
21
|
<Card.Section classNames='aspect-square'>
|
|
@@ -6,6 +6,7 @@ import { useState } from 'react';
|
|
|
6
6
|
|
|
7
7
|
import { Doc } from '@dxos/echo-doc';
|
|
8
8
|
import { log } from '@dxos/log';
|
|
9
|
+
import { Drawing } from '@dxos/plugin-illustrator/types';
|
|
9
10
|
import { useAsyncEffect } from '@dxos/react-ui';
|
|
10
11
|
|
|
11
12
|
import { Tldraw } from '#types';
|
|
@@ -19,7 +20,7 @@ import { TLDrawStoreAdapter } from './adapter';
|
|
|
19
20
|
* @param canvas - Optional canvas whose content will be synced.
|
|
20
21
|
* @returns The TLDrawStoreAdapter instance managing the tldraw store.
|
|
21
22
|
*/
|
|
22
|
-
export const useStoreAdapter = (canvas?:
|
|
23
|
+
export const useStoreAdapter = (canvas?: Drawing.Canvas) => {
|
|
23
24
|
const [adapter] = useState(new TLDrawStoreAdapter());
|
|
24
25
|
const [_, forceUpdate] = useState({});
|
|
25
26
|
useAsyncEffect(
|
|
@@ -5,17 +5,17 @@
|
|
|
5
5
|
import { createTLSchema } from '@tldraw/tlschema';
|
|
6
6
|
import { describe, test } from 'vitest';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { RecordBuilder } from './RecordBuilder';
|
|
9
9
|
|
|
10
|
-
describe('
|
|
10
|
+
describe('RecordBuilder', () => {
|
|
11
11
|
test('builds an empty canvas with document and page', ({ expect }) => {
|
|
12
|
-
const content = new
|
|
12
|
+
const content = new RecordBuilder().build();
|
|
13
13
|
expect(content['document:document'].typeName).to.eq('document');
|
|
14
14
|
expect(content['page:page'].typeName).to.eq('page');
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
test('chains shapes and connectors', ({ expect }) => {
|
|
18
|
-
const content = new
|
|
18
|
+
const content = new RecordBuilder()
|
|
19
19
|
.rectangle({ id: 'a', x: 0, y: 0, text: 'DXOS', color: 'blue' })
|
|
20
20
|
.ellipse({ id: 'b', x: 320, y: 0, text: 'ECHO', color: 'green' })
|
|
21
21
|
.text({ x: 0, y: 240, text: 'Hello', font: 'mono' })
|
|
@@ -30,7 +30,7 @@ describe('TldrawBuilder', () => {
|
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
test('connects via explicit points when shapes are not referenced', ({ expect }) => {
|
|
33
|
-
const content = new
|
|
33
|
+
const content = new RecordBuilder()
|
|
34
34
|
.arrow({ id: 'arrow', start: { x: 0, y: 0 }, end: { x: 200, y: 100 } })
|
|
35
35
|
.line({ id: 'line', start: { x: 0, y: 0 }, end: { x: 100, y: 0 } })
|
|
36
36
|
.build();
|
|
@@ -44,14 +44,14 @@ describe('TldrawBuilder', () => {
|
|
|
44
44
|
});
|
|
45
45
|
|
|
46
46
|
test('throws on unknown connector handles and duplicate shape ids', ({ expect }) => {
|
|
47
|
-
expect(() => new
|
|
47
|
+
expect(() => new RecordBuilder().rectangle({ id: 'a' }).arrow({ from: 'a', to: 'missing' })).to.throw(
|
|
48
48
|
/unknown target shape/,
|
|
49
49
|
);
|
|
50
|
-
expect(() => new
|
|
50
|
+
expect(() => new RecordBuilder().rectangle({ id: 'dup' }).ellipse({ id: 'dup' })).to.throw(/duplicate shape id/);
|
|
51
51
|
});
|
|
52
52
|
|
|
53
53
|
test('produces records that pass tldraw schema validation', ({ expect }) => {
|
|
54
|
-
const content = new
|
|
54
|
+
const content = new RecordBuilder()
|
|
55
55
|
.rectangle({ id: 'a', x: 0, y: 0, text: 'A' })
|
|
56
56
|
.circle({ id: 'b', x: 320, y: 0, text: 'B' })
|
|
57
57
|
.geo('star', { id: 'c', x: 160, y: 240, color: 'yellow' })
|
|
@@ -134,14 +134,14 @@ type Box = { id: string; x: number; y: number; w: number; h: number };
|
|
|
134
134
|
*
|
|
135
135
|
* @example
|
|
136
136
|
* ```ts
|
|
137
|
-
* const content = new
|
|
137
|
+
* const content = new RecordBuilder()
|
|
138
138
|
* .rectangle({ id: 'a', x: 0, y: 0, text: 'DXOS', color: 'blue' })
|
|
139
139
|
* .ellipse({ id: 'b', x: 320, y: 0, text: 'ECHO', color: 'green' })
|
|
140
140
|
* .arrow({ from: 'a', to: 'b' })
|
|
141
141
|
* .build();
|
|
142
142
|
* ```
|
|
143
143
|
*/
|
|
144
|
-
export class
|
|
144
|
+
export class RecordBuilder {
|
|
145
145
|
readonly #records: CanvasContent = {};
|
|
146
146
|
readonly #boxes = new Map<string, Box>();
|
|
147
147
|
readonly #metaFor?: (handle: string) => Record<string, any>;
|
package/src/model/builder.ts
CHANGED
|
@@ -3,29 +3,66 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
//
|
|
6
|
-
// tldraw implementation of the illustrator `
|
|
7
|
-
//
|
|
6
|
+
// tldraw implementation of the illustrator `DrawingBuilder` contract: supplies the record
|
|
7
|
+
// encoding (identity in `meta`, page scaffold, binding cleanup) and inherits the command
|
|
8
|
+
// semantics from the shared content handler.
|
|
8
9
|
//
|
|
9
10
|
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
import {
|
|
12
|
+
type ContentHandler,
|
|
13
|
+
type ContentMap,
|
|
14
|
+
type Identity,
|
|
15
|
+
type Scene,
|
|
16
|
+
applyCommands as applyContentCommands,
|
|
17
|
+
makeBuilder,
|
|
18
|
+
nextIndex,
|
|
19
|
+
} from '@dxos/plugin-illustrator/model';
|
|
13
20
|
|
|
14
21
|
import { Tldraw } from '../types';
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
22
|
+
import { elementBoxes, readScene } from './read';
|
|
23
|
+
import { DOCUMENT_ID, PAGE_ID } from './RecordBuilder';
|
|
24
|
+
import { renderObject } from './render';
|
|
17
25
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
26
|
+
const isShape = (record: any) => record?.typeName === 'shape';
|
|
27
|
+
|
|
28
|
+
const handler: ContentHandler = {
|
|
29
|
+
identify: (record) => {
|
|
30
|
+
if (!isShape(record) || typeof record.meta?.object !== 'string' || typeof record.meta?.element !== 'string') {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
return { object: record.meta.object, element: record.meta.element } satisfies Identity;
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
render: (object, placement, content) =>
|
|
37
|
+
renderObject(object, { ...placement, indexStart: nextIndex(content, isShape), external: elementBoxes(content) }),
|
|
38
|
+
|
|
39
|
+
read: (content) => readScene(content),
|
|
40
|
+
|
|
41
|
+
translate: (record, delta) => {
|
|
42
|
+
record.x += delta.x;
|
|
43
|
+
record.y += delta.y;
|
|
22
44
|
},
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
45
|
+
|
|
46
|
+
scaffold: (content: ContentMap) => {
|
|
47
|
+
content[DOCUMENT_ID] ??= { gridSize: 10, name: '', meta: {}, id: DOCUMENT_ID, typeName: 'document' };
|
|
48
|
+
content[PAGE_ID] ??= { meta: {}, id: PAGE_ID, name: 'Page 1', index: 'a1', typeName: 'page' };
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
// Bindings reference shapes by id; drop any left dangling by a deletion.
|
|
52
|
+
prune: (content: ContentMap) => {
|
|
53
|
+
for (const [key, record] of Object.entries(content)) {
|
|
54
|
+
if (record?.typeName === 'binding' && (!content[record.fromId] || !content[record.toId])) {
|
|
55
|
+
delete content[key];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
30
58
|
},
|
|
31
59
|
};
|
|
60
|
+
|
|
61
|
+
export const TldrawBuilder = makeBuilder({ schema: Tldraw.TLDRAW_SCHEMA, handler });
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Apply commands straight to a content map, bypassing ECHO — for tests and tooling that hold
|
|
65
|
+
* raw tldraw records. The object-aware path is {@link TldrawBuilder}.
|
|
66
|
+
*/
|
|
67
|
+
export const applyCommands = (content: ContentMap, commands: readonly Scene.Command[]) =>
|
|
68
|
+
applyContentCommands(content, commands, handler);
|
package/src/model/index.ts
CHANGED
package/src/model/read.ts
CHANGED
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
|
|
11
11
|
import { type ReadResult, type ReadWorldObject, type Scene } from '@dxos/plugin-illustrator/model';
|
|
12
12
|
|
|
13
|
+
import { type CanvasContent } from './RecordBuilder';
|
|
13
14
|
import { type ExternalBox } from './render';
|
|
14
|
-
import { type CanvasContent } from './TldrawBuilder';
|
|
15
15
|
|
|
16
16
|
type ShapeRecord = Record<string, any>;
|
|
17
17
|
|
package/src/model/render.ts
CHANGED
|
@@ -17,9 +17,9 @@ import {
|
|
|
17
17
|
type Fill,
|
|
18
18
|
type PathProps,
|
|
19
19
|
type Point,
|
|
20
|
+
RecordBuilder,
|
|
20
21
|
type ShapeProps,
|
|
21
|
-
|
|
22
|
-
} from './TldrawBuilder';
|
|
22
|
+
} from './RecordBuilder';
|
|
23
23
|
|
|
24
24
|
export const DEFAULT_SCALE = 1;
|
|
25
25
|
|
|
@@ -79,7 +79,7 @@ export const renderObject = (object: Scene.WorldObject, options: RenderOptions):
|
|
|
79
79
|
const length = (units: number) => units * scale;
|
|
80
80
|
|
|
81
81
|
const kinds = new Map<string, string>();
|
|
82
|
-
const builder = new
|
|
82
|
+
const builder = new RecordBuilder({
|
|
83
83
|
indexStart,
|
|
84
84
|
metaFor: (handle) => {
|
|
85
85
|
const [objectId, elementId] = splitHandle(handle);
|