@likec4/diagram 1.44.0 → 1.45.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/bundle/index.js +18160 -17671
- package/dist/LikeC4Diagram.js +7 -5
- package/dist/LikeC4Diagram.props.d.ts +9 -8
- package/dist/LikeC4Styles.js +0 -3
- package/dist/LikeC4View.d.ts +3 -3
- package/dist/LikeC4View.js +7 -3
- package/dist/ReactLikeC4.d.ts +2 -2
- package/dist/base/Base.d.ts +1 -1
- package/dist/base/updateEdges.js +25 -15
- package/dist/base/updateNodes.d.ts +14 -0
- package/dist/base/updateNodes.js +51 -18
- package/dist/base-primitives/Markdown.d.ts +30 -4
- package/dist/base-primitives/Markdown.js +3 -2
- package/dist/base-primitives/compound/CompoundActionButton.d.ts +3 -2
- package/dist/base-primitives/compound/CompoundDetailsButton.d.ts +3 -2
- package/dist/base-primitives/edge/EdgeActionButton.d.ts +3 -2
- package/dist/base-primitives/edge/EdgeContainer.d.ts +1 -1
- package/dist/base-primitives/edge/EdgeContainer.js +4 -1
- package/dist/base-primitives/edge/EdgeLabel.d.ts +2 -2
- package/dist/base-primitives/edge/EdgePath.js +24 -4
- package/dist/base-primitives/element/ElementActionButtons.d.ts +3 -2
- package/dist/base-primitives/element/ElementActionButtons.js +2 -2
- package/dist/base-primitives/element/ElementData.d.ts +3 -3
- package/dist/base-primitives/element/ElementData.js +13 -7
- package/dist/base-primitives/element/ElementDetailsButton.d.ts +3 -2
- package/dist/base-primitives/element/ElementDetailsButton.js +3 -0
- package/dist/base-primitives/element/ElementShape.js +5 -5
- package/dist/base-primitives/element/ElementTags.d.ts +6 -4
- package/dist/context/DiagramFeatures.d.ts +1 -0
- package/dist/context/TagStylesContext.js +1 -1
- package/dist/custom/hooks.d.ts +2 -2
- package/dist/custom/index.js +1 -1
- package/dist/hooks/index.d.ts +2 -1
- package/dist/hooks/useDiagramCompareLayout.js +7 -2
- package/dist/hooks/useLikeC4Project.d.ts +6 -1
- package/dist/hooks/useLikeC4Project.js +14 -2
- package/dist/hooks/useMediaPrint.d.ts +6 -0
- package/dist/likec4diagram/DiagramXYFlow.js +11 -6
- package/dist/likec4diagram/custom/edges/EdgeDrifts.d.ts +6 -0
- package/dist/likec4diagram/custom/edges/EdgeDrifts.js +38 -0
- package/dist/likec4diagram/custom/edges/RelationshipEdge.js +24 -14
- package/dist/likec4diagram/custom/edges/SequenceStepEdge.js +3 -1
- package/dist/likec4diagram/custom/edges/useControlPoints.js +3 -3
- package/dist/likec4diagram/custom/edges/useRelationshipEdgePath.js +5 -5
- package/dist/likec4diagram/custom/nodes/NodeDrifts.d.ts +6 -0
- package/dist/likec4diagram/custom/nodes/{ElementNodeDrifts.js → NodeDrifts.js} +8 -4
- package/dist/likec4diagram/custom/nodes/SequenceActorNode.js +4 -2
- package/dist/likec4diagram/custom/nodes/index.d.ts +1 -0
- package/dist/likec4diagram/custom/nodes/nodes.js +64 -23
- package/dist/likec4diagram/relationship-popover/RelationshipPopover.js +3 -3
- package/dist/likec4diagram/relationship-popover/actor.d.ts +1 -1
- package/dist/likec4diagram/state/DiagramActorProvider.d.ts +2 -2
- package/dist/likec4diagram/state/DiagramActorProvider.js +0 -1
- package/dist/likec4diagram/state/assign.d.ts +10 -6
- package/dist/likec4diagram/state/assign.js +17 -192
- package/dist/likec4diagram/state/createViewChange.js +15 -26
- package/dist/likec4diagram/state/diagram-api.d.ts +2 -6
- package/dist/likec4diagram/state/diagram-api.js +2 -10
- package/dist/likec4diagram/state/hotkeyActor.d.ts +0 -7
- package/dist/likec4diagram/state/hotkeyActor.js +1 -17
- package/dist/likec4diagram/state/machine.actions.d.ts +430 -746
- package/dist/likec4diagram/state/machine.actions.js +193 -284
- package/dist/likec4diagram/state/machine.actions.layout.d.ts +579 -0
- package/dist/likec4diagram/state/machine.actions.layout.js +129 -0
- package/dist/likec4diagram/state/machine.d.ts +17 -3712
- package/dist/likec4diagram/state/machine.js +59 -73
- package/dist/likec4diagram/state/machine.setup.d.ts +61 -18
- package/dist/likec4diagram/state/machine.setup.js +27 -5
- package/dist/likec4diagram/state/machine.state.initializing.d.ts +25 -0
- package/dist/likec4diagram/state/machine.state.initializing.js +5 -5
- package/dist/likec4diagram/state/machine.state.navigating.d.ts +5 -108
- package/dist/likec4diagram/state/machine.state.navigating.js +167 -34
- package/dist/likec4diagram/state/machine.state.ready.d.ts +2316 -2851
- package/dist/likec4diagram/state/machine.state.ready.focused.d.ts +386 -0
- package/dist/likec4diagram/state/machine.state.ready.focused.js +85 -0
- package/dist/likec4diagram/state/machine.state.ready.idle.d.ts +474 -0
- package/dist/likec4diagram/state/machine.state.ready.idle.js +96 -0
- package/dist/likec4diagram/state/machine.state.ready.js +144 -319
- package/dist/likec4diagram/state/machine.state.ready.printing.d.ts +128 -0
- package/dist/likec4diagram/state/machine.state.ready.printing.js +40 -0
- package/dist/likec4diagram/state/machine.state.ready.walkthrough.d.ts +511 -0
- package/dist/likec4diagram/state/machine.state.ready.walkthrough.js +177 -0
- package/dist/likec4diagram/state/mediaPrintActor.d.ts +12 -0
- package/dist/likec4diagram/state/mediaPrintActor.js +18 -0
- package/dist/likec4diagram/state/syncManualLayoutActor.d.ts +6 -240
- package/dist/likec4diagram/state/syncManualLayoutActor.js +150 -89
- package/dist/likec4diagram/state/types.d.ts +5 -7
- package/dist/likec4diagram/state/utils.d.ts +15 -2
- package/dist/likec4diagram/state/utils.js +43 -3
- package/dist/likec4diagram/types.d.ts +8 -13
- package/dist/likec4diagram/ui/notation/NotationPanel.css.js +5 -2
- package/dist/likec4diagram/useLayoutConstraints.js +107 -102
- package/dist/likec4diagram/xyflow-diagram/diagram-view.js +12 -15
- package/dist/likec4diagram/xyflow-sequence/sequence-layout.js +11 -8
- package/dist/navigationpanel/NavigationPanel.js +5 -1
- package/dist/navigationpanel/actor.d.ts +4 -204
- package/dist/navigationpanel/actor.js +1 -1
- package/dist/navigationpanel/controls/ToggleReadonly.js +8 -3
- package/dist/navigationpanel/walkthrough/DynamicViewControls.d.ts +66 -66
- package/dist/navigationpanel/walkthrough/WalkthroughPanel.js +4 -3
- package/dist/overlays/element-details/ElementDetailsCard.css.js +3 -3
- package/dist/overlays/element-details/MetadataValue.d.ts +2 -1
- package/dist/overlays/element-details/actor.d.ts +8 -83
- package/dist/overlays/element-details/actor.js +0 -8
- package/dist/overlays/overlay/Overlay.js +10 -10
- package/dist/overlays/overlaysActor.d.ts +7 -392
- package/dist/overlays/overlaysActor.js +67 -46
- package/dist/overlays/relationship-details/_types.d.ts +3 -4
- package/dist/overlays/relationship-details/actor.d.ts +6 -562
- package/dist/overlays/relationship-details/actor.js +1 -0
- package/dist/overlays/relationship-details/layout-to-xyflow.js +3 -5
- package/dist/overlays/relationship-details/layout.d.ts +3 -3
- package/dist/overlays/relationship-details/layout.js +4 -4
- package/dist/overlays/relationships-browser/_types.d.ts +2 -3
- package/dist/overlays/relationships-browser/actor.d.ts +7 -739
- package/dist/overlays/relationships-browser/layout.d.ts +2 -2
- package/dist/overlays/relationships-browser/layout.js +3 -3
- package/dist/overlays/relationships-browser/useViewToNodesEdges.js +0 -3
- package/dist/overlays/types.d.ts +12 -13
- package/dist/search/components/_shared.css.d.ts +1 -1
- package/dist/search/searchActor.d.ts +3 -66
- package/dist/shadowroot/ShadowRoot.d.ts +5 -7
- package/dist/shadowroot/ShadowRoot.js +7 -5
- package/dist/styles.css2.js +1 -1
- package/dist/utils/vector.d.ts +5 -0
- package/dist/utils/vector.js +7 -0
- package/dist/utils/view-bounds.js +7 -6
- package/dist/utils/xyflow.d.ts +4 -2
- package/dist/utils/xyflow.js +18 -50
- package/package.json +19 -18
- package/panda.buildinfo.json +17 -5
- package/styles-min.css +1 -1
- package/styles.css +1 -1
- package/dist/likec4diagram/custom/nodes/ElementNodeDrifts.d.ts +0 -4
package/dist/LikeC4Diagram.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import { useCustomCompareMemo } from '@react-hookz/web';
|
|
3
3
|
import { ReactFlowProvider } from '@xyflow/react';
|
|
4
|
+
import { deepEqual } from 'fast-equals';
|
|
4
5
|
import { useRef } from 'react';
|
|
5
6
|
import { isPlainObject, mapValues } from 'remeda';
|
|
6
7
|
import { RootContainer } from './components/RootContainer.js';
|
|
@@ -179,14 +180,15 @@ function useNormalizedViewPadding(raw) {
|
|
|
179
180
|
if (isPlainObject(raw)) {
|
|
180
181
|
return mapValues(raw, toLiteralPaddingWithUnit);
|
|
181
182
|
}
|
|
182
|
-
|
|
183
|
+
const v = toLiteralPaddingWithUnit(raw);
|
|
184
|
+
return {
|
|
185
|
+
x: v,
|
|
186
|
+
y: v
|
|
187
|
+
};
|
|
183
188
|
},
|
|
184
189
|
[raw],
|
|
185
|
-
|
|
190
|
+
deepEqual
|
|
186
191
|
);
|
|
187
192
|
}
|
|
188
|
-
const compareViewPaddingObject = ([a], [b]) => {
|
|
189
|
-
return a === b || isPlainObject(a) && isPlainObject(b) && a.bottom == b.bottom && a.left == b.left && a.right == b.right && a.top == b.top;
|
|
190
|
-
};
|
|
191
193
|
|
|
192
194
|
export { LikeC4Diagram };
|
|
@@ -29,6 +29,14 @@ export type LikeC4ColorScheme = 'light' | 'dark';
|
|
|
29
29
|
export type OverrideReactFlowProps = Pick<ReactFlowProps<Types.AnyNode, Types.AnyEdge>, 'paneClickDistance' | 'nodeClickDistance' | 'selectionKeyCode' | 'panActivationKeyCode' | 'multiSelectionKeyCode' | 'zoomActivationKeyCode' | 'snapToGrid' | 'snapGrid' | 'onlyRenderVisibleElements' | 'nodesDraggable' | 'nodesFocusable' | 'elementsSelectable' | 'selectNodesOnDrag' | 'panOnDrag' | 'preventScrolling' | 'zoomOnScroll' | 'zoomOnPinch' | 'panOnScroll' | 'panOnScrollSpeed' | 'panOnScrollMode' | 'zoomOnDoubleClick' | 'nodeDragThreshold'>;
|
|
30
30
|
export type PaddingUnit = 'px' | '%';
|
|
31
31
|
export type PaddingWithUnit = `${number}${PaddingUnit}` | number;
|
|
32
|
+
export type ViewPaddings = {
|
|
33
|
+
top?: PaddingWithUnit;
|
|
34
|
+
right?: PaddingWithUnit;
|
|
35
|
+
bottom?: PaddingWithUnit;
|
|
36
|
+
left?: PaddingWithUnit;
|
|
37
|
+
x?: PaddingWithUnit;
|
|
38
|
+
y?: PaddingWithUnit;
|
|
39
|
+
};
|
|
32
40
|
/**
|
|
33
41
|
* Padding around the diagram
|
|
34
42
|
*
|
|
@@ -45,14 +53,7 @@ export type PaddingWithUnit = `${number}${PaddingUnit}` | number;
|
|
|
45
53
|
* y: '16px',
|
|
46
54
|
* }
|
|
47
55
|
*/
|
|
48
|
-
export type ViewPadding = PaddingWithUnit |
|
|
49
|
-
top?: PaddingWithUnit;
|
|
50
|
-
right?: PaddingWithUnit;
|
|
51
|
-
bottom?: PaddingWithUnit;
|
|
52
|
-
left?: PaddingWithUnit;
|
|
53
|
-
x?: PaddingWithUnit;
|
|
54
|
-
y?: PaddingWithUnit;
|
|
55
|
-
};
|
|
56
|
+
export type ViewPadding = PaddingWithUnit | ViewPaddings;
|
|
56
57
|
export interface LikeC4DiagramProperties<A extends Any = Unknown> {
|
|
57
58
|
view: LayoutedView<A>;
|
|
58
59
|
className?: string | undefined;
|
package/dist/LikeC4Styles.js
CHANGED
|
@@ -7,7 +7,6 @@ import { useLikeC4Styles } from './hooks/useLikeC4Styles.js';
|
|
|
7
7
|
|
|
8
8
|
const scheme = (scheme2) => `[data-mantine-color-scheme="${scheme2}"]`;
|
|
9
9
|
const whenDark = scheme("dark");
|
|
10
|
-
const whenLight = scheme("light");
|
|
11
10
|
const MAX_DEPTH = 5;
|
|
12
11
|
const generateCompoundColors = (rootSelector, name, colors, depth) => {
|
|
13
12
|
const compoundDarkColor = (color) => toHex(
|
|
@@ -47,8 +46,6 @@ ${selector} {
|
|
|
47
46
|
--likec4-palette-relation-stroke: ${relationships.line};
|
|
48
47
|
--likec4-palette-relation-label: ${relationships.label};
|
|
49
48
|
--likec4-palette-relation-label-bg: ${relationships.labelBg};
|
|
50
|
-
}
|
|
51
|
-
${whenLight} ${selector} {
|
|
52
49
|
--likec4-palette-relation-stroke-selected: ${toRgba(mix(relationships.line, "black", 85))};
|
|
53
50
|
}
|
|
54
51
|
${whenDark} ${selector} {
|
package/dist/LikeC4View.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CSSProperties } from 'react';
|
|
1
|
+
import { CSSProperties, ReactNode } from 'react';
|
|
2
2
|
import { ElementIconRenderer, NodeRenderers, OverrideReactFlowProps, PaddingWithUnit, ViewPadding } from './LikeC4Diagram.props';
|
|
3
3
|
import type * as t from '@likec4/core/types';
|
|
4
4
|
export interface LikeC4ViewProps<A extends t.aux.Any = t.aux.UnknownLayouted> {
|
|
@@ -159,7 +159,7 @@ export interface LikeC4ViewProps<A extends t.aux.Any = t.aux.UnknownLayouted> {
|
|
|
159
159
|
/**
|
|
160
160
|
* Children to render inside the diagram (not inside the browser overlay)
|
|
161
161
|
*/
|
|
162
|
-
children?:
|
|
162
|
+
children?: ReactNode | undefined;
|
|
163
163
|
}
|
|
164
164
|
export interface LikeC4BrowserProps {
|
|
165
165
|
/**
|
|
@@ -250,7 +250,7 @@ export interface LikeC4BrowserProps {
|
|
|
250
250
|
/**
|
|
251
251
|
* Children to render inside the browser overlay
|
|
252
252
|
*/
|
|
253
|
-
children?:
|
|
253
|
+
children?: ReactNode | undefined;
|
|
254
254
|
}
|
|
255
255
|
/**
|
|
256
256
|
* Ready-to-use component to display embedded LikeC4 view,
|
package/dist/LikeC4View.js
CHANGED
|
@@ -2,7 +2,8 @@ import { jsx, jsxs } from 'react/jsx-runtime';
|
|
|
2
2
|
import { cx, css } from '@likec4/styles/css';
|
|
3
3
|
import { Box } from '@likec4/styles/jsx';
|
|
4
4
|
import { ActionIcon } from '@mantine/core';
|
|
5
|
-
import {
|
|
5
|
+
import { AnimatePresence } from 'motion/react';
|
|
6
|
+
import { useRef, useState } from 'react';
|
|
6
7
|
import { isBoolean } from 'remeda';
|
|
7
8
|
import { FitViewPaddings } from './base/const.js';
|
|
8
9
|
import { ErrorMessage, ViewNotFound } from './components/ViewNotFound.js';
|
|
@@ -49,6 +50,7 @@ function LikeC4View({
|
|
|
49
50
|
children,
|
|
50
51
|
...props
|
|
51
52
|
}) {
|
|
53
|
+
const rootRef = useRef(null);
|
|
52
54
|
const likec4model = useOptionalLikeC4Model();
|
|
53
55
|
const [layoutType, setLayoutType] = useState("manual");
|
|
54
56
|
const [browserViewId, _onNavigateTo] = useState(null);
|
|
@@ -82,9 +84,11 @@ function LikeC4View({
|
|
|
82
84
|
const isBrowserEnabled = browser !== false;
|
|
83
85
|
const browserProps = isBoolean(browser) ? {} : browser;
|
|
84
86
|
const bounds = pickViewBounds(view, props.dynamicViewVariant);
|
|
87
|
+
const root = rootRef.current ? { root: rootRef.current } : void 0;
|
|
85
88
|
return /* @__PURE__ */ jsx(
|
|
86
89
|
ShadowRoot,
|
|
87
90
|
{
|
|
91
|
+
ref: rootRef,
|
|
88
92
|
injectFontCss,
|
|
89
93
|
theme: mantineTheme,
|
|
90
94
|
colorScheme,
|
|
@@ -133,7 +137,7 @@ function LikeC4View({
|
|
|
133
137
|
...props
|
|
134
138
|
}
|
|
135
139
|
),
|
|
136
|
-
browserView && /* @__PURE__ */ jsxs(Overlay, { openDelay: 0, onClose: () => onNavigateTo(null), children: [
|
|
140
|
+
/* @__PURE__ */ jsx(AnimatePresence, { ...root, children: browserView && /* @__PURE__ */ jsxs(Overlay, { openDelay: 0, onClose: () => onNavigateTo(null), children: [
|
|
137
141
|
/* @__PURE__ */ jsx(
|
|
138
142
|
LikeC4Diagram,
|
|
139
143
|
{
|
|
@@ -175,7 +179,7 @@ function LikeC4View({
|
|
|
175
179
|
children: /* @__PURE__ */ jsx(IconX, {})
|
|
176
180
|
}
|
|
177
181
|
) })
|
|
178
|
-
] })
|
|
182
|
+
] }) })
|
|
179
183
|
] })
|
|
180
184
|
}
|
|
181
185
|
);
|
package/dist/ReactLikeC4.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CSSProperties } from 'react';
|
|
1
|
+
import { CSSProperties, ReactNode } from 'react';
|
|
2
2
|
import { Except } from 'type-fest';
|
|
3
3
|
import { LikeC4DiagramEventHandlers, LikeC4DiagramProperties } from './LikeC4Diagram.props';
|
|
4
4
|
import type * as t from '@likec4/core/types';
|
|
@@ -26,7 +26,7 @@ export type ReactLikeC4Props<A extends t.aux.Any = t.aux.UnknownLayouted> = {
|
|
|
26
26
|
mantineTheme?: any;
|
|
27
27
|
/** Function to generate nonce attribute added to all generated `<style />` tags */
|
|
28
28
|
styleNonce?: string | (() => string) | undefined;
|
|
29
|
-
children?:
|
|
29
|
+
children?: ReactNode | undefined;
|
|
30
30
|
} & Except<LikeC4DiagramProperties<A>, 'view', {
|
|
31
31
|
requireExactProps: true;
|
|
32
32
|
}> & LikeC4DiagramEventHandlers<A>;
|
package/dist/base/Base.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ type WithData<D> = {
|
|
|
16
16
|
data: D;
|
|
17
17
|
};
|
|
18
18
|
declare function setData<E extends WithData<any>>(value: E, state: Partial<E['data']>): E;
|
|
19
|
-
declare function setData<E extends WithData<any>>(state: Partial<E['data']
|
|
19
|
+
declare function setData<E extends WithData<any>>(state: Partial<NoInfer<E['data']>>): (value: E) => E;
|
|
20
20
|
export declare const Base: {
|
|
21
21
|
setDimmed: typeof setDimmed;
|
|
22
22
|
setHovered: typeof setHovered;
|
package/dist/base/updateEdges.js
CHANGED
|
@@ -1,22 +1,32 @@
|
|
|
1
1
|
import { deepEqual } from 'fast-equals';
|
|
2
|
-
import { isDefined,
|
|
2
|
+
import { isDefined, pickBy, isShallowEqual } from 'remeda';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
4
|
+
const EMPTY_OBJ = {};
|
|
5
|
+
function _update(current, updated) {
|
|
6
|
+
if (current === updated) {
|
|
7
|
+
return current;
|
|
8
|
+
}
|
|
9
|
+
updated = updated.map((update) => {
|
|
10
|
+
const existing = current.find(
|
|
11
|
+
(n) => n.id === update.id && n.type === update.type && n.source === update.source && n.target === update.target
|
|
12
|
+
);
|
|
13
|
+
if (!existing) {
|
|
14
|
+
return update;
|
|
15
|
+
}
|
|
16
|
+
const isSameData = deepEqual(existing.data, update.data);
|
|
17
|
+
const data = isSameData ? existing.data : update.data;
|
|
18
|
+
if (isSameData && deepEqual(existing.hidden, update.hidden ?? existing.hidden) && deepEqual(existing.selected, update.selected ?? existing.selected) && deepEqual(existing.selectable, update.selectable ?? existing.selectable) && deepEqual(existing.focusable, update.focusable ?? existing.focusable) && deepEqual(existing.animated, update.animated ?? existing.animated) && deepEqual(existing.className, update.className) && deepEqual(existing.zIndex, update.zIndex ?? existing.zIndex) && deepEqual(existing.label, update.label) && deepEqual(existing.sourceHandle, update.sourceHandle) && deepEqual(existing.targetHandle, update.targetHandle) && deepEqual(existing.style ?? EMPTY_OBJ, update.style ?? EMPTY_OBJ)) {
|
|
19
|
+
return existing;
|
|
17
20
|
}
|
|
18
|
-
return
|
|
21
|
+
return {
|
|
22
|
+
// Retain existing properties that are defined, except parentId
|
|
23
|
+
...pickBy(existing, isDefined),
|
|
24
|
+
// Apply updates, omitting undefined values
|
|
25
|
+
...pickBy(update, isDefined),
|
|
26
|
+
data
|
|
27
|
+
};
|
|
19
28
|
});
|
|
29
|
+
return isShallowEqual(current, updated) ? current : updated;
|
|
20
30
|
}
|
|
21
31
|
function updateEdges(current, update) {
|
|
22
32
|
if (isDefined(update)) {
|
|
@@ -1,3 +1,17 @@
|
|
|
1
1
|
import { BaseNode } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Updates nodes by merging existing nodes with updated nodes based on their IDs.
|
|
4
|
+
*
|
|
5
|
+
* Can be used in two ways:
|
|
6
|
+
* 1. By providing both current and updated node arrays:
|
|
7
|
+
* `const newNodes = updateNodes(currentNodes, updatedNodes);`
|
|
8
|
+
* 2. By providing only the updated node array, returning a function that takes the current nodes:
|
|
9
|
+
* `const updater = updateNodes(updatedNodes);
|
|
10
|
+
* const newNodes = updater(currentNodes);`
|
|
11
|
+
*
|
|
12
|
+
* @param current - The current array of nodes.
|
|
13
|
+
* @param update - The array of nodes with updates.
|
|
14
|
+
* @returns The updated array of nodes.
|
|
15
|
+
*/
|
|
2
16
|
export declare function updateNodes<N extends BaseNode>(current: N[], update: N[]): N[];
|
|
3
17
|
export declare function updateNodes<N extends BaseNode>(update: N[]): (current: N[]) => N[];
|
package/dist/base/updateNodes.js
CHANGED
|
@@ -1,34 +1,67 @@
|
|
|
1
1
|
import { getNodeDimensions } from '@xyflow/system';
|
|
2
2
|
import { deepEqual } from 'fast-equals';
|
|
3
|
-
import { isDefined,
|
|
3
|
+
import { isDefined, hasSubObject, pickBy, isShallowEqual } from 'remeda';
|
|
4
4
|
|
|
5
|
+
const EMPTY_OBJ = {};
|
|
5
6
|
function _update(current, updated) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
if (current === updated) {
|
|
8
|
+
return current;
|
|
9
|
+
}
|
|
10
|
+
updated = updated.map((update) => {
|
|
11
|
+
const existing = current.find((n) => n.id === update.id && n.type === update.type);
|
|
12
|
+
if (!existing) {
|
|
13
|
+
return update;
|
|
14
|
+
}
|
|
15
|
+
const isSameData = hasSubObject(existing.data, update.data);
|
|
16
|
+
let data = isSameData ? existing.data : update.data;
|
|
17
|
+
if (!isSameData) {
|
|
18
|
+
if (isDefined(existing.data.hovered) && !isDefined(update.data.hovered)) {
|
|
19
|
+
data = {
|
|
20
|
+
...data,
|
|
21
|
+
hovered: existing.data.hovered
|
|
22
|
+
};
|
|
13
23
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
24
|
+
if (isDefined(existing.data.dimmed) && !isDefined(update.data.dimmed)) {
|
|
25
|
+
data = {
|
|
26
|
+
...data,
|
|
27
|
+
dimmed: existing.data.dimmed
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const { width: existingWidth, height: existingHeight } = getNodeDimensions(existing);
|
|
32
|
+
const haveHandles = Object.hasOwn(existing, "handles") || Object.hasOwn(update, "handles");
|
|
33
|
+
const isSameHandles = !haveHandles || deepEqual(existing.handles ?? [], update.handles ?? []);
|
|
34
|
+
if (isSameData && isSameHandles && deepEqual(existingWidth, update.width ?? update.initialWidth) && deepEqual(existingHeight, update.height ?? update.initialHeight) && deepEqual(existing.parentId ?? null, update.parentId ?? null) && deepEqual(existing.hidden, update.hidden ?? existing.hidden) && deepEqual(existing.selected, update.selected ?? existing.selected) && deepEqual(existing.selectable, update.selectable ?? existing.selectable) && deepEqual(existing.focusable, update.focusable ?? existing.focusable) && deepEqual(existing.draggable, update.draggable ?? existing.draggable) && deepEqual(existing.dragHandle, update.dragHandle) && deepEqual(existing.className, update.className) && deepEqual(existing.zIndex, update.zIndex ?? existing.zIndex) && deepEqual(existing.position, update.position) && deepEqual(existing.domAttributes ?? EMPTY_OBJ, update.domAttributes ?? EMPTY_OBJ) && deepEqual(existing.style ?? EMPTY_OBJ, update.style ?? EMPTY_OBJ)) {
|
|
35
|
+
return existing;
|
|
22
36
|
}
|
|
23
|
-
|
|
37
|
+
const handles = haveHandles && isSameHandles ? existing.handles : update.handles;
|
|
38
|
+
return {
|
|
39
|
+
// Retain existing properties that are defined, except parentId
|
|
40
|
+
...pickBy(existing, (v, k) => isDefined(v) && k !== "parentId"),
|
|
41
|
+
// Retain measured dimensions from existing if present
|
|
42
|
+
..."measured" in existing && {
|
|
43
|
+
measured: {
|
|
44
|
+
width: update.width ?? update.initialWidth,
|
|
45
|
+
height: update.height ?? update.initialHeight
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
// Apply updates, omitting undefined values
|
|
49
|
+
...pickBy(update, isDefined),
|
|
50
|
+
// Force dimensions
|
|
51
|
+
width: update.width ?? update.initialWidth,
|
|
52
|
+
height: update.height ?? update.initialHeight,
|
|
53
|
+
...handles && { handles },
|
|
54
|
+
data
|
|
55
|
+
};
|
|
24
56
|
});
|
|
57
|
+
return isShallowEqual(current, updated) ? current : updated;
|
|
25
58
|
}
|
|
26
59
|
function updateNodes(current, update) {
|
|
27
60
|
if (isDefined(update)) {
|
|
28
61
|
return _update(current, update);
|
|
29
62
|
}
|
|
30
63
|
update = current;
|
|
31
|
-
return (
|
|
64
|
+
return (existing) => _update(existing, update);
|
|
32
65
|
}
|
|
33
66
|
|
|
34
67
|
export { updateNodes };
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { RichTextOrEmpty as RichTextType } from '@likec4/core/types';
|
|
2
|
-
import { BoxProps } from '@likec4/styles/jsx';
|
|
3
2
|
import { JsxStyleProps } from '@likec4/styles/types';
|
|
4
|
-
import { ForwardRefExoticComponent, RefAttributes } from 'react';
|
|
5
|
-
export type MarkdownProps = Omit<
|
|
3
|
+
import { ComponentPropsWithoutRef, ForwardRefExoticComponent, DetailedHTMLProps, HTMLAttributes, RefAttributes } from 'react';
|
|
4
|
+
export type MarkdownProps = Omit<ComponentPropsWithoutRef<'div'>, 'dangerouslySetInnerHTML' | 'children' | 'color'> & {
|
|
6
5
|
value: RichTextType;
|
|
7
6
|
/**
|
|
8
7
|
* When markdown block is used inside a diagram node, this variant should be used to apply the likec4 palette.
|
|
@@ -30,4 +29,31 @@ export type MarkdownProps = Omit<BoxProps, 'dangerouslySetInnerHTML' | 'children
|
|
|
30
29
|
*/
|
|
31
30
|
emptyText?: string;
|
|
32
31
|
};
|
|
33
|
-
export declare const Markdown: ForwardRefExoticComponent<Omit<
|
|
32
|
+
export declare const Markdown: ForwardRefExoticComponent<Omit<Omit< DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, "children" | "color" | "dangerouslySetInnerHTML"> & {
|
|
33
|
+
value: RichTextType;
|
|
34
|
+
/**
|
|
35
|
+
* When markdown block is used inside a diagram node, this variant should be used to apply the likec4 palette.
|
|
36
|
+
* @default false
|
|
37
|
+
*/
|
|
38
|
+
uselikec4palette?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Scale factor for the block
|
|
41
|
+
* @default 1
|
|
42
|
+
*/
|
|
43
|
+
textScale?: number;
|
|
44
|
+
/**
|
|
45
|
+
* Font size for the block
|
|
46
|
+
* @default 'md'
|
|
47
|
+
*/
|
|
48
|
+
fontSize?: (JsxStyleProps["fontSize"] & string) | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* If true, the component will not render anything if the value is empty.
|
|
51
|
+
* @default false
|
|
52
|
+
*/
|
|
53
|
+
hideIfEmpty?: boolean | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* Text to show if the value is empty.
|
|
56
|
+
* @default "no content"
|
|
57
|
+
*/
|
|
58
|
+
emptyText?: string;
|
|
59
|
+
} & RefAttributes<HTMLDivElement>>;
|
|
@@ -37,8 +37,9 @@ const Markdown = forwardRef(({
|
|
|
37
37
|
...fontSize && {
|
|
38
38
|
"--text-fz": `var(--font-sizes-${fontSize}, var(--font-sizes-md))`
|
|
39
39
|
},
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
...textScale !== 1 && {
|
|
41
|
+
["--mantine-scale"]: textScale
|
|
42
|
+
}
|
|
42
43
|
},
|
|
43
44
|
...content
|
|
44
45
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { MouseEvent as ReactMouseEvent, ReactNode } from 'react';
|
|
1
2
|
import { Simplify } from 'type-fest';
|
|
2
3
|
import { BaseNodeProps } from '../../base/types';
|
|
3
4
|
type CompoundActionButtonProps = Simplify<BaseNodeProps & {
|
|
4
|
-
icon?:
|
|
5
|
-
onClick: (e:
|
|
5
|
+
icon?: ReactNode;
|
|
6
|
+
onClick: (e: ReactMouseEvent) => void;
|
|
6
7
|
}>;
|
|
7
8
|
export declare function CompoundActionButton({ data: { hovered: isHovered, }, icon, onClick, }: CompoundActionButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
8
9
|
export {};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { MouseEvent as ReactMouseEvent, ReactNode } from 'react';
|
|
1
2
|
import { Simplify } from 'type-fest';
|
|
2
3
|
import { BaseNodeProps } from '../../base/types';
|
|
3
4
|
type CompoundDetailsButtonProps = Simplify<BaseNodeProps & {
|
|
4
|
-
icon?:
|
|
5
|
-
onClick: (e:
|
|
5
|
+
icon?: ReactNode;
|
|
6
|
+
onClick: (e: ReactMouseEvent) => void;
|
|
6
7
|
}>;
|
|
7
8
|
export declare function CompoundDetailsButton({ data: { hovered: isHovered, }, icon, onClick, }: CompoundDetailsButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
8
9
|
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { MouseEvent as ReactMouseEvent, ReactNode } from 'react';
|
|
1
2
|
type EdgeActionBtnProps = {
|
|
2
|
-
icon?:
|
|
3
|
-
onClick: (e:
|
|
3
|
+
icon?: ReactNode;
|
|
4
|
+
onClick: (e: ReactMouseEvent) => void;
|
|
4
5
|
};
|
|
5
6
|
export declare function EdgeActionButton({ icon, onClick }: EdgeActionBtnProps): import("react/jsx-runtime").JSX.Element;
|
|
6
7
|
export {};
|
|
@@ -7,5 +7,5 @@ type EdgeContainerProps = PropsWithChildren<BaseEdgePropsWithData<Data> & {
|
|
|
7
7
|
component?: 'g' | 'svg' | undefined;
|
|
8
8
|
className?: string | undefined;
|
|
9
9
|
}>;
|
|
10
|
-
export declare function EdgeContainer({ className, component, selected, data: { color, hovered: isHovered, active: isActive, dimmed: isDimmed, ...data }, children, style, }: EdgeContainerProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export declare function EdgeContainer({ className, component, selectable, selected, data: { color, hovered: isHovered, active: isActive, dimmed: isDimmed, ...data }, children, style, }: EdgeContainerProps): import("react/jsx-runtime").JSX.Element;
|
|
11
11
|
export {};
|
|
@@ -6,6 +6,7 @@ import { edgeContainer } from './edge.css.js';
|
|
|
6
6
|
function EdgeContainer({
|
|
7
7
|
className,
|
|
8
8
|
component = "g",
|
|
9
|
+
selectable = false,
|
|
9
10
|
selected = false,
|
|
10
11
|
data: {
|
|
11
12
|
color = "gray",
|
|
@@ -21,7 +22,9 @@ function EdgeContainer({
|
|
|
21
22
|
className: cx(
|
|
22
23
|
className,
|
|
23
24
|
edgeContainer,
|
|
24
|
-
"likec4-edge-container"
|
|
25
|
+
"likec4-edge-container",
|
|
26
|
+
selected && "selected",
|
|
27
|
+
selectable && "selectable"
|
|
25
28
|
),
|
|
26
29
|
"data-likec4-color": color,
|
|
27
30
|
"data-edge-dir": data.dir ?? "forward",
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { DiagramEdge } from '@likec4/core/types';
|
|
2
2
|
import { HTMLMotionProps } from 'motion/react';
|
|
3
|
+
import { ReactNode, ForwardRefExoticComponent, RefAttributes } from 'react';
|
|
3
4
|
import { UndefinedOnPartialDeep } from 'type-fest';
|
|
4
5
|
import { BaseEdgePropsWithData } from '../../base/types';
|
|
5
|
-
import { ForwardRefExoticComponent, RefAttributes } from 'react';
|
|
6
6
|
type Data = UndefinedOnPartialDeep<Pick<DiagramEdge, 'label' | 'technology'>>;
|
|
7
7
|
type EdgeLabelProps = HTMLMotionProps<'div'> & {
|
|
8
|
-
children?:
|
|
8
|
+
children?: ReactNode;
|
|
9
9
|
edgeProps: BaseEdgePropsWithData<Data>;
|
|
10
10
|
pointerEvents?: 'all' | 'none';
|
|
11
11
|
};
|
|
@@ -39,7 +39,7 @@ const EdgePath = forwardRef(({
|
|
|
39
39
|
strokeDasharray = "8,10";
|
|
40
40
|
}
|
|
41
41
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
42
|
-
selectable &&
|
|
42
|
+
selectable && /* @__PURE__ */ jsx(
|
|
43
43
|
"path",
|
|
44
44
|
{
|
|
45
45
|
className: cx(
|
|
@@ -53,22 +53,42 @@ const EdgePath = forwardRef(({
|
|
|
53
53
|
style: {
|
|
54
54
|
strokeWidth: interactionWidth ?? 10,
|
|
55
55
|
stroke: "currentcolor",
|
|
56
|
-
strokeOpacity: 0
|
|
56
|
+
strokeOpacity: 0,
|
|
57
|
+
...isDragging ? { display: "none" } : {}
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
60
|
),
|
|
61
|
+
/* @__PURE__ */ jsx(
|
|
62
|
+
"circle",
|
|
63
|
+
{
|
|
64
|
+
className: cx(
|
|
65
|
+
"edge-center-point",
|
|
66
|
+
css({
|
|
67
|
+
visibility: "hidden",
|
|
68
|
+
offsetDistance: "50%"
|
|
69
|
+
})
|
|
70
|
+
),
|
|
71
|
+
style: {
|
|
72
|
+
offsetPath: `path("${svgPath}")`
|
|
73
|
+
},
|
|
74
|
+
cx: 0,
|
|
75
|
+
cy: 0,
|
|
76
|
+
r: 2
|
|
77
|
+
}
|
|
78
|
+
),
|
|
60
79
|
/* @__PURE__ */ jsxs("g", { className: markerContext, onPointerDown: onEdgePointerDown, children: [
|
|
61
80
|
/* @__PURE__ */ jsxs("defs", { children: [
|
|
62
81
|
MarkerStart && /* @__PURE__ */ jsx(MarkerStart, { id: "start" + id }),
|
|
63
82
|
MarkerEnd && /* @__PURE__ */ jsx(MarkerEnd, { id: "end" + id })
|
|
64
83
|
] }),
|
|
65
|
-
|
|
84
|
+
/* @__PURE__ */ jsx(
|
|
66
85
|
"path",
|
|
67
86
|
{
|
|
68
87
|
className: cx(
|
|
69
88
|
"react-flow__edge-path",
|
|
70
89
|
"hide-on-reduced-graphics",
|
|
71
|
-
edgePathBg
|
|
90
|
+
edgePathBg,
|
|
91
|
+
isDragging && css({ display: "none" })
|
|
72
92
|
),
|
|
73
93
|
d: svgPath,
|
|
74
94
|
style,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { MouseEvent as ReactMouseEvent, ReactNode } from 'react';
|
|
1
2
|
type ElementActionButtonsProps = {
|
|
2
3
|
selected?: boolean;
|
|
3
4
|
data: {
|
|
@@ -34,8 +35,8 @@ export declare function ElementActionButtons({ selected, data: { hovered: isHove
|
|
|
34
35
|
export declare namespace ElementActionButtons {
|
|
35
36
|
type Item = {
|
|
36
37
|
key?: string;
|
|
37
|
-
icon?:
|
|
38
|
-
onClick: (e:
|
|
38
|
+
icon?: ReactNode;
|
|
39
|
+
onClick: (e: ReactMouseEvent) => void;
|
|
39
40
|
};
|
|
40
41
|
}
|
|
41
42
|
export {};
|
|
@@ -58,6 +58,7 @@ function ElementActionButtons({
|
|
|
58
58
|
scale: isHovered ? 1.1 : selected ? 0.9 : 0.8,
|
|
59
59
|
y: isHovered || selected ? 6 : 0
|
|
60
60
|
},
|
|
61
|
+
layoutDependency: `${isHovered}-${selected}`,
|
|
61
62
|
"data-likec4-hovered": isHovered,
|
|
62
63
|
className: cx("nodrag nopan", actionButtons),
|
|
63
64
|
children: buttons.map((button, index) => /* @__PURE__ */ jsx(
|
|
@@ -76,8 +77,7 @@ function ElementActionButtons({
|
|
|
76
77
|
},
|
|
77
78
|
`${id}-${button.key ?? index}`
|
|
78
79
|
))
|
|
79
|
-
}
|
|
80
|
-
`${id}-action-buttons`
|
|
80
|
+
}
|
|
81
81
|
)
|
|
82
82
|
}
|
|
83
83
|
);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ComputedNodeStyle, NodeId } from '@likec4/core';
|
|
2
|
-
import { Color
|
|
1
|
+
import { ComputedNodeStyle, MarkdownOrString, NodeId } from '@likec4/core';
|
|
2
|
+
import { Color } from '@likec4/core/types';
|
|
3
3
|
import { CSSProperties, DetailedHTMLProps, HTMLAttributes } from 'react';
|
|
4
4
|
type RequiredData = {
|
|
5
5
|
id: NodeId;
|
|
@@ -7,7 +7,7 @@ type RequiredData = {
|
|
|
7
7
|
technology?: string | null | undefined;
|
|
8
8
|
color: Color;
|
|
9
9
|
style: ComputedNodeStyle;
|
|
10
|
-
description?:
|
|
10
|
+
description?: MarkdownOrString | null | undefined;
|
|
11
11
|
icon?: string | null;
|
|
12
12
|
};
|
|
13
13
|
type ElementDataProps = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { ensureSizes } from '@likec4/core/types';
|
|
3
|
-
import { cx } from '@likec4/styles/css';
|
|
2
|
+
import { ensureSizes, RichText } from '@likec4/core/types';
|
|
3
|
+
import { cx, css } from '@likec4/styles/css';
|
|
4
4
|
import { elementNodeData } from '@likec4/styles/recipes';
|
|
5
5
|
import { Text } from '@mantine/core';
|
|
6
6
|
import { forwardRef } from 'react';
|
|
@@ -69,9 +69,10 @@ const Technology = forwardRef(({ data, children, className, ...props }, ref) =>
|
|
|
69
69
|
) : null;
|
|
70
70
|
});
|
|
71
71
|
const Description = forwardRef(({ data: { description, style }, className, ...props }, ref) => {
|
|
72
|
-
if (!description
|
|
72
|
+
if (!description) {
|
|
73
73
|
return null;
|
|
74
74
|
}
|
|
75
|
+
const desc = RichText.from(description);
|
|
75
76
|
const { size } = ensureSizes(style);
|
|
76
77
|
const isSm = size === "sm" || size === "xs";
|
|
77
78
|
return /* @__PURE__ */ jsx(
|
|
@@ -80,14 +81,19 @@ const Description = forwardRef(({ data: { description, style }, className, ...pr
|
|
|
80
81
|
...props,
|
|
81
82
|
className: cx(
|
|
82
83
|
className,
|
|
83
|
-
"likec4-element-description"
|
|
84
|
+
"likec4-element-description",
|
|
85
|
+
css({
|
|
86
|
+
lineClamp: isSm ? 3 : 5
|
|
87
|
+
})
|
|
84
88
|
),
|
|
85
89
|
"data-likec4-node-description": "",
|
|
86
|
-
value:
|
|
90
|
+
value: desc,
|
|
87
91
|
uselikec4palette: true,
|
|
88
92
|
hideIfEmpty: true,
|
|
89
|
-
|
|
90
|
-
|
|
93
|
+
style: {
|
|
94
|
+
// Workaround for lineClamp not working with nested TABLE elements (if markdown has tables)
|
|
95
|
+
maxHeight: desc.isMarkdown ? "8rem" : void 0
|
|
96
|
+
},
|
|
91
97
|
ref
|
|
92
98
|
}
|
|
93
99
|
);
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { MouseEvent as ReactMouseEvent, ReactNode } from 'react';
|
|
1
2
|
import { BaseNodeData } from '../../base/types';
|
|
2
3
|
type ElementDetailsButtonProps = {
|
|
3
4
|
selected?: boolean;
|
|
4
5
|
data: BaseNodeData;
|
|
5
|
-
icon?:
|
|
6
|
-
onClick: (e:
|
|
6
|
+
icon?: ReactNode;
|
|
7
|
+
onClick: (e: ReactMouseEvent) => void;
|
|
7
8
|
};
|
|
8
9
|
export declare function ElementDetailsButton({ selected, data: { hovered: isHovered, }, icon, onClick, }: ElementDetailsButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
9
10
|
export {};
|