@likec4/diagram 1.24.0 → 1.24.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/LikeC4Diagram.css.d.ts +5 -0
- package/dist/LikeC4Diagram.css.js +1 -0
- package/dist/LikeC4Diagram.d.ts +1 -1
- package/dist/LikeC4Diagram.js +6 -2
- package/dist/LikeC4Diagram.props.d.ts +6 -0
- package/dist/base/BaseXYFlow.d.ts +1 -1
- package/dist/base/BaseXYFlow.js +12 -3
- package/dist/base/const.d.ts +1 -1
- package/dist/base/const.js +1 -1
- package/dist/base/primitives/compound/CompoundActionButton.css.js +2 -0
- package/dist/base/primitives/compound/CompoundDetailsButton.css.js +2 -0
- package/dist/base/primitives/compound/CompoundNodeContainer.css.d.ts +0 -1
- package/dist/base/primitives/compound/CompoundNodeContainer.css.js +4 -4
- package/dist/base/primitives/compound/CompoundNodeContainer.js +35 -22
- package/dist/base/primitives/compound/CompoundTitle.css.js +3 -1
- package/dist/base/primitives/customNode.js +1 -1
- package/dist/base/primitives/edge/EdgeContainer.js +5 -4
- package/dist/base/primitives/edge/EdgeLabel.css.d.ts +0 -1
- package/dist/base/primitives/edge/EdgeLabel.css.js +2 -5
- package/dist/base/primitives/edge/EdgeLabel.js +5 -5
- package/dist/base/primitives/edge/edge.css.d.ts +1 -1
- package/dist/base/primitives/edge/edge.css.js +4 -5
- package/dist/base/primitives/element/ElementActionButtons.css.js +2 -0
- package/dist/base/primitives/element/ElementActionButtons.js +4 -3
- package/dist/base/primitives/element/ElementDetailsButton.css.js +2 -0
- package/dist/base/primitives/element/ElementNodeContainer.css.js +2 -0
- package/dist/base/primitives/element/ElementNodeContainer.js +3 -1
- package/dist/base/primitives/element/ElementShape.css.js +4 -2
- package/dist/base/primitives/element/ElementShape.js +2 -3
- package/dist/base/primitives/element/ElementTitle.css.js +2 -0
- package/dist/base/primitives/element/styles.css.js +2 -0
- package/dist/components/SearchControl.css.js +2 -0
- package/dist/context/FramerMotionConfig.d.ts +9 -1
- package/dist/context/FramerMotionConfig.js +5 -2
- package/dist/context/RootContainer.js +13 -1
- package/dist/diagram.css +1 -1
- package/dist/globals.css.d.ts +2 -0
- package/dist/hooks/safeContext.js +1 -0
- package/dist/hooks/useDiagram.d.ts +554 -864
- package/dist/hooks/useDiagram.js +1 -0
- package/dist/hooks/useIsReducedGraphics.d.ts +4 -0
- package/dist/hooks/useIsReducedGraphics.js +8 -0
- package/dist/hooks/useXYFlow.js +1 -1
- package/dist/likec4diagram/DiagramUI.d.ts +2 -1
- package/dist/likec4diagram/DiagramUI.js +5 -3
- package/dist/likec4diagram/custom/nodes/nodeTypes.js +2 -2
- package/dist/likec4diagram/ui/controls/styles.css.js +2 -0
- package/dist/likec4diagram/ui/diagram-title/DiagramTitlePanel.css.js +2 -0
- package/dist/likec4diagram/ui/diagram-title/DiagramTitlePanel.js +3 -4
- package/dist/likec4diagram/ui/search/LikeC4Search.css.js +2 -0
- package/dist/overlays/element-details/ElementDetailsCard.js +12 -8
- package/dist/overlays/element-details/actor.d.ts +9084 -2569
- package/dist/overlays/overlay/Overlay.js +6 -3
- package/dist/overlays/relationship-details/RelationshipDetails.js +31 -17
- package/dist/overlays/relationship-details/actor.d.ts +228 -3
- package/dist/overlays/relationship-details/actor.js +86 -14
- package/dist/overlays/relationship-details/hooks.d.ts +3 -0
- package/dist/overlays/relationship-details/hooks.js +6 -2
- package/dist/overlays/relationships-browser/-useRelationshipsView.js +12 -3
- package/dist/overlays/relationships-browser/RelationshipsBrowser.js +12 -3
- package/dist/overlays/relationships-browser/actor.d.ts +271 -54
- package/dist/overlays/relationships-browser/actor.js +86 -23
- package/dist/state/DiagramActorProvider.js +12 -2
- package/dist/state/diagram-machine.d.ts +563 -867
- package/dist/state/diagram-machine.js +82 -81
- package/dist/state/persistence.d.ts +5 -0
- package/dist/state/persistence.js +23 -0
- package/package.json +9 -9
- package/src/LikeC4Diagram.css.ts +13 -5
- package/src/LikeC4Diagram.props.ts +7 -0
- package/src/LikeC4Diagram.tsx +33 -24
- package/src/base/BaseXYFlow.tsx +14 -9
- package/src/base/const.ts +1 -1
- package/src/base/primitives/compound/CompoundActionButton.css.ts +6 -0
- package/src/base/primitives/compound/CompoundDetailsButton.css.ts +4 -0
- package/src/base/primitives/compound/CompoundNodeContainer.css.ts +41 -59
- package/src/base/primitives/compound/CompoundNodeContainer.tsx +42 -22
- package/src/base/primitives/compound/CompoundTitle.css.ts +14 -13
- package/src/base/primitives/customNode.ts +3 -2
- package/src/base/primitives/edge/EdgeContainer.tsx +4 -3
- package/src/base/primitives/edge/EdgeLabel.css.ts +17 -11
- package/src/base/primitives/edge/EdgeLabel.tsx +4 -4
- package/src/base/primitives/edge/edge.css.ts +47 -27
- package/src/base/primitives/element/ElementActionButtons.css.ts +4 -0
- package/src/base/primitives/element/ElementActionButtons.tsx +4 -2
- package/src/base/primitives/element/ElementDetailsButton.css.ts +6 -8
- package/src/base/primitives/element/ElementNodeContainer.css.ts +18 -21
- package/src/base/primitives/element/ElementNodeContainer.tsx +3 -1
- package/src/base/primitives/element/ElementShape.css.ts +10 -6
- package/src/base/primitives/element/ElementShape.tsx +2 -2
- package/src/components/SearchControl.css.ts +11 -4
- package/src/context/FramerMotionConfig.tsx +13 -2
- package/src/context/RootContainer.tsx +9 -2
- package/src/globals.css.ts +3 -0
- package/src/hooks/safeContext.tsx +2 -1
- package/src/hooks/useDiagram.ts +1 -0
- package/src/hooks/useIsReducedGraphics.ts +5 -0
- package/src/hooks/useXYFlow.ts +1 -1
- package/src/likec4diagram/DiagramUI.tsx +5 -3
- package/src/likec4diagram/custom/nodes/nodeTypes.tsx +2 -2
- package/src/likec4diagram/ui/controls/styles.css.ts +11 -1
- package/src/likec4diagram/ui/diagram-title/DiagramTitlePanel.css.ts +10 -3
- package/src/likec4diagram/ui/diagram-title/DiagramTitlePanel.tsx +6 -3
- package/src/likec4diagram/ui/search/LikeC4Search.css.ts +1 -0
- package/src/overlays/element-details/ElementDetailsCard.tsx +238 -231
- package/src/overlays/overlay/Overlay.css.ts +1 -9
- package/src/overlays/overlay/Overlay.tsx +6 -3
- package/src/overlays/relationship-details/RelationshipDetails.tsx +83 -66
- package/src/overlays/relationship-details/actor.ts +106 -13
- package/src/overlays/relationship-details/hooks.ts +6 -2
- package/src/overlays/relationships-browser/-useRelationshipsView.ts +10 -0
- package/src/overlays/relationships-browser/RelationshipsBrowser.tsx +16 -8
- package/src/overlays/relationships-browser/actor.ts +92 -22
- package/src/state/DiagramActorProvider.tsx +13 -2
- package/src/state/diagram-machine.ts +80 -79
- package/src/state/persistence.ts +22 -0
|
@@ -62,6 +62,7 @@ import {
|
|
|
62
62
|
updateNodeData,
|
|
63
63
|
} from './assign'
|
|
64
64
|
import { type HotKeyEvent, hotkeyActorLogic } from './hotkeyActor'
|
|
65
|
+
import { DiagramToggledFeaturesPersistence } from './persistence'
|
|
65
66
|
import { type Events as SyncLayoutEvents, syncManualLayoutActorLogic } from './syncManualLayoutActor'
|
|
66
67
|
import { findDiagramNode, focusedBounds, typedSystem } from './utils'
|
|
67
68
|
|
|
@@ -197,7 +198,7 @@ export const diagramMachine = setup({
|
|
|
197
198
|
}
|
|
198
199
|
nonexhaustive(event.type)
|
|
199
200
|
},
|
|
200
|
-
'click: selected node
|
|
201
|
+
'click: selected node': ({ event }) => {
|
|
201
202
|
assertEvent(event, 'xyflow.nodeClick')
|
|
202
203
|
return event.node.selected === true
|
|
203
204
|
},
|
|
@@ -209,6 +210,10 @@ export const diagramMachine = setup({
|
|
|
209
210
|
assertEvent(event, 'xyflow.nodeClick')
|
|
210
211
|
return context.focusedNode === event.node.id
|
|
211
212
|
},
|
|
213
|
+
'click: node has connections': ({ context, event }) => {
|
|
214
|
+
assertEvent(event, 'xyflow.nodeClick')
|
|
215
|
+
return context.xyedges.some(e => e.source === event.node.id || e.target === event.node.id)
|
|
216
|
+
},
|
|
212
217
|
},
|
|
213
218
|
actions: {
|
|
214
219
|
'trigger:NavigateTo': (_, _params: { viewId: ViewId }) => {
|
|
@@ -220,22 +225,23 @@ export const diagramMachine = setup({
|
|
|
220
225
|
'trigger:OpenSource': (_, _params: OpenSourceParams) => {
|
|
221
226
|
},
|
|
222
227
|
|
|
223
|
-
'
|
|
224
|
-
|
|
225
|
-
|
|
228
|
+
'assign lastClickedNode': assign(({ context, event }) => {
|
|
229
|
+
assertEvent(event, 'xyflow.nodeClick')
|
|
230
|
+
return {
|
|
231
|
+
lastClickedNode: lastClickedNode({ context, event }),
|
|
232
|
+
}
|
|
233
|
+
}),
|
|
234
|
+
|
|
235
|
+
'open source of focused or last clicked node': enqueueActions(({ context, enqueue }) => {
|
|
236
|
+
const nodeId = context.focusedNode ?? context.lastClickedNode?.id
|
|
237
|
+
if (!nodeId || !context.features.enableVscode) return
|
|
238
|
+
const diagramNode = findDiagramNode(context, nodeId)
|
|
226
239
|
if (!diagramNode) return
|
|
227
240
|
|
|
228
|
-
enqueue.cancel('openSource')
|
|
229
241
|
if (DiagramNode.deploymentRef(diagramNode)) {
|
|
230
|
-
enqueue.raise({ type: 'open.source', deployment: DiagramNode.deploymentRef(diagramNode)! }
|
|
231
|
-
id: 'openSource',
|
|
232
|
-
delay: 100,
|
|
233
|
-
})
|
|
242
|
+
enqueue.raise({ type: 'open.source', deployment: DiagramNode.deploymentRef(diagramNode)! })
|
|
234
243
|
} else if (DiagramNode.modelRef(diagramNode)) {
|
|
235
|
-
enqueue.raise({ type: 'open.source', element: DiagramNode.modelRef(diagramNode)! }
|
|
236
|
-
id: 'openSource',
|
|
237
|
-
delay: 100,
|
|
238
|
-
})
|
|
244
|
+
enqueue.raise({ type: 'open.source', element: DiagramNode.modelRef(diagramNode)! })
|
|
239
245
|
}
|
|
240
246
|
}),
|
|
241
247
|
|
|
@@ -359,7 +365,7 @@ export const diagramMachine = setup({
|
|
|
359
365
|
context: ({ input, self, spawn }) => ({
|
|
360
366
|
...input,
|
|
361
367
|
features: { ...AllDisabled },
|
|
362
|
-
toggledFeatures: {
|
|
368
|
+
toggledFeatures: DiagramToggledFeaturesPersistence.read() ?? {
|
|
363
369
|
enableReadOnly: true,
|
|
364
370
|
},
|
|
365
371
|
initialized: false,
|
|
@@ -417,10 +423,11 @@ export const diagramMachine = setup({
|
|
|
417
423
|
{
|
|
418
424
|
// TODO: xstate fails to infer the type of the guard
|
|
419
425
|
guard: and([
|
|
420
|
-
'enabled: FocusMode'
|
|
426
|
+
'enabled: FocusMode',
|
|
427
|
+
'click: node has connections',
|
|
421
428
|
or([
|
|
422
|
-
'click: same node'
|
|
423
|
-
'click: selected node
|
|
429
|
+
'click: same node',
|
|
430
|
+
'click: selected node',
|
|
424
431
|
]),
|
|
425
432
|
]) as any,
|
|
426
433
|
actions: [
|
|
@@ -432,9 +439,10 @@ export const diagramMachine = setup({
|
|
|
432
439
|
target: 'focused',
|
|
433
440
|
},
|
|
434
441
|
{
|
|
435
|
-
actions:
|
|
436
|
-
lastClickedNode,
|
|
437
|
-
|
|
442
|
+
actions: [
|
|
443
|
+
'assign lastClickedNode',
|
|
444
|
+
'open source of focused or last clicked node',
|
|
445
|
+
],
|
|
438
446
|
},
|
|
439
447
|
],
|
|
440
448
|
'xyflow.paneClick': {
|
|
@@ -477,7 +485,7 @@ export const diagramMachine = setup({
|
|
|
477
485
|
...focusNodesEdges(s),
|
|
478
486
|
viewportBeforeFocus: { ...s.context.viewport },
|
|
479
487
|
})),
|
|
480
|
-
'open source of focused node',
|
|
488
|
+
'open source of focused or last clicked node',
|
|
481
489
|
spawnChild('hotkeyActorLogic', { id: 'hotkey' }),
|
|
482
490
|
{
|
|
483
491
|
type: 'xyflow:fitDiagram',
|
|
@@ -510,7 +518,7 @@ export const diagramMachine = setup({
|
|
|
510
518
|
focusedNode: ({ event }) => event.node.id as NodeId,
|
|
511
519
|
}),
|
|
512
520
|
assign(focusNodesEdges),
|
|
513
|
-
'open source of focused node',
|
|
521
|
+
'open source of focused or last clicked node',
|
|
514
522
|
{
|
|
515
523
|
type: 'xyflow:fitDiagram',
|
|
516
524
|
params: focusedBounds,
|
|
@@ -524,7 +532,7 @@ export const diagramMachine = setup({
|
|
|
524
532
|
focusedNode: ({ event }) => event.nodeId,
|
|
525
533
|
}),
|
|
526
534
|
assign(focusNodesEdges),
|
|
527
|
-
'open source of focused node',
|
|
535
|
+
'open source of focused or last clicked node',
|
|
528
536
|
{
|
|
529
537
|
type: 'xyflow:fitDiagram',
|
|
530
538
|
params: focusedBounds,
|
|
@@ -556,57 +564,16 @@ export const diagramMachine = setup({
|
|
|
556
564
|
},
|
|
557
565
|
// Navigating to another view (after `navigateTo` event)
|
|
558
566
|
navigating: {
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
enqueue({
|
|
567
|
-
type: 'trigger:NavigateTo',
|
|
568
|
-
params: ({ context }) => ({
|
|
569
|
-
viewId: nonNullable(context.lastOnNavigate, 'Invalid state, lastOnNavigate is null').toView,
|
|
570
|
-
}),
|
|
571
|
-
})
|
|
567
|
+
entry: [
|
|
568
|
+
'closeAllOverlays',
|
|
569
|
+
'stopSyncLayout',
|
|
570
|
+
{
|
|
571
|
+
type: 'trigger:NavigateTo',
|
|
572
|
+
params: ({ context }) => ({
|
|
573
|
+
viewId: nonNullable(context.lastOnNavigate, 'Invalid state, lastOnNavigate is null').toView,
|
|
572
574
|
}),
|
|
573
|
-
on: {
|
|
574
|
-
'update.view': {
|
|
575
|
-
actions: enqueueActions(({ enqueue, context, event }) => {
|
|
576
|
-
const { fromNode, toNode } = findCorrespondingNode(context, event)
|
|
577
|
-
if (fromNode && toNode) {
|
|
578
|
-
enqueue({
|
|
579
|
-
type: 'xyflow:alignNodeFromToAfterNavigate',
|
|
580
|
-
params: {
|
|
581
|
-
fromNode: fromNode.id,
|
|
582
|
-
toPosition: {
|
|
583
|
-
x: toNode.position[0],
|
|
584
|
-
y: toNode.position[1],
|
|
585
|
-
},
|
|
586
|
-
},
|
|
587
|
-
})
|
|
588
|
-
enqueue.raise({ type: 'fitDiagram' }, { id: 'fitDiagram', delay: 80 })
|
|
589
|
-
} else {
|
|
590
|
-
enqueue({
|
|
591
|
-
type: 'xyflow:setViewportCenter',
|
|
592
|
-
params: getBBoxCenter(event.view.bounds),
|
|
593
|
-
})
|
|
594
|
-
enqueue.raise({ type: 'fitDiagram', duration: 200 }, { id: 'fitDiagram', delay: 25 })
|
|
595
|
-
}
|
|
596
|
-
enqueue.assign(updateNavigationHistory)
|
|
597
|
-
enqueue.assign(mergeXYNodesEdges)
|
|
598
|
-
}),
|
|
599
|
-
target: 'done',
|
|
600
|
-
},
|
|
601
|
-
},
|
|
602
|
-
},
|
|
603
|
-
done: {
|
|
604
|
-
type: 'final',
|
|
605
575
|
},
|
|
606
|
-
|
|
607
|
-
onDone: {
|
|
608
|
-
target: 'idle',
|
|
609
|
-
},
|
|
576
|
+
],
|
|
610
577
|
exit: assign({
|
|
611
578
|
syncLayoutActorRef: ({ self, context, spawn }) =>
|
|
612
579
|
spawn('syncManualLayoutActorLogic', {
|
|
@@ -614,12 +581,44 @@ export const diagramMachine = setup({
|
|
|
614
581
|
systemId: 'syncLayout',
|
|
615
582
|
input: { parent: self, viewId: context.view.id },
|
|
616
583
|
}),
|
|
617
|
-
lastOnNavigate: null,
|
|
584
|
+
// lastOnNavigate: null,
|
|
618
585
|
}),
|
|
586
|
+
on: {
|
|
587
|
+
'update.view': {
|
|
588
|
+
actions: enqueueActions(({ enqueue, context, event }) => {
|
|
589
|
+
const { fromNode, toNode } = findCorrespondingNode(context, event)
|
|
590
|
+
if (fromNode && toNode) {
|
|
591
|
+
enqueue({
|
|
592
|
+
type: 'xyflow:alignNodeFromToAfterNavigate',
|
|
593
|
+
params: {
|
|
594
|
+
fromNode: fromNode.id,
|
|
595
|
+
toPosition: {
|
|
596
|
+
x: toNode.position[0],
|
|
597
|
+
y: toNode.position[1],
|
|
598
|
+
},
|
|
599
|
+
},
|
|
600
|
+
})
|
|
601
|
+
enqueue.raise({ type: 'fitDiagram' }, { id: 'fitDiagram', delay: 80 })
|
|
602
|
+
} else {
|
|
603
|
+
enqueue({
|
|
604
|
+
type: 'xyflow:setViewportCenter',
|
|
605
|
+
params: getBBoxCenter(event.view.bounds),
|
|
606
|
+
})
|
|
607
|
+
enqueue.raise({ type: 'fitDiagram', duration: 200 }, { id: 'fitDiagram', delay: 25 })
|
|
608
|
+
}
|
|
609
|
+
enqueue.assign(updateNavigationHistory)
|
|
610
|
+
enqueue.assign(mergeXYNodesEdges)
|
|
611
|
+
enqueue.assign({
|
|
612
|
+
lastOnNavigate: null,
|
|
613
|
+
})
|
|
614
|
+
}),
|
|
615
|
+
target: '#idle',
|
|
616
|
+
},
|
|
617
|
+
},
|
|
619
618
|
},
|
|
620
619
|
walkthrough: {
|
|
621
620
|
entry: [
|
|
622
|
-
|
|
621
|
+
spawnChild('hotkeyActorLogic', { id: 'hotkey' }),
|
|
623
622
|
assign({
|
|
624
623
|
viewportBeforeFocus: ({ context }) => context.viewport,
|
|
625
624
|
activeWalkthrough: ({ context, event }) => {
|
|
@@ -885,11 +884,13 @@ export const diagramMachine = setup({
|
|
|
885
884
|
},
|
|
886
885
|
'toggle.feature': {
|
|
887
886
|
actions: assign({
|
|
888
|
-
toggledFeatures: ({ context, event }) =>
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
887
|
+
toggledFeatures: ({ context, event }) => {
|
|
888
|
+
return DiagramToggledFeaturesPersistence.write({
|
|
889
|
+
...context.toggledFeatures,
|
|
890
|
+
[`enable${event.feature}`]: event.forceValue ??
|
|
891
|
+
!(context.toggledFeatures[`enable${event.feature}`] ?? context.features[`enable${event.feature}`]),
|
|
892
|
+
})
|
|
893
|
+
},
|
|
893
894
|
}),
|
|
894
895
|
},
|
|
895
896
|
},
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { isBoolean, pickBy } from 'remeda'
|
|
2
|
+
import type { EnabledFeatures } from '../context/DiagramFeatures'
|
|
3
|
+
|
|
4
|
+
const key = `likec4:diagram:toggledFeatures`
|
|
5
|
+
export const DiagramToggledFeaturesPersistence = {
|
|
6
|
+
read() {
|
|
7
|
+
try {
|
|
8
|
+
let fromStorage = sessionStorage.getItem(key)
|
|
9
|
+
if (fromStorage) {
|
|
10
|
+
return JSON.parse(fromStorage) as Partial<EnabledFeatures>
|
|
11
|
+
}
|
|
12
|
+
throw new Error(`Workspace ${key} not found`)
|
|
13
|
+
} catch (e) {
|
|
14
|
+
console.error(`Error reading fromStorage ${key}:`, e)
|
|
15
|
+
return null
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
write<F extends Partial<EnabledFeatures>>(toggledFeatures: F): F {
|
|
19
|
+
sessionStorage.setItem(key, JSON.stringify(pickBy(toggledFeatures, isBoolean)))
|
|
20
|
+
return toggledFeatures
|
|
21
|
+
},
|
|
22
|
+
}
|