@visuallyjs/browser-ui-svelte 1.2.0 → 1.2.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/ColorPickerComponent.svelte +2 -2
- package/EdgeTypePickerComponent.svelte +1 -1
- package/OverlayWrapperComponent.svelte +35 -0
- package/PaperComponent.svelte +365 -0
- package/PaperProvider.svelte +11 -0
- package/SurfaceComponent.svelte +100 -5
- package/SurfacePopup.svelte +32 -0
- package/WrapperComponent.svelte +3 -1
- package/components.d.ts +4 -0
- package/components.js +4 -0
- package/definitions.d.ts +92 -6
- package/package.json +1 -1
- package/surface-store.d.ts +21 -1
- package/surface-store.js +41 -0
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
|
|
56
56
|
function colorPicked() {
|
|
57
57
|
const v = colorInput.value
|
|
58
|
-
inspector.setValue(props.propertyName, v)
|
|
58
|
+
inspector.setValue(props.propertyName, v, null)
|
|
59
59
|
addColor(v)
|
|
60
60
|
}
|
|
61
61
|
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
})
|
|
79
79
|
|
|
80
80
|
function selectSwatch(c:string) {
|
|
81
|
-
inspector.setValue(props.propertyName, c)
|
|
81
|
+
inspector.setValue(props.propertyName, c, null)
|
|
82
82
|
colorInput.value = c
|
|
83
83
|
}
|
|
84
84
|
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
inspector = i
|
|
31
31
|
const edgeMappings = resolveMappings()
|
|
32
32
|
edgeTypePicker = new EdgeTypePicker(inspector.$ui, container, edgeMappings, inspector.getValue(propertyName), (v) => {
|
|
33
|
-
inspector.setValue(propertyName, v)
|
|
33
|
+
inspector.setValue(propertyName, v, null)
|
|
34
34
|
})
|
|
35
35
|
|
|
36
36
|
edgeTypePicker.render(propertyName, inspector._currentCommonData)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
|
|
3
|
+
// This is a placeholder component that the surface uses to render each Svelte overlay,
|
|
4
|
+
// via a portal
|
|
5
|
+
import {type BrowserElement, BrowserUI} from "@visuallyjs/browser-ui";
|
|
6
|
+
|
|
7
|
+
let {component, edge, ui, data, className, el} = $props()
|
|
8
|
+
|
|
9
|
+
// svelte wants uppercase here. So we just assign to an uppercase var, which we use in the
|
|
10
|
+
// template
|
|
11
|
+
const ComponentToRender = component
|
|
12
|
+
|
|
13
|
+
// Define the portal action
|
|
14
|
+
function portal(node: BrowserElement, target: BrowserElement) {
|
|
15
|
+
if (!target) return; // Ensure target exists
|
|
16
|
+
|
|
17
|
+
target.appendChild(node);
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
destroy() {
|
|
21
|
+
if (target.contains(node)) {
|
|
22
|
+
target.removeChild(node);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const _ui = $state.raw(ui) as BrowserUI
|
|
29
|
+
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<!-- Use the portal action on the root div -->
|
|
33
|
+
<div use:portal={el} class={className}>
|
|
34
|
+
<ComponentToRender this={component} data={data} ui={_ui} edge={edge} model={_ui.model}/>
|
|
35
|
+
</div>
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount, type Snippet } from "svelte";
|
|
3
|
+
import {
|
|
4
|
+
BrowserUISvelteModel,
|
|
5
|
+
newInstance,
|
|
6
|
+
type PaperComponentProps
|
|
7
|
+
} from "./index";
|
|
8
|
+
import {
|
|
9
|
+
isNode,
|
|
10
|
+
isGroup,
|
|
11
|
+
renderPaper,
|
|
12
|
+
uuid,
|
|
13
|
+
EVENT_RENDER_END,
|
|
14
|
+
CLASS_DEFAULT_GROUP,
|
|
15
|
+
CLASS_DEFAULT_NODE, Paper,
|
|
16
|
+
type BrowserElement,
|
|
17
|
+
type ObjectData,
|
|
18
|
+
Vertex,
|
|
19
|
+
partition,
|
|
20
|
+
type VertexUpdatedParams,
|
|
21
|
+
extend, EVENT_GRAPH_CLEARED, EVENT_NODE_UPDATED, EVENT_GROUP_UPDATED,
|
|
22
|
+
type NodeRemovedParams, EVENT_NODE_REMOVED,
|
|
23
|
+
type GroupRemovedParams, EVENT_GROUP_REMOVED,
|
|
24
|
+
type PaperOptions,
|
|
25
|
+
OVERLAY_TYPE_CUSTOM,
|
|
26
|
+
type Connection,
|
|
27
|
+
type EdgeUpdatedParams,
|
|
28
|
+
type EdgeRemovedParams,
|
|
29
|
+
EVENT_EDGE_UPDATED,
|
|
30
|
+
EVENT_EDGE_REMOVED,
|
|
31
|
+
ELEMENT_DIV
|
|
32
|
+
} from "@visuallyjs/browser-ui";
|
|
33
|
+
import { internal_getPaperContext } from "./surface-store";
|
|
34
|
+
|
|
35
|
+
import DefaultNodeComponent from './DefaultNodeComponent.svelte'
|
|
36
|
+
import DefaultGroupComponent from './DefaultGroupComponent.svelte'
|
|
37
|
+
import WrapperComponent from "./WrapperComponent.svelte";
|
|
38
|
+
import OverlayWrapperComponent from "./OverlayWrapperComponent.svelte";
|
|
39
|
+
|
|
40
|
+
let container:HTMLElement;
|
|
41
|
+
|
|
42
|
+
let {
|
|
43
|
+
className,
|
|
44
|
+
renderOptions,
|
|
45
|
+
viewOptions,
|
|
46
|
+
modelOptions,
|
|
47
|
+
model,
|
|
48
|
+
data,
|
|
49
|
+
url,
|
|
50
|
+
shapeLibrary,
|
|
51
|
+
injector,
|
|
52
|
+
children
|
|
53
|
+
}:PaperComponentProps = $props();
|
|
54
|
+
|
|
55
|
+
const paperContext = internal_getPaperContext(false);
|
|
56
|
+
|
|
57
|
+
let paper:Paper;
|
|
58
|
+
|
|
59
|
+
export function getPaper() {
|
|
60
|
+
return paper
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function getModel() {
|
|
64
|
+
return paper?.model
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
type ComponentHolder = {
|
|
68
|
+
component:any,
|
|
69
|
+
props:any,
|
|
70
|
+
vertex:Vertex,
|
|
71
|
+
def:any,
|
|
72
|
+
id:string
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const componentMap:Map<string, ComponentHolder> = new Map();
|
|
76
|
+
const id = uuid();
|
|
77
|
+
|
|
78
|
+
// list of vertices to render
|
|
79
|
+
let _vertices:Array<ComponentHolder> = []
|
|
80
|
+
|
|
81
|
+
type OverlayHolder = {
|
|
82
|
+
component: any,
|
|
83
|
+
props: any,
|
|
84
|
+
edge: any,
|
|
85
|
+
id: string,
|
|
86
|
+
el:BrowserElement
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let _overlays: Array<OverlayHolder> = []
|
|
90
|
+
|
|
91
|
+
// state wrapper around the vertex list
|
|
92
|
+
let vertexState = $state({
|
|
93
|
+
vertices:_vertices
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
let overlayState = $state({
|
|
97
|
+
overlays: _overlays
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
// manages updating the vertex state cleanly.
|
|
101
|
+
function _updateVertexState() {
|
|
102
|
+
vertexState.vertices.length = 0
|
|
103
|
+
vertexState.vertices.push(..._vertices.slice())
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function _updateOverlayState() {
|
|
107
|
+
overlayState.overlays.length = 0
|
|
108
|
+
overlayState.overlays.push(..._overlays.slice())
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function _initialiseSvelteOverlays() {
|
|
112
|
+
const edgeTypes = viewOptions?.edges || {}
|
|
113
|
+
for (let type in edgeTypes) {
|
|
114
|
+
const edgeDefinition = edgeTypes[type];
|
|
115
|
+
if (edgeDefinition.overlays) {
|
|
116
|
+
edgeDefinition.overlays = edgeDefinition.overlays.map((ov: any) => {
|
|
117
|
+
if (ov.component != null) {
|
|
118
|
+
return {
|
|
119
|
+
type: OVERLAY_TYPE_CUSTOM,
|
|
120
|
+
options: {
|
|
121
|
+
create: (c: Connection<BrowserElement>) => {
|
|
122
|
+
const el = document.createElement(ELEMENT_DIV);
|
|
123
|
+
const overlayProps = {
|
|
124
|
+
data: c.edge.data,
|
|
125
|
+
model: paper.model,
|
|
126
|
+
ui: paper,
|
|
127
|
+
edge: c.edge,
|
|
128
|
+
vertex: c.edge, // Some components might expect vertex
|
|
129
|
+
...ov.props
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const holder: OverlayHolder = {
|
|
133
|
+
component: ov.component,
|
|
134
|
+
props: overlayProps,
|
|
135
|
+
edge: c.edge,
|
|
136
|
+
id: uuid(),
|
|
137
|
+
el
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
_overlays.push(holder);
|
|
141
|
+
_updateOverlayState();
|
|
142
|
+
return el;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
return ov;
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function render ( id:string, data:ObjectData, model:BrowserUISvelteModel, type:string,
|
|
154
|
+
paper:Paper, def:any, modelObject:Vertex, eventInfo:any) {
|
|
155
|
+
|
|
156
|
+
const hasComponent = def.component != null
|
|
157
|
+
let component;
|
|
158
|
+
if (!hasComponent) {
|
|
159
|
+
if (isNode(modelObject)) {
|
|
160
|
+
component = DefaultNodeComponent;
|
|
161
|
+
} else if (isGroup(modelObject)) {
|
|
162
|
+
component = DefaultGroupComponent;
|
|
163
|
+
}
|
|
164
|
+
} else {
|
|
165
|
+
component = def.component;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (component) {
|
|
169
|
+
let propsToSet:Record<string, any> = {
|
|
170
|
+
data: modelObject.data,
|
|
171
|
+
model,
|
|
172
|
+
ui:paper,
|
|
173
|
+
componentId: modelObject.getFullId(),
|
|
174
|
+
vertex: modelObject,
|
|
175
|
+
eventInfo,
|
|
176
|
+
className:hasComponent ? null : (isGroup(modelObject) ? CLASS_DEFAULT_GROUP : CLASS_DEFAULT_NODE)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (injector != null) {
|
|
180
|
+
const injectedProps = injector(modelObject);
|
|
181
|
+
if (injectedProps != null) {
|
|
182
|
+
for (let key in injectedProps) {
|
|
183
|
+
propsToSet[key] = injectedProps[key];
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const props = $state(propsToSet)
|
|
189
|
+
const componentHolder:ComponentHolder = {
|
|
190
|
+
component, props, vertex:modelObject, def, id:modelObject.id
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
_vertices.push(componentHolder)
|
|
194
|
+
_updateVertexState()
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function cleanupVertex(objId:string, el:BrowserElement) {
|
|
200
|
+
el.parentNode && el.parentNode.removeChild(el);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
onMount(async () => {
|
|
204
|
+
model = model || newInstance(modelOptions || {});
|
|
205
|
+
|
|
206
|
+
const templateRenderer = {
|
|
207
|
+
asynchronous: true,
|
|
208
|
+
reactive: true,
|
|
209
|
+
usesWrapperElement:true,
|
|
210
|
+
update: (el:BrowserElement, data:Object, vertex:Vertex) => {
|
|
211
|
+
const component = componentMap.get(vertex.id);
|
|
212
|
+
if (component) {
|
|
213
|
+
component.props.data = vertex.data
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
render,
|
|
217
|
+
cleanupVertex,
|
|
218
|
+
cleanupPort: (objId:string, el:BrowserElement) => {},
|
|
219
|
+
rerender: (
|
|
220
|
+
id:string,
|
|
221
|
+
data:ObjectData,
|
|
222
|
+
model:BrowserUISvelteModel,
|
|
223
|
+
type:string,
|
|
224
|
+
paper:Paper,
|
|
225
|
+
def:any,
|
|
226
|
+
modelObject:Vertex,
|
|
227
|
+
eventInfo:any,
|
|
228
|
+
originalElement:BrowserElement
|
|
229
|
+
) => {
|
|
230
|
+
|
|
231
|
+
// split into vertices we want to keep and the one we want to discard
|
|
232
|
+
const p = partition(_vertices, (v) => v.vertex !== modelObject)
|
|
233
|
+
// assign the ones we want to keep, update state
|
|
234
|
+
_vertices = p.left
|
|
235
|
+
_updateVertexState()
|
|
236
|
+
|
|
237
|
+
// remove the old DOM element
|
|
238
|
+
if (p.right.length > 0) {
|
|
239
|
+
cleanupVertex(modelObject.id, originalElement)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// on next tick, render again. it's important to wait for the next tick or the
|
|
243
|
+
// vertices state array gets messed up
|
|
244
|
+
setTimeout(() => {
|
|
245
|
+
render(id, data, model, type, paper, def, modelObject, eventInfo)
|
|
246
|
+
})
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
const params = (renderOptions || {}) as PaperOptions;
|
|
251
|
+
params.view = (viewOptions || {}) as any;
|
|
252
|
+
params.id = id;
|
|
253
|
+
|
|
254
|
+
if (shapeLibrary != null) {
|
|
255
|
+
params.shapes = {
|
|
256
|
+
library: shapeLibrary,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
_initialiseSvelteOverlays();
|
|
261
|
+
|
|
262
|
+
paper = renderPaper(model, container, templateRenderer, params);
|
|
263
|
+
|
|
264
|
+
// with continuous anchors it's necessary to do this, for
|
|
265
|
+
// asynchronous-y reasons. $redrawEveryConnection only redraws
|
|
266
|
+
// edges and does not update element positions so it's
|
|
267
|
+
// reasonably quick.
|
|
268
|
+
paper.bind(EVENT_RENDER_END, () => setTimeout(() => paper.$redrawEveryConnection()))
|
|
269
|
+
|
|
270
|
+
if (paperContext != null) {
|
|
271
|
+
paperContext.set(paper);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const updateVertex = (vertexId: string, eventPayload: VertexUpdatedParams) => {
|
|
275
|
+
|
|
276
|
+
let mergeData = () => {
|
|
277
|
+
let data = {}
|
|
278
|
+
if (eventPayload.originalData || eventPayload.updates) {
|
|
279
|
+
data = extend(eventPayload.originalData, eventPayload.updates)
|
|
280
|
+
}
|
|
281
|
+
return data
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
const entry = _vertices.find((v) => v.vertex.id === vertexId);
|
|
285
|
+
if (entry != null) {
|
|
286
|
+
entry.props.data = mergeData()
|
|
287
|
+
_updateVertexState()
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const removeVertex = (id: string) => {
|
|
292
|
+
_vertices = _vertices.filter(n => n.vertex.id !== id)
|
|
293
|
+
_updateVertexState()
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
model.bind<VertexUpdatedParams>(EVENT_NODE_UPDATED, (p: VertexUpdatedParams) => {
|
|
297
|
+
updateVertex(p.vertex.getFullId(), p)
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
model.bind<VertexUpdatedParams>(EVENT_GROUP_UPDATED, (p: VertexUpdatedParams) => {
|
|
301
|
+
updateVertex(p.vertex.getFullId(), p)
|
|
302
|
+
});
|
|
303
|
+
//
|
|
304
|
+
model.bind<NodeRemovedParams>(EVENT_NODE_REMOVED, (p: NodeRemovedParams) => {
|
|
305
|
+
removeVertex(p.node.id)
|
|
306
|
+
});
|
|
307
|
+
//
|
|
308
|
+
model.bind<GroupRemovedParams>(EVENT_GROUP_REMOVED, (p: GroupRemovedParams) => {
|
|
309
|
+
removeVertex(p.group.id)
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
const updateOverlays = (edgeId: string, eventPayload: EdgeUpdatedParams) => {
|
|
313
|
+
_overlays.forEach(o => {
|
|
314
|
+
if (o.edge.id === edgeId) {
|
|
315
|
+
o.props.data = eventPayload.edge.data;
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
_updateOverlayState();
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
const removeOverlays = (edgeId: string) => {
|
|
322
|
+
_overlays = _overlays.filter(o => o.edge.id !== edgeId);
|
|
323
|
+
_updateOverlayState();
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
model.bind<EdgeUpdatedParams>(EVENT_EDGE_UPDATED, (p) => updateOverlays(p.edge.id, p));
|
|
327
|
+
model.bind<EdgeRemovedParams>(EVENT_EDGE_REMOVED, (p) => removeOverlays(p.edge.id));
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
model.bind(EVENT_GRAPH_CLEARED, () => {
|
|
331
|
+
_vertices = []
|
|
332
|
+
_updateVertexState()
|
|
333
|
+
_overlays = []
|
|
334
|
+
_updateOverlayState()
|
|
335
|
+
})
|
|
336
|
+
|
|
337
|
+
if (url != null) {
|
|
338
|
+
model.load({ url });
|
|
339
|
+
} else if (data != null) {
|
|
340
|
+
model.load({ data });
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
</script>
|
|
345
|
+
|
|
346
|
+
<div class={className} bind:this={container}>
|
|
347
|
+
{#each vertexState.vertices as vertex (vertex.id)}
|
|
348
|
+
<WrapperComponent component={vertex.component}
|
|
349
|
+
data={vertex.props.data}
|
|
350
|
+
ui={paper}
|
|
351
|
+
def={vertex.def}
|
|
352
|
+
vertex={vertex.vertex}
|
|
353
|
+
className={vertex.props.className}/>
|
|
354
|
+
{/each}
|
|
355
|
+
|
|
356
|
+
{#each overlayState.overlays as overlay (overlay.id)}
|
|
357
|
+
<OverlayWrapperComponent component={overlay.component}
|
|
358
|
+
data={overlay.props.data}
|
|
359
|
+
ui={paper}
|
|
360
|
+
edge={overlay.edge}
|
|
361
|
+
className="vjs-svelte-overlay"
|
|
362
|
+
el={overlay.el}/>
|
|
363
|
+
{/each}
|
|
364
|
+
{@render children?.()}
|
|
365
|
+
</div>
|
package/SurfaceComponent.svelte
CHANGED
|
@@ -21,13 +21,21 @@
|
|
|
21
21
|
extend, EVENT_GRAPH_CLEARED, EVENT_NODE_UPDATED, EVENT_GROUP_UPDATED,
|
|
22
22
|
type NodeRemovedParams, EVENT_NODE_REMOVED,
|
|
23
23
|
type GroupRemovedParams, EVENT_GROUP_REMOVED,
|
|
24
|
-
type SurfaceOptions
|
|
24
|
+
type SurfaceOptions,
|
|
25
|
+
OVERLAY_TYPE_CUSTOM,
|
|
26
|
+
type Connection,
|
|
27
|
+
type EdgeUpdatedParams,
|
|
28
|
+
type EdgeRemovedParams,
|
|
29
|
+
EVENT_EDGE_UPDATED,
|
|
30
|
+
EVENT_EDGE_REMOVED,
|
|
31
|
+
ELEMENT_DIV
|
|
25
32
|
} from "@visuallyjs/browser-ui";
|
|
26
33
|
import { internal_getSurfaceContext } from "./surface-store";
|
|
27
34
|
|
|
28
35
|
import DefaultNodeComponent from './DefaultNodeComponent.svelte'
|
|
29
36
|
import DefaultGroupComponent from './DefaultGroupComponent.svelte'
|
|
30
37
|
import WrapperComponent from "./WrapperComponent.svelte";
|
|
38
|
+
import OverlayWrapperComponent from "./OverlayWrapperComponent.svelte";
|
|
31
39
|
|
|
32
40
|
let container:HTMLElement;
|
|
33
41
|
|
|
@@ -70,17 +78,78 @@
|
|
|
70
78
|
// list of vertices to render
|
|
71
79
|
let _vertices:Array<ComponentHolder> = []
|
|
72
80
|
|
|
81
|
+
type OverlayHolder = {
|
|
82
|
+
component: any,
|
|
83
|
+
props: any,
|
|
84
|
+
edge: any,
|
|
85
|
+
id: string,
|
|
86
|
+
el:BrowserElement
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let _overlays: Array<OverlayHolder> = []
|
|
90
|
+
|
|
73
91
|
// state wrapper around the vertex list
|
|
74
92
|
let vertexState = $state({
|
|
75
93
|
vertices:_vertices
|
|
76
94
|
})
|
|
77
95
|
|
|
96
|
+
let overlayState = $state({
|
|
97
|
+
overlays: _overlays
|
|
98
|
+
})
|
|
99
|
+
|
|
78
100
|
// manages updating the vertex state cleanly.
|
|
79
101
|
function _updateVertexState() {
|
|
80
102
|
vertexState.vertices.length = 0
|
|
81
103
|
vertexState.vertices.push(..._vertices.slice())
|
|
82
104
|
}
|
|
83
105
|
|
|
106
|
+
function _updateOverlayState() {
|
|
107
|
+
overlayState.overlays.length = 0
|
|
108
|
+
overlayState.overlays.push(..._overlays.slice())
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function _initialiseSvelteOverlays() {
|
|
112
|
+
const edgeTypes = viewOptions?.edges || {}
|
|
113
|
+
for (let type in edgeTypes) {
|
|
114
|
+
const edgeDefinition = edgeTypes[type];
|
|
115
|
+
if (edgeDefinition.overlays) {
|
|
116
|
+
edgeDefinition.overlays = edgeDefinition.overlays.map((ov: any) => {
|
|
117
|
+
if (ov.component != null) {
|
|
118
|
+
return {
|
|
119
|
+
type: OVERLAY_TYPE_CUSTOM,
|
|
120
|
+
options: {
|
|
121
|
+
create: (c: Connection<BrowserElement>) => {
|
|
122
|
+
const el = document.createElement(ELEMENT_DIV);
|
|
123
|
+
const overlayProps = {
|
|
124
|
+
data: c.edge.data,
|
|
125
|
+
model: surface.model,
|
|
126
|
+
ui: surface,
|
|
127
|
+
edge: c.edge,
|
|
128
|
+
vertex: c.edge, // Some components might expect vertex
|
|
129
|
+
...ov.props
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const holder: OverlayHolder = {
|
|
133
|
+
component: ov.component,
|
|
134
|
+
props: overlayProps,
|
|
135
|
+
edge: c.edge,
|
|
136
|
+
id: uuid(),
|
|
137
|
+
el
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
_overlays.push(holder);
|
|
141
|
+
_updateOverlayState();
|
|
142
|
+
return el;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
return ov;
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
84
153
|
function render ( id:string, data:ObjectData, model:BrowserUISvelteModel, type:string,
|
|
85
154
|
surface:Surface, def:any, modelObject:Vertex, eventInfo:any) {
|
|
86
155
|
|
|
@@ -179,7 +248,7 @@
|
|
|
179
248
|
};
|
|
180
249
|
|
|
181
250
|
const params = (renderOptions || {}) as SurfaceOptions;
|
|
182
|
-
params.view = viewOptions || {};
|
|
251
|
+
params.view = (viewOptions || {}) as any;
|
|
183
252
|
params.id = id;
|
|
184
253
|
|
|
185
254
|
if (shapeLibrary != null) {
|
|
@@ -188,6 +257,8 @@
|
|
|
188
257
|
};
|
|
189
258
|
}
|
|
190
259
|
|
|
260
|
+
_initialiseSvelteOverlays();
|
|
261
|
+
|
|
191
262
|
surface = renderSurface(model, container, templateRenderer, params);
|
|
192
263
|
|
|
193
264
|
// with continuous anchors it's necessary to do this, for
|
|
@@ -238,13 +309,29 @@
|
|
|
238
309
|
removeVertex(p.group.id)
|
|
239
310
|
});
|
|
240
311
|
|
|
312
|
+
const updateOverlays = (edgeId: string, eventPayload: EdgeUpdatedParams) => {
|
|
313
|
+
_overlays.forEach(o => {
|
|
314
|
+
if (o.edge.id === edgeId) {
|
|
315
|
+
o.props.data = eventPayload.edge.data;
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
_updateOverlayState();
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
const removeOverlays = (edgeId: string) => {
|
|
322
|
+
_overlays = _overlays.filter(o => o.edge.id !== edgeId);
|
|
323
|
+
_updateOverlayState();
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
model.bind<EdgeUpdatedParams>(EVENT_EDGE_UPDATED, (p) => updateOverlays(p.edge.id, p));
|
|
327
|
+
model.bind<EdgeRemovedParams>(EVENT_EDGE_REMOVED, (p) => removeOverlays(p.edge.id));
|
|
328
|
+
|
|
241
329
|
|
|
242
330
|
model.bind(EVENT_GRAPH_CLEARED, () => {
|
|
243
331
|
_vertices = []
|
|
244
332
|
_updateVertexState()
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
// _updateOverlayState()
|
|
333
|
+
_overlays = []
|
|
334
|
+
_updateOverlayState()
|
|
248
335
|
})
|
|
249
336
|
|
|
250
337
|
if (url != null) {
|
|
@@ -264,7 +351,15 @@
|
|
|
264
351
|
def={vertex.def}
|
|
265
352
|
vertex={vertex.vertex}
|
|
266
353
|
className={vertex.props.className}/>
|
|
354
|
+
{/each}
|
|
267
355
|
|
|
356
|
+
{#each overlayState.overlays as overlay (overlay.id)}
|
|
357
|
+
<OverlayWrapperComponent component={overlay.component}
|
|
358
|
+
data={overlay.props.data}
|
|
359
|
+
ui={surface}
|
|
360
|
+
edge={overlay.edge}
|
|
361
|
+
className="vjs-svelte-overlay"
|
|
362
|
+
el={overlay.el}/>
|
|
268
363
|
{/each}
|
|
269
364
|
{@render children?.()}
|
|
270
365
|
</div>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {PopupHandler, type Vertex, CLASS_SURFACE_POPUP} from "@visuallyjs/browser-ui";
|
|
3
|
+
import {useSurface} from "./use-surface.svelte";
|
|
4
|
+
import type {SurfacePopupProps} from "./definitions";
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
selector,
|
|
8
|
+
anchor,
|
|
9
|
+
popup
|
|
10
|
+
}:SurfacePopupProps = $props()
|
|
11
|
+
|
|
12
|
+
const surface = useSurface()
|
|
13
|
+
let container:HTMLElement
|
|
14
|
+
let initialized = false
|
|
15
|
+
|
|
16
|
+
let current = $state<Vertex|null>(null)
|
|
17
|
+
let display = $derived(current == null ? "none" : "block")
|
|
18
|
+
|
|
19
|
+
$effect(() => {
|
|
20
|
+
if (!initialized && surface.current && container) {
|
|
21
|
+
initialized = true
|
|
22
|
+
new PopupHandler(selector, container, surface.current, (v:Vertex|null) => current = v, anchor)
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<div bind:this={container} class={CLASS_SURFACE_POPUP} style:display={display} style:position="absolute">
|
|
29
|
+
{#if surface.current != null}
|
|
30
|
+
{@render popup(current, surface.current.model, surface.current)}
|
|
31
|
+
{/if}
|
|
32
|
+
</div>
|
package/WrapperComponent.svelte
CHANGED
package/components.d.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* list of exported Svelte components.
|
|
3
3
|
*/
|
|
4
4
|
export { default as SurfaceComponent } from "./SurfaceComponent.svelte";
|
|
5
|
+
export { default as PaperComponent } from "./PaperComponent.svelte";
|
|
5
6
|
export { default as DiagramComponent } from "./DiagramComponent.svelte";
|
|
6
7
|
export { default as ControlsComponent } from "./ControlsComponent.svelte";
|
|
7
8
|
export { default as ExportControlsComponent } from "./ExportControlsComponent.svelte";
|
|
@@ -14,6 +15,7 @@ export { default as DiagramPaletteComponent } from "./DiagramPaletteComponent.sv
|
|
|
14
15
|
export { default as ShapeComponent } from "./ShapeComponent.svelte";
|
|
15
16
|
export { default as EdgeTypePickerComponent } from "./EdgeTypePickerComponent.svelte";
|
|
16
17
|
export { default as ColorPickerComponent } from "./ColorPickerComponent.svelte";
|
|
18
|
+
export { default as SurfacePopup } from "./SurfacePopup.svelte";
|
|
17
19
|
export { default as ColumnChartComponent } from "./ColumnChartComponent.svelte";
|
|
18
20
|
export { default as BarChartComponent } from "./BarChartComponent.svelte";
|
|
19
21
|
export { default as XYChartComponent } from "./XYChartComponent.svelte";
|
|
@@ -25,5 +27,7 @@ export { default as BubbleChartComponent } from "./BubbleChartComponent.svelte";
|
|
|
25
27
|
export { default as GaugeChartComponent } from "./GaugeChartComponent.svelte";
|
|
26
28
|
export { default as SankeyChartComponent } from "./SankeyChartComponent.svelte";
|
|
27
29
|
export { default as WrapperComponent } from "./WrapperComponent.svelte";
|
|
30
|
+
export { default as OverlayWrapperComponent } from "./OverlayWrapperComponent.svelte";
|
|
28
31
|
export { default as DiagramProvider } from "./DiagramProvider.svelte";
|
|
29
32
|
export { default as SurfaceProvider } from "./SurfaceProvider.svelte";
|
|
33
|
+
export { default as PaperProvider } from "./PaperProvider.svelte";
|
package/components.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* list of exported Svelte components.
|
|
3
3
|
*/
|
|
4
4
|
export { default as SurfaceComponent } from "./SurfaceComponent.svelte";
|
|
5
|
+
export { default as PaperComponent } from "./PaperComponent.svelte";
|
|
5
6
|
export { default as DiagramComponent } from "./DiagramComponent.svelte";
|
|
6
7
|
export { default as ControlsComponent } from "./ControlsComponent.svelte";
|
|
7
8
|
export { default as ExportControlsComponent } from "./ExportControlsComponent.svelte";
|
|
@@ -14,6 +15,7 @@ export { default as DiagramPaletteComponent } from "./DiagramPaletteComponent.sv
|
|
|
14
15
|
export { default as ShapeComponent } from "./ShapeComponent.svelte";
|
|
15
16
|
export { default as EdgeTypePickerComponent } from "./EdgeTypePickerComponent.svelte";
|
|
16
17
|
export { default as ColorPickerComponent } from "./ColorPickerComponent.svelte";
|
|
18
|
+
export { default as SurfacePopup } from "./SurfacePopup.svelte";
|
|
17
19
|
export { default as ColumnChartComponent } from "./ColumnChartComponent.svelte";
|
|
18
20
|
export { default as BarChartComponent } from "./BarChartComponent.svelte";
|
|
19
21
|
export { default as XYChartComponent } from "./XYChartComponent.svelte";
|
|
@@ -25,5 +27,7 @@ export { default as BubbleChartComponent } from "./BubbleChartComponent.svelte";
|
|
|
25
27
|
export { default as GaugeChartComponent } from "./GaugeChartComponent.svelte";
|
|
26
28
|
export { default as SankeyChartComponent } from "./SankeyChartComponent.svelte";
|
|
27
29
|
export { default as WrapperComponent } from "./WrapperComponent.svelte";
|
|
30
|
+
export { default as OverlayWrapperComponent } from "./OverlayWrapperComponent.svelte";
|
|
28
31
|
export { default as DiagramProvider } from "./DiagramProvider.svelte";
|
|
29
32
|
export { default as SurfaceProvider } from "./SurfaceProvider.svelte";
|
|
33
|
+
export { default as PaperProvider } from "./PaperProvider.svelte";
|
package/definitions.d.ts
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { type Snippet } from "svelte";
|
|
2
2
|
import type { DOMAttributes } from "svelte/elements";
|
|
3
|
-
import { SurfaceOptions, Vertex, Group, Node, ControlsComponentButtons, DataGeneratorFunction, type BrowserElement, Base, Size, ObjectData, DropTargetInfo, PaletteMode, SvgExportUIOptions, ImageExportUIOptions, ShapeLibraryImpl, ModelOptions, DiagramOptions, Diagram, DiagramCell, NodeMapping, GroupMapping, PortMapping, BrowserUI, EdgeMapping, OnVertexAddedCallback, CanvasDropFilter, FontSpec, BrowserUIModel, PreparedShape, PointXY, FixedElementConstraints } from "@visuallyjs/browser-ui";
|
|
3
|
+
import { SurfaceOptions, Vertex, Group, Node, ControlsComponentButtons, DataGeneratorFunction, type BrowserElement, Base, Size, ObjectData, DropTargetInfo, PaletteMode, SvgExportUIOptions, ImageExportUIOptions, ShapeLibraryImpl, ModelOptions, DiagramOptions, Diagram, DiagramCell, NodeMapping, GroupMapping, PortMapping, BrowserUI, EdgeMapping, OnVertexAddedCallback, CanvasDropFilter, FontSpec, BrowserUIModel, PreparedShape, PointXY, FixedElementConstraints, PopupPosition, OverlaySpec, PaperOptions } from "@visuallyjs/browser-ui";
|
|
4
4
|
/**
|
|
5
5
|
* Render options for a SurfaceComponent. This interface is the same as SurfaceOptions but with several vanilla-only options removed.
|
|
6
6
|
*/
|
|
7
7
|
export interface SvelteSurfaceRenderOptions extends Omit<SurfaceOptions, "directRender" | "enhancedView" | "view" | "templates"> {
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Render options for a PaperComponent. This interface is the same as PaperOptions but with several vanilla-only options removed.
|
|
11
|
+
*/
|
|
12
|
+
export interface SveltePaperRenderOptions extends Omit<PaperOptions, "directRender" | "enhancedView" | "view" | "templates"> {
|
|
13
|
+
}
|
|
9
14
|
/**
|
|
10
15
|
* Definition of a node - its component, and behaviour.
|
|
11
16
|
*/
|
|
@@ -40,15 +45,23 @@ export type RefObject<T> = {
|
|
|
40
45
|
current: T | null;
|
|
41
46
|
};
|
|
42
47
|
/**
|
|
43
|
-
*
|
|
44
|
-
*/
|
|
45
|
-
/**
|
|
46
|
-
* Edge mappings for a view.
|
|
48
|
+
* Definition for an overlay when using Svelte components.
|
|
47
49
|
*/
|
|
50
|
+
export interface SvelteOverlaySpec {
|
|
51
|
+
/**
|
|
52
|
+
* Component used to render this overlay.
|
|
53
|
+
*/
|
|
54
|
+
component: any;
|
|
55
|
+
/**
|
|
56
|
+
* Props to pass to the component.
|
|
57
|
+
*/
|
|
58
|
+
props?: Record<string, any>;
|
|
59
|
+
}
|
|
48
60
|
/**
|
|
49
61
|
* Mapping definition for edges in a Svelte view.
|
|
50
62
|
*/
|
|
51
|
-
export interface SvelteEdgeMapping extends EdgeMapping {
|
|
63
|
+
export interface SvelteEdgeMapping extends Omit<EdgeMapping, "overlays"> {
|
|
64
|
+
overlays?: Array<OverlaySpec | SvelteOverlaySpec>;
|
|
52
65
|
}
|
|
53
66
|
/**
|
|
54
67
|
* Options for the view in the Svelte surface component. Maps node/group/port/edge types to components and behaviour.
|
|
@@ -71,6 +84,11 @@ export interface SvelteSurfaceViewOptions {
|
|
|
71
84
|
*/
|
|
72
85
|
edges?: Record<string, SvelteEdgeMapping>;
|
|
73
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Options for the view in the Svelte paper component. Maps node/group/port/edge types to components and behaviour.
|
|
89
|
+
*/
|
|
90
|
+
export interface SveltePaperViewOptions extends SvelteSurfaceViewOptions {
|
|
91
|
+
}
|
|
74
92
|
/**
|
|
75
93
|
* @group Props
|
|
76
94
|
*/
|
|
@@ -115,6 +133,56 @@ export interface SurfaceComponentProps extends DOMAttributes<HTMLDivElement> {
|
|
|
115
133
|
* Shape library to use to render SVG shapes. Optional.
|
|
116
134
|
*/
|
|
117
135
|
shapeLibrary?: ShapeLibraryImpl<ObjectData>;
|
|
136
|
+
/**
|
|
137
|
+
* An optional array of reactive objects. The properties from these objects will be
|
|
138
|
+
* merged into the props passed to each WrapperComponent, preserving reactivity.
|
|
139
|
+
*/
|
|
140
|
+
additionalProps?: Array<Record<string, any>>;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* @group Props
|
|
144
|
+
*/
|
|
145
|
+
export interface PaperComponentProps extends DOMAttributes<HTMLDivElement> {
|
|
146
|
+
/**
|
|
147
|
+
* @internal
|
|
148
|
+
*/
|
|
149
|
+
children?: Snippet;
|
|
150
|
+
/**
|
|
151
|
+
* Optional class name to set on the paper component's container
|
|
152
|
+
*/
|
|
153
|
+
className?: string;
|
|
154
|
+
/**
|
|
155
|
+
* Render options for the Paper.
|
|
156
|
+
*/
|
|
157
|
+
renderOptions?: SveltePaperRenderOptions;
|
|
158
|
+
/**
|
|
159
|
+
* View options for the Paper.
|
|
160
|
+
*/
|
|
161
|
+
viewOptions?: SveltePaperViewOptions;
|
|
162
|
+
/**
|
|
163
|
+
* Options for the underlying model instance.
|
|
164
|
+
*/
|
|
165
|
+
modelOptions?: ModelOptions;
|
|
166
|
+
/**
|
|
167
|
+
* Optional Visually JS instance to use. If this is not provided, a Visually JS instance will be created, with `modelOptions` if you provide them.
|
|
168
|
+
*/
|
|
169
|
+
model?: BrowserUIModel;
|
|
170
|
+
/**
|
|
171
|
+
* Optional function that is used to generate a set of props for a given vertex before rendering it. This provides a mechanism for you to inject specific items into the components you use to render your vertices. The return value of this function should be `Record<string, any>`. It may be null.
|
|
172
|
+
*/
|
|
173
|
+
injector?: (v: Vertex) => Record<string, any>;
|
|
174
|
+
/**
|
|
175
|
+
* Optional data to load after the component has been mounted.
|
|
176
|
+
*/
|
|
177
|
+
data?: any;
|
|
178
|
+
/**
|
|
179
|
+
* Optional url from which to load data after the component has been mounted. If you provide this and also data, this will take precedence.
|
|
180
|
+
*/
|
|
181
|
+
url?: string;
|
|
182
|
+
/**
|
|
183
|
+
* Shape library to use to render SVG shapes. Optional.
|
|
184
|
+
*/
|
|
185
|
+
shapeLibrary?: ShapeLibraryImpl<ObjectData>;
|
|
118
186
|
}
|
|
119
187
|
/**
|
|
120
188
|
* @group Props
|
|
@@ -613,3 +681,21 @@ export interface DecoratorComponentProps extends DOMAttributes<HTMLDivElement> {
|
|
|
613
681
|
*/
|
|
614
682
|
children?: Snippet;
|
|
615
683
|
}
|
|
684
|
+
/**
|
|
685
|
+
* Props for the SurfacePopup component.
|
|
686
|
+
* @group Props
|
|
687
|
+
*/
|
|
688
|
+
export interface SurfacePopupProps {
|
|
689
|
+
/**
|
|
690
|
+
* CSS3 selector identifying elements from which this popup is launched.
|
|
691
|
+
*/
|
|
692
|
+
selector: string;
|
|
693
|
+
/**
|
|
694
|
+
* Optional position to place this popup. Defaults to "bottom", and can also be overridden on a per-launcher basis via a DOM attribute.
|
|
695
|
+
*/
|
|
696
|
+
anchor?: PopupPosition;
|
|
697
|
+
/**
|
|
698
|
+
* The snippet that renders the content for the popup.
|
|
699
|
+
*/
|
|
700
|
+
popup: Snippet<[Vertex | null, BrowserUIModel, BrowserUI]>;
|
|
701
|
+
}
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@visuallyjs/browser-ui-svelte","version":"1.2.
|
|
1
|
+
{"name":"@visuallyjs/browser-ui-svelte","version":"1.2.1","description":"VisuallyJS Svelte integration for Browser UI renderer","module":"index.js","main":"index.js","types":"index.d.ts","svelte":"index.js","files":["**/*.d.ts","**/*.js","SurfaceComponent.svelte","PaperComponent.svelte","DecoratorComponent.svelte","DefaultGroupComponent.svelte","DefaultNodeComponent.svelte","MiniviewComponent.svelte","ControlsComponent.svelte","SurfaceProvider.svelte","PaperProvider.svelte","PaletteComponent.svelte","InspectorComponent.svelte","EdgeTypePickerComponent.svelte","ShapePaletteComponent.svelte","ExportControlsComponent.svelte","ShapeComponent.svelte","DiagramComponent.svelte","BarChartComponent.svelte","ColumnChartComponent.svelte","XYChartComponent.svelte","LineChartComponent.svelte","AreaChartComponent.svelte","PieChartComponent.svelte","WrapperComponent.svelte","OverlayWrapperComponent.svelte","DiagramProvider.svelte","DiagramPaletteComponent.svelte","ColorPickerComponent.svelte","ScatterChartComponent.svelte","BubbleChartComponent.svelte","GaugeChartComponent.svelte","SankeyChartComponent.svelte","SurfacePopup.svelte"],"author":"VisuallyJs <hello@visuallyjs.com> (https://visuallyjs.com)","license":"Commercial","dependencies":{"@visuallyjs/browser-ui":"1.2.1"},"homepage":"https://visuallyjs.com/svelte","bugs":"https://github.com/visuallyjs/visuallyjs/issues"}
|
package/surface-store.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Surface } from "@visuallyjs/browser-ui";
|
|
1
|
+
import type { Paper, Surface } from "@visuallyjs/browser-ui";
|
|
2
2
|
import { BrowserUISvelteModel } from "./index";
|
|
3
3
|
/**
|
|
4
4
|
* Key for the surface context
|
|
@@ -17,11 +17,24 @@ export interface SurfaceRef {
|
|
|
17
17
|
set: (surface: Surface) => void;
|
|
18
18
|
listen: (l: (s: Surface) => any) => void;
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Handle for a paper - use `set` to set the paper and `listen` to register a listener.
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
export interface PaperRef {
|
|
25
|
+
set: (paper: Paper) => void;
|
|
26
|
+
listen: (l: (s: Paper) => any) => void;
|
|
27
|
+
}
|
|
20
28
|
/**
|
|
21
29
|
* Create a surface context, and set it on Svelte via `setContext`.
|
|
22
30
|
* @internal
|
|
23
31
|
*/
|
|
24
32
|
export declare function internal_createSurfaceContext(): SurfaceRef;
|
|
33
|
+
/**
|
|
34
|
+
* Create a paper context, and set it on Svelte via `setContext`.
|
|
35
|
+
* @internal
|
|
36
|
+
*/
|
|
37
|
+
export declare function internal_createPaperContext(): PaperRef;
|
|
25
38
|
/**
|
|
26
39
|
* Gets the current surface context from Svelte, optionally creating it if it does not exist. The Surface and the SurfaceProvider both set `doNotCreate` to false; other components such as miniview/controls must set it to true.
|
|
27
40
|
* This method is NOT to be invoked by users of the API. Use {@link useSurface} to access the current Surface.
|
|
@@ -29,6 +42,13 @@ export declare function internal_createSurfaceContext(): SurfaceRef;
|
|
|
29
42
|
* @internal
|
|
30
43
|
*/
|
|
31
44
|
export declare function internal_getSurfaceContext(doNotCreate: boolean): SurfaceRef;
|
|
45
|
+
/**
|
|
46
|
+
* Gets the current paper context from Svelte, optionally creating it if it does not exist. The Paper and the PaperProvider both set `doNotCreate` to false; other components such as miniview/controls must set it to true.
|
|
47
|
+
* This method is NOT to be invoked by users of the API. Use {@link usePaper} to access the current Paper.
|
|
48
|
+
* @param doNotCreate
|
|
49
|
+
* @internal
|
|
50
|
+
*/
|
|
51
|
+
export declare function internal_getPaperContext(doNotCreate: boolean): PaperRef;
|
|
32
52
|
/**
|
|
33
53
|
* Hook to expose the current model. This hook is asynchronous and returns a Promise.
|
|
34
54
|
* @group Hooks
|
package/surface-store.js
CHANGED
|
@@ -29,6 +29,30 @@ export function internal_createSurfaceContext() {
|
|
|
29
29
|
setContext(STORE_KEY, ref);
|
|
30
30
|
return ref;
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Create a paper context, and set it on Svelte via `setContext`.
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
export function internal_createPaperContext() {
|
|
37
|
+
const listeners = [];
|
|
38
|
+
const handle = { current: null };
|
|
39
|
+
const ref = {
|
|
40
|
+
set: (paper) => {
|
|
41
|
+
handle.current = paper;
|
|
42
|
+
listeners.forEach(l => l(paper));
|
|
43
|
+
},
|
|
44
|
+
listen: (l) => {
|
|
45
|
+
if (handle.current == null) {
|
|
46
|
+
listeners.push(l);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
l(handle.current);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
setContext(STORE_KEY, ref);
|
|
54
|
+
return ref;
|
|
55
|
+
}
|
|
32
56
|
/**
|
|
33
57
|
* Gets the current surface context from Svelte, optionally creating it if it does not exist. The Surface and the SurfaceProvider both set `doNotCreate` to false; other components such as miniview/controls must set it to true.
|
|
34
58
|
* This method is NOT to be invoked by users of the API. Use {@link useSurface} to access the current Surface.
|
|
@@ -42,17 +66,34 @@ export function internal_getSurfaceContext(doNotCreate) {
|
|
|
42
66
|
}
|
|
43
67
|
return ctx;
|
|
44
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Gets the current paper context from Svelte, optionally creating it if it does not exist. The Paper and the PaperProvider both set `doNotCreate` to false; other components such as miniview/controls must set it to true.
|
|
71
|
+
* This method is NOT to be invoked by users of the API. Use {@link usePaper} to access the current Paper.
|
|
72
|
+
* @param doNotCreate
|
|
73
|
+
* @internal
|
|
74
|
+
*/
|
|
75
|
+
export function internal_getPaperContext(doNotCreate) {
|
|
76
|
+
let ctx = getContext(STORE_KEY);
|
|
77
|
+
if (ctx == null && !doNotCreate) {
|
|
78
|
+
ctx = internal_createPaperContext();
|
|
79
|
+
}
|
|
80
|
+
return ctx;
|
|
81
|
+
}
|
|
45
82
|
/**
|
|
46
83
|
* Hook to expose the current model. This hook is asynchronous and returns a Promise.
|
|
47
84
|
* @group Hooks
|
|
48
85
|
*/
|
|
49
86
|
export function useVisuallyJsModel() {
|
|
50
87
|
const ref = internal_getSurfaceContext(true);
|
|
88
|
+
const paperRef = internal_getPaperContext(true);
|
|
51
89
|
const diagramRef = internal_getDiagramContext(true);
|
|
52
90
|
return new Promise((resolve, reject) => {
|
|
53
91
|
if (ref != null) {
|
|
54
92
|
ref.listen((s) => resolve(s.model));
|
|
55
93
|
}
|
|
94
|
+
else if (paperRef != null) {
|
|
95
|
+
paperRef.listen((s) => resolve(s.model));
|
|
96
|
+
}
|
|
56
97
|
else if (diagramRef != null) {
|
|
57
98
|
diagramRef.listen((d) => resolve(d.model));
|
|
58
99
|
}
|