@likec4/diagram 1.0.0-next.1 → 1.0.0-next.11
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/cjs/index.cjs +4596 -0
- package/dist/esm/index.mjs +4596 -0
- package/dist/style.css +1 -1
- package/dist/{EmbeddedLikeC4Diagram.css.d.ts → types/EmbeddedLikeC4Diagram.css.d.ts} +0 -1
- package/dist/{EmbeddedLikeC4Diagram.d.ts → types/EmbeddedLikeC4Diagram.d.ts} +0 -1
- package/dist/{LikeC4Diagram.css.d.ts → types/LikeC4Diagram.css.d.ts} +0 -1
- package/dist/{LikeC4Diagram.d.ts → types/LikeC4Diagram.d.ts} +0 -1
- package/dist/{LikeC4Diagram.props.d.ts → types/LikeC4Diagram.props.d.ts} +5 -5
- package/dist/{StaticLikeC4Diagram.d.ts → types/StaticLikeC4Diagram.d.ts} +0 -1
- package/dist/{hooks → types/hooks}/index.d.ts +0 -1
- package/dist/{hooks → types/hooks}/use-set-state.d.ts +0 -1
- package/dist/types/hooks/use-update-effect.d.ts +3 -0
- package/dist/{icons → types/icons}/Clipboard.d.ts +0 -1
- package/dist/{icons → types/icons}/Link.d.ts +0 -1
- package/dist/{icons → types/icons}/ZoomIn.d.ts +0 -1
- package/dist/{icons → types/icons}/index.d.ts +0 -1
- package/dist/types/index.css.d.ts +1 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/{mantine → types/mantine}/EnsureMantine.d.ts +0 -1
- package/dist/{mantine → types/mantine}/index.d.ts +0 -1
- package/dist/{state → types/state}/DiagramState.d.ts +0 -1
- package/dist/types/state/index.d.ts +1 -0
- package/dist/{theme.css.d.ts → types/theme.css.d.ts} +0 -1
- package/dist/{ui → types/ui}/Camera.d.ts +0 -1
- package/dist/types/ui/KeepAspectRatio.css.d.ts +1 -0
- package/dist/{ui → types/ui}/KeepAspectRatio.d.ts +0 -1
- package/dist/types/ui/OptionsPanel.css.d.ts +1 -0
- package/dist/{ui → types/ui}/OptionsPanel.d.ts +0 -1
- package/dist/{ui → types/ui}/index.d.ts +0 -1
- package/dist/{ui → types/ui}/options/NodeOptions.d.ts +0 -1
- package/dist/types/xyflow/FitviewOnDiagramChange.d.ts +4 -0
- package/dist/{xyflow → types/xyflow}/UpdateOnDiagramChange.d.ts +0 -1
- package/dist/{xyflow → types/xyflow}/XYFlowBackground.d.ts +0 -1
- package/dist/{xyflow → types/xyflow}/XYFlowEvents.d.ts +5 -6
- package/dist/{xyflow → types/xyflow}/XYFlowWrapper.d.ts +0 -1
- package/dist/{xyflow → types/xyflow}/const.d.ts +1 -2
- package/dist/{xyflow → types/xyflow}/diagram-to-xyflow.d.ts +0 -1
- package/dist/{xyflow → types/xyflow}/edges/RelationshipEdge.d.ts +0 -1
- package/dist/{xyflow → types/xyflow}/edges/edges.css.d.ts +0 -1
- package/dist/{xyflow → types/xyflow}/edges/utils.d.ts +0 -1
- package/dist/{xyflow → types/xyflow}/hooks/index.d.ts +0 -1
- package/dist/{xyflow → types/xyflow}/hooks/use-layout-/321/201onstraints.d.ts +0 -1
- package/dist/{xyflow → types/xyflow}/nodes/compound/CompoundNode.css.d.ts +0 -1
- package/dist/{xyflow → types/xyflow}/nodes/compound/CompoundNode.d.ts +0 -1
- package/dist/{xyflow → types/xyflow}/nodes/compound/index.d.ts +0 -1
- package/dist/{xyflow → types/xyflow}/nodes/element/ElementIcon.d.ts +0 -1
- package/dist/{xyflow → types/xyflow}/nodes/element/ElementLink.css.d.ts +0 -1
- package/dist/{xyflow → types/xyflow}/nodes/element/ElementLink.d.ts +0 -1
- package/dist/types/xyflow/nodes/element/ElementNode.d.ts +7 -0
- package/dist/{xyflow → types/xyflow}/nodes/element/ElementShapeSvg.d.ts +0 -1
- package/dist/{xyflow → types/xyflow}/nodes/element/element.css.d.ts +0 -1
- package/dist/{xyflow → types/xyflow}/nodes/element/index.d.ts +0 -1
- package/dist/{xyflow → types/xyflow}/nodes/shared/NavigateToBtn.d.ts +0 -1
- package/dist/{xyflow → types/xyflow}/types.d.ts +0 -1
- package/dist/{xyflow → types/xyflow}/utils.d.ts +0 -1
- package/package.json +29 -45
- package/dist/bundle.d.ts +0 -12
- package/dist/bundle.js +0 -30
- package/dist/hooks/use-update-effect.d.ts +0 -4
- package/dist/index-DClug9zV.js +0 -23964
- package/dist/index.css.d.ts +0 -2
- package/dist/index.d.ts +0 -7
- package/dist/index.js +0 -1
- package/dist/state/index.d.ts +0 -2
- package/dist/ui/KeepAspectRatio.css.d.ts +0 -2
- package/dist/ui/OptionsPanel.css.d.ts +0 -2
- package/dist/xyflow/FitviewOnDiagramChange.d.ts +0 -6
- package/dist/xyflow/nodes/element/ElementNode.d.ts +0 -7
|
@@ -0,0 +1,4596 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
|
+
var __publicField = (obj, key, value) => {
|
|
5
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
6
|
+
return value;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
9
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
10
|
+
const core$1 = require("@likec4/core");
|
|
11
|
+
const core = require("@mantine/core");
|
|
12
|
+
const react = require("react");
|
|
13
|
+
const react$1 = require("@xyflow/react");
|
|
14
|
+
const clsx = require("clsx");
|
|
15
|
+
const reactTracked = require("react-tracked");
|
|
16
|
+
const framerMotion = require("framer-motion");
|
|
17
|
+
var scope = "_2t65ix0";
|
|
18
|
+
function useSyncedRef(value) {
|
|
19
|
+
const ref = react.useRef(value);
|
|
20
|
+
ref.current = value;
|
|
21
|
+
return react.useMemo(() => Object.freeze({
|
|
22
|
+
get current() {
|
|
23
|
+
return ref.current;
|
|
24
|
+
}
|
|
25
|
+
}), []);
|
|
26
|
+
}
|
|
27
|
+
function useUnmountEffect(effect) {
|
|
28
|
+
const effectRef = useSyncedRef(effect);
|
|
29
|
+
react.useEffect(() => () => {
|
|
30
|
+
effectRef.current();
|
|
31
|
+
}, []);
|
|
32
|
+
}
|
|
33
|
+
function useDebouncedCallback(callback, deps, delay, maxWait = 0) {
|
|
34
|
+
const timeout = react.useRef();
|
|
35
|
+
const waitTimeout = react.useRef();
|
|
36
|
+
const cb = react.useRef(callback);
|
|
37
|
+
const lastCall = react.useRef();
|
|
38
|
+
const clear = () => {
|
|
39
|
+
if (timeout.current) {
|
|
40
|
+
clearTimeout(timeout.current);
|
|
41
|
+
timeout.current = void 0;
|
|
42
|
+
}
|
|
43
|
+
if (waitTimeout.current) {
|
|
44
|
+
clearTimeout(waitTimeout.current);
|
|
45
|
+
waitTimeout.current = void 0;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
useUnmountEffect(clear);
|
|
49
|
+
react.useEffect(() => {
|
|
50
|
+
cb.current = callback;
|
|
51
|
+
}, deps);
|
|
52
|
+
return react.useMemo(() => {
|
|
53
|
+
const execute = () => {
|
|
54
|
+
clear();
|
|
55
|
+
if (!lastCall.current)
|
|
56
|
+
return;
|
|
57
|
+
const context = lastCall.current;
|
|
58
|
+
lastCall.current = void 0;
|
|
59
|
+
cb.current.apply(context.this, context.args);
|
|
60
|
+
};
|
|
61
|
+
const wrapped = function(...args) {
|
|
62
|
+
if (timeout.current) {
|
|
63
|
+
clearTimeout(timeout.current);
|
|
64
|
+
}
|
|
65
|
+
lastCall.current = { args, this: this };
|
|
66
|
+
timeout.current = setTimeout(execute, delay);
|
|
67
|
+
if (maxWait > 0 && !waitTimeout.current) {
|
|
68
|
+
waitTimeout.current = setTimeout(execute, maxWait);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
Object.defineProperties(wrapped, {
|
|
72
|
+
length: { value: callback.length },
|
|
73
|
+
name: { value: `${callback.name || "anonymous"}__debounced__${delay}` }
|
|
74
|
+
});
|
|
75
|
+
return wrapped;
|
|
76
|
+
}, [delay, maxWait, ...deps]);
|
|
77
|
+
}
|
|
78
|
+
const isBrowser = typeof window !== "undefined" && typeof navigator !== "undefined" && typeof document !== "undefined";
|
|
79
|
+
const basicDepsComparator = (d1, d2) => {
|
|
80
|
+
if (d1 === d2)
|
|
81
|
+
return true;
|
|
82
|
+
if (d1.length !== d2.length)
|
|
83
|
+
return false;
|
|
84
|
+
for (const [i, element] of d1.entries()) {
|
|
85
|
+
if (element !== d2[i]) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return true;
|
|
90
|
+
};
|
|
91
|
+
function useCustomCompareEffect(callback, deps, comparator = basicDepsComparator, effectHook = react.useEffect, ...effectHookRestArgs) {
|
|
92
|
+
const dependencies = react.useRef();
|
|
93
|
+
if (dependencies.current === void 0 || isBrowser && !comparator(dependencies.current, deps)) {
|
|
94
|
+
dependencies.current = deps;
|
|
95
|
+
}
|
|
96
|
+
effectHook(callback, dependencies.current, ...effectHookRestArgs);
|
|
97
|
+
}
|
|
98
|
+
function useDebouncedEffect(callback, deps, delay, maxWait = 0) {
|
|
99
|
+
react.useEffect(useDebouncedCallback(callback, deps, delay, maxWait), deps);
|
|
100
|
+
}
|
|
101
|
+
function resolveHookState(nextState, previousState) {
|
|
102
|
+
if (typeof nextState === "function")
|
|
103
|
+
return nextState(previousState);
|
|
104
|
+
return nextState;
|
|
105
|
+
}
|
|
106
|
+
const useCustomCompareMemo = (factory, deps, comparator) => {
|
|
107
|
+
const dependencies = react.useRef();
|
|
108
|
+
if (dependencies.current === void 0 || !comparator(dependencies.current, deps)) {
|
|
109
|
+
dependencies.current = deps;
|
|
110
|
+
}
|
|
111
|
+
return react.useMemo(factory, dependencies.current);
|
|
112
|
+
};
|
|
113
|
+
function useToggle(initialState = false, ignoreReactEvents = true) {
|
|
114
|
+
const [state, setState] = react.useState(initialState);
|
|
115
|
+
const ignoreReactEventsRef = useSyncedRef(ignoreReactEvents);
|
|
116
|
+
return [
|
|
117
|
+
state,
|
|
118
|
+
react.useCallback((nextState) => {
|
|
119
|
+
setState((previousState) => {
|
|
120
|
+
if (nextState === void 0 || ignoreReactEventsRef.current && typeof nextState === "object" && (nextState.constructor.name === "SyntheticBaseEvent" || typeof nextState._reactName === "string")) {
|
|
121
|
+
return !previousState;
|
|
122
|
+
}
|
|
123
|
+
return Boolean(resolveHookState(nextState, previousState));
|
|
124
|
+
});
|
|
125
|
+
}, [])
|
|
126
|
+
];
|
|
127
|
+
}
|
|
128
|
+
var getOwnPropertyNames = Object.getOwnPropertyNames, getOwnPropertySymbols = Object.getOwnPropertySymbols;
|
|
129
|
+
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
130
|
+
function combineComparators(comparatorA, comparatorB) {
|
|
131
|
+
return function isEqual(a, b, state) {
|
|
132
|
+
return comparatorA(a, b, state) && comparatorB(a, b, state);
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function createIsCircular(areItemsEqual) {
|
|
136
|
+
return function isCircular(a, b, state) {
|
|
137
|
+
if (!a || !b || typeof a !== "object" || typeof b !== "object") {
|
|
138
|
+
return areItemsEqual(a, b, state);
|
|
139
|
+
}
|
|
140
|
+
var cache = state.cache;
|
|
141
|
+
var cachedA = cache.get(a);
|
|
142
|
+
var cachedB = cache.get(b);
|
|
143
|
+
if (cachedA && cachedB) {
|
|
144
|
+
return cachedA === b && cachedB === a;
|
|
145
|
+
}
|
|
146
|
+
cache.set(a, b);
|
|
147
|
+
cache.set(b, a);
|
|
148
|
+
var result = areItemsEqual(a, b, state);
|
|
149
|
+
cache.delete(a);
|
|
150
|
+
cache.delete(b);
|
|
151
|
+
return result;
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
function getStrictProperties(object) {
|
|
155
|
+
return getOwnPropertyNames(object).concat(getOwnPropertySymbols(object));
|
|
156
|
+
}
|
|
157
|
+
var hasOwn = Object.hasOwn || function(object, property) {
|
|
158
|
+
return hasOwnProperty.call(object, property);
|
|
159
|
+
};
|
|
160
|
+
function sameValueZeroEqual(a, b) {
|
|
161
|
+
return a || b ? a === b : a === b || a !== a && b !== b;
|
|
162
|
+
}
|
|
163
|
+
var OWNER = "_owner";
|
|
164
|
+
var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor, keys$1 = Object.keys;
|
|
165
|
+
function areArraysEqual(a, b, state) {
|
|
166
|
+
var index = a.length;
|
|
167
|
+
if (b.length !== index) {
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
while (index-- > 0) {
|
|
171
|
+
if (!state.equals(a[index], b[index], index, index, a, b, state)) {
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
function areDatesEqual(a, b) {
|
|
178
|
+
return sameValueZeroEqual(a.getTime(), b.getTime());
|
|
179
|
+
}
|
|
180
|
+
function areMapsEqual(a, b, state) {
|
|
181
|
+
if (a.size !== b.size) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
var matchedIndices = {};
|
|
185
|
+
var aIterable = a.entries();
|
|
186
|
+
var index = 0;
|
|
187
|
+
var aResult;
|
|
188
|
+
var bResult;
|
|
189
|
+
while (aResult = aIterable.next()) {
|
|
190
|
+
if (aResult.done) {
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
var bIterable = b.entries();
|
|
194
|
+
var hasMatch = false;
|
|
195
|
+
var matchIndex = 0;
|
|
196
|
+
while (bResult = bIterable.next()) {
|
|
197
|
+
if (bResult.done) {
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
var _a = aResult.value, aKey = _a[0], aValue = _a[1];
|
|
201
|
+
var _b = bResult.value, bKey = _b[0], bValue = _b[1];
|
|
202
|
+
if (!hasMatch && !matchedIndices[matchIndex] && (hasMatch = state.equals(aKey, bKey, index, matchIndex, a, b, state) && state.equals(aValue, bValue, aKey, bKey, a, b, state))) {
|
|
203
|
+
matchedIndices[matchIndex] = true;
|
|
204
|
+
}
|
|
205
|
+
matchIndex++;
|
|
206
|
+
}
|
|
207
|
+
if (!hasMatch) {
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
index++;
|
|
211
|
+
}
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
214
|
+
function areObjectsEqual(a, b, state) {
|
|
215
|
+
var properties = keys$1(a);
|
|
216
|
+
var index = properties.length;
|
|
217
|
+
if (keys$1(b).length !== index) {
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
var property;
|
|
221
|
+
while (index-- > 0) {
|
|
222
|
+
property = properties[index];
|
|
223
|
+
if (property === OWNER && (a.$$typeof || b.$$typeof) && a.$$typeof !== b.$$typeof) {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
if (!hasOwn(b, property) || !state.equals(a[property], b[property], property, property, a, b, state)) {
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
function areObjectsEqualStrict(a, b, state) {
|
|
233
|
+
var properties = getStrictProperties(a);
|
|
234
|
+
var index = properties.length;
|
|
235
|
+
if (getStrictProperties(b).length !== index) {
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
var property;
|
|
239
|
+
var descriptorA;
|
|
240
|
+
var descriptorB;
|
|
241
|
+
while (index-- > 0) {
|
|
242
|
+
property = properties[index];
|
|
243
|
+
if (property === OWNER && (a.$$typeof || b.$$typeof) && a.$$typeof !== b.$$typeof) {
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
if (!hasOwn(b, property)) {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
if (!state.equals(a[property], b[property], property, property, a, b, state)) {
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
descriptorA = getOwnPropertyDescriptor(a, property);
|
|
253
|
+
descriptorB = getOwnPropertyDescriptor(b, property);
|
|
254
|
+
if ((descriptorA || descriptorB) && (!descriptorA || !descriptorB || descriptorA.configurable !== descriptorB.configurable || descriptorA.enumerable !== descriptorB.enumerable || descriptorA.writable !== descriptorB.writable)) {
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return true;
|
|
259
|
+
}
|
|
260
|
+
function arePrimitiveWrappersEqual(a, b) {
|
|
261
|
+
return sameValueZeroEqual(a.valueOf(), b.valueOf());
|
|
262
|
+
}
|
|
263
|
+
function areRegExpsEqual(a, b) {
|
|
264
|
+
return a.source === b.source && a.flags === b.flags;
|
|
265
|
+
}
|
|
266
|
+
function areSetsEqual(a, b, state) {
|
|
267
|
+
if (a.size !== b.size) {
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
var matchedIndices = {};
|
|
271
|
+
var aIterable = a.values();
|
|
272
|
+
var aResult;
|
|
273
|
+
var bResult;
|
|
274
|
+
while (aResult = aIterable.next()) {
|
|
275
|
+
if (aResult.done) {
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
var bIterable = b.values();
|
|
279
|
+
var hasMatch = false;
|
|
280
|
+
var matchIndex = 0;
|
|
281
|
+
while (bResult = bIterable.next()) {
|
|
282
|
+
if (bResult.done) {
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
if (!hasMatch && !matchedIndices[matchIndex] && (hasMatch = state.equals(aResult.value, bResult.value, aResult.value, bResult.value, a, b, state))) {
|
|
286
|
+
matchedIndices[matchIndex] = true;
|
|
287
|
+
}
|
|
288
|
+
matchIndex++;
|
|
289
|
+
}
|
|
290
|
+
if (!hasMatch) {
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return true;
|
|
295
|
+
}
|
|
296
|
+
function areTypedArraysEqual(a, b) {
|
|
297
|
+
var index = a.length;
|
|
298
|
+
if (b.length !== index) {
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
while (index-- > 0) {
|
|
302
|
+
if (a[index] !== b[index]) {
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return true;
|
|
307
|
+
}
|
|
308
|
+
var ARGUMENTS_TAG = "[object Arguments]";
|
|
309
|
+
var BOOLEAN_TAG = "[object Boolean]";
|
|
310
|
+
var DATE_TAG = "[object Date]";
|
|
311
|
+
var MAP_TAG = "[object Map]";
|
|
312
|
+
var NUMBER_TAG = "[object Number]";
|
|
313
|
+
var OBJECT_TAG = "[object Object]";
|
|
314
|
+
var REG_EXP_TAG = "[object RegExp]";
|
|
315
|
+
var SET_TAG = "[object Set]";
|
|
316
|
+
var STRING_TAG = "[object String]";
|
|
317
|
+
var isArray = Array.isArray;
|
|
318
|
+
var isTypedArray = typeof ArrayBuffer === "function" && ArrayBuffer.isView ? ArrayBuffer.isView : null;
|
|
319
|
+
var assign = Object.assign;
|
|
320
|
+
var getTag = Object.prototype.toString.call.bind(Object.prototype.toString);
|
|
321
|
+
function createEqualityComparator(_a) {
|
|
322
|
+
var areArraysEqual2 = _a.areArraysEqual, areDatesEqual2 = _a.areDatesEqual, areMapsEqual2 = _a.areMapsEqual, areObjectsEqual2 = _a.areObjectsEqual, arePrimitiveWrappersEqual2 = _a.arePrimitiveWrappersEqual, areRegExpsEqual2 = _a.areRegExpsEqual, areSetsEqual2 = _a.areSetsEqual, areTypedArraysEqual2 = _a.areTypedArraysEqual;
|
|
323
|
+
return function comparator(a, b, state) {
|
|
324
|
+
if (a === b) {
|
|
325
|
+
return true;
|
|
326
|
+
}
|
|
327
|
+
if (a == null || b == null || typeof a !== "object" || typeof b !== "object") {
|
|
328
|
+
return a !== a && b !== b;
|
|
329
|
+
}
|
|
330
|
+
var constructor = a.constructor;
|
|
331
|
+
if (constructor !== b.constructor) {
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
334
|
+
if (constructor === Object) {
|
|
335
|
+
return areObjectsEqual2(a, b, state);
|
|
336
|
+
}
|
|
337
|
+
if (isArray(a)) {
|
|
338
|
+
return areArraysEqual2(a, b, state);
|
|
339
|
+
}
|
|
340
|
+
if (isTypedArray != null && isTypedArray(a)) {
|
|
341
|
+
return areTypedArraysEqual2(a, b, state);
|
|
342
|
+
}
|
|
343
|
+
if (constructor === Date) {
|
|
344
|
+
return areDatesEqual2(a, b, state);
|
|
345
|
+
}
|
|
346
|
+
if (constructor === RegExp) {
|
|
347
|
+
return areRegExpsEqual2(a, b, state);
|
|
348
|
+
}
|
|
349
|
+
if (constructor === Map) {
|
|
350
|
+
return areMapsEqual2(a, b, state);
|
|
351
|
+
}
|
|
352
|
+
if (constructor === Set) {
|
|
353
|
+
return areSetsEqual2(a, b, state);
|
|
354
|
+
}
|
|
355
|
+
var tag = getTag(a);
|
|
356
|
+
if (tag === DATE_TAG) {
|
|
357
|
+
return areDatesEqual2(a, b, state);
|
|
358
|
+
}
|
|
359
|
+
if (tag === REG_EXP_TAG) {
|
|
360
|
+
return areRegExpsEqual2(a, b, state);
|
|
361
|
+
}
|
|
362
|
+
if (tag === MAP_TAG) {
|
|
363
|
+
return areMapsEqual2(a, b, state);
|
|
364
|
+
}
|
|
365
|
+
if (tag === SET_TAG) {
|
|
366
|
+
return areSetsEqual2(a, b, state);
|
|
367
|
+
}
|
|
368
|
+
if (tag === OBJECT_TAG) {
|
|
369
|
+
return typeof a.then !== "function" && typeof b.then !== "function" && areObjectsEqual2(a, b, state);
|
|
370
|
+
}
|
|
371
|
+
if (tag === ARGUMENTS_TAG) {
|
|
372
|
+
return areObjectsEqual2(a, b, state);
|
|
373
|
+
}
|
|
374
|
+
if (tag === BOOLEAN_TAG || tag === NUMBER_TAG || tag === STRING_TAG) {
|
|
375
|
+
return arePrimitiveWrappersEqual2(a, b, state);
|
|
376
|
+
}
|
|
377
|
+
return false;
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
function createEqualityComparatorConfig(_a) {
|
|
381
|
+
var circular = _a.circular, createCustomConfig = _a.createCustomConfig, strict = _a.strict;
|
|
382
|
+
var config = {
|
|
383
|
+
areArraysEqual: strict ? areObjectsEqualStrict : areArraysEqual,
|
|
384
|
+
areDatesEqual,
|
|
385
|
+
areMapsEqual: strict ? combineComparators(areMapsEqual, areObjectsEqualStrict) : areMapsEqual,
|
|
386
|
+
areObjectsEqual: strict ? areObjectsEqualStrict : areObjectsEqual,
|
|
387
|
+
arePrimitiveWrappersEqual,
|
|
388
|
+
areRegExpsEqual,
|
|
389
|
+
areSetsEqual: strict ? combineComparators(areSetsEqual, areObjectsEqualStrict) : areSetsEqual,
|
|
390
|
+
areTypedArraysEqual: strict ? areObjectsEqualStrict : areTypedArraysEqual
|
|
391
|
+
};
|
|
392
|
+
if (createCustomConfig) {
|
|
393
|
+
config = assign({}, config, createCustomConfig(config));
|
|
394
|
+
}
|
|
395
|
+
if (circular) {
|
|
396
|
+
var areArraysEqual$1 = createIsCircular(config.areArraysEqual);
|
|
397
|
+
var areMapsEqual$1 = createIsCircular(config.areMapsEqual);
|
|
398
|
+
var areObjectsEqual$1 = createIsCircular(config.areObjectsEqual);
|
|
399
|
+
var areSetsEqual$1 = createIsCircular(config.areSetsEqual);
|
|
400
|
+
config = assign({}, config, {
|
|
401
|
+
areArraysEqual: areArraysEqual$1,
|
|
402
|
+
areMapsEqual: areMapsEqual$1,
|
|
403
|
+
areObjectsEqual: areObjectsEqual$1,
|
|
404
|
+
areSetsEqual: areSetsEqual$1
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
return config;
|
|
408
|
+
}
|
|
409
|
+
function createInternalEqualityComparator(compare) {
|
|
410
|
+
return function(a, b, _indexOrKeyA, _indexOrKeyB, _parentA, _parentB, state) {
|
|
411
|
+
return compare(a, b, state);
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
function createIsEqual(_a) {
|
|
415
|
+
var circular = _a.circular, comparator = _a.comparator, createState = _a.createState, equals = _a.equals, strict = _a.strict;
|
|
416
|
+
if (createState) {
|
|
417
|
+
return function isEqual(a, b) {
|
|
418
|
+
var _a2 = createState(), _b = _a2.cache, cache = _b === void 0 ? circular ? /* @__PURE__ */ new WeakMap() : void 0 : _b, meta = _a2.meta;
|
|
419
|
+
return comparator(a, b, {
|
|
420
|
+
cache,
|
|
421
|
+
equals,
|
|
422
|
+
meta,
|
|
423
|
+
strict
|
|
424
|
+
});
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
if (circular) {
|
|
428
|
+
return function isEqual(a, b) {
|
|
429
|
+
return comparator(a, b, {
|
|
430
|
+
cache: /* @__PURE__ */ new WeakMap(),
|
|
431
|
+
equals,
|
|
432
|
+
meta: void 0,
|
|
433
|
+
strict
|
|
434
|
+
});
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
var state = {
|
|
438
|
+
cache: void 0,
|
|
439
|
+
equals,
|
|
440
|
+
meta: void 0,
|
|
441
|
+
strict
|
|
442
|
+
};
|
|
443
|
+
return function isEqual(a, b) {
|
|
444
|
+
return comparator(a, b, state);
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
var deepEqual = createCustomEqual();
|
|
448
|
+
createCustomEqual({ strict: true });
|
|
449
|
+
createCustomEqual({ circular: true });
|
|
450
|
+
createCustomEqual({
|
|
451
|
+
circular: true,
|
|
452
|
+
strict: true
|
|
453
|
+
});
|
|
454
|
+
var shallowEqual = createCustomEqual({
|
|
455
|
+
createInternalComparator: function() {
|
|
456
|
+
return sameValueZeroEqual;
|
|
457
|
+
}
|
|
458
|
+
});
|
|
459
|
+
createCustomEqual({
|
|
460
|
+
strict: true,
|
|
461
|
+
createInternalComparator: function() {
|
|
462
|
+
return sameValueZeroEqual;
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
createCustomEqual({
|
|
466
|
+
circular: true,
|
|
467
|
+
createInternalComparator: function() {
|
|
468
|
+
return sameValueZeroEqual;
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
createCustomEqual({
|
|
472
|
+
circular: true,
|
|
473
|
+
createInternalComparator: function() {
|
|
474
|
+
return sameValueZeroEqual;
|
|
475
|
+
},
|
|
476
|
+
strict: true
|
|
477
|
+
});
|
|
478
|
+
function createCustomEqual(options) {
|
|
479
|
+
if (options === void 0) {
|
|
480
|
+
options = {};
|
|
481
|
+
}
|
|
482
|
+
var _a = options.circular, circular = _a === void 0 ? false : _a, createCustomInternalComparator = options.createInternalComparator, createState = options.createState, _b = options.strict, strict = _b === void 0 ? false : _b;
|
|
483
|
+
var config = createEqualityComparatorConfig(options);
|
|
484
|
+
var comparator = createEqualityComparator(config);
|
|
485
|
+
var equals = createCustomInternalComparator ? createCustomInternalComparator(comparator) : createInternalEqualityComparator(comparator);
|
|
486
|
+
return createIsEqual({ circular, comparator, createState, equals, strict });
|
|
487
|
+
}
|
|
488
|
+
var modalContent = "_1yqpph0";
|
|
489
|
+
var modalBody = "_1yqpph1";
|
|
490
|
+
var modalHeader = "_1yqpph2";
|
|
491
|
+
var modalCloseButtonBox = "_1yqpph3";
|
|
492
|
+
var modalCloseButton = "_1yqpph4";
|
|
493
|
+
function useSetState(initialState) {
|
|
494
|
+
const [state, _setState] = react.useState(initialState);
|
|
495
|
+
const setState = react.useCallback(
|
|
496
|
+
(statePartial) => _setState((current) => {
|
|
497
|
+
const next = {
|
|
498
|
+
...current,
|
|
499
|
+
...typeof statePartial === "function" ? statePartial(current) : statePartial
|
|
500
|
+
};
|
|
501
|
+
return shallowEqual(current, next) ? current : next;
|
|
502
|
+
}),
|
|
503
|
+
[]
|
|
504
|
+
);
|
|
505
|
+
return [state, setState];
|
|
506
|
+
}
|
|
507
|
+
function useUpdateEffect(callback, deps) {
|
|
508
|
+
const render = react.useRef(false);
|
|
509
|
+
const effect = react.useRef(false);
|
|
510
|
+
useCustomCompareEffect(
|
|
511
|
+
() => {
|
|
512
|
+
const mounted = render.current;
|
|
513
|
+
const run = mounted && effect.current;
|
|
514
|
+
if (run) {
|
|
515
|
+
return callback();
|
|
516
|
+
}
|
|
517
|
+
effect.current = true;
|
|
518
|
+
},
|
|
519
|
+
deps,
|
|
520
|
+
shallowEqual
|
|
521
|
+
);
|
|
522
|
+
react.useEffect(() => {
|
|
523
|
+
render.current = true;
|
|
524
|
+
return () => {
|
|
525
|
+
render.current = false;
|
|
526
|
+
};
|
|
527
|
+
}, []);
|
|
528
|
+
}
|
|
529
|
+
var cssReactFlow = "_2h8g8h0";
|
|
530
|
+
var cssDisablePan = "_2h8g8h1";
|
|
531
|
+
var cssTransparentBg = "_2h8g8h2";
|
|
532
|
+
var cssNoControls = "_2h8g8h3";
|
|
533
|
+
const theme = core.createTheme({
|
|
534
|
+
primaryColor: "indigo",
|
|
535
|
+
cursorType: "pointer",
|
|
536
|
+
headings: {
|
|
537
|
+
fontWeight: "500",
|
|
538
|
+
sizes: {
|
|
539
|
+
h1: {
|
|
540
|
+
// fontSize: '2rem',
|
|
541
|
+
fontWeight: "600"
|
|
542
|
+
},
|
|
543
|
+
h2: {
|
|
544
|
+
// fontSize: '1.85rem',
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
function EnsureMantine({ colorMode, children }) {
|
|
550
|
+
const mantineCtx = react.useContext(core.MantineContext);
|
|
551
|
+
if (mantineCtx) {
|
|
552
|
+
mantineCtx.getRootElement;
|
|
553
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
|
|
554
|
+
}
|
|
555
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
556
|
+
core.MantineProvider,
|
|
557
|
+
{
|
|
558
|
+
...colorMode && {
|
|
559
|
+
forceColorScheme: colorMode
|
|
560
|
+
},
|
|
561
|
+
theme,
|
|
562
|
+
defaultColorScheme: "auto",
|
|
563
|
+
children
|
|
564
|
+
}
|
|
565
|
+
);
|
|
566
|
+
}
|
|
567
|
+
const useDiagramStateValue = ({
|
|
568
|
+
isNodeInteractive,
|
|
569
|
+
view,
|
|
570
|
+
fitViewPadding,
|
|
571
|
+
readonly,
|
|
572
|
+
disableHovercards,
|
|
573
|
+
eventHandlers
|
|
574
|
+
}) => {
|
|
575
|
+
const hasEventHandlers = {
|
|
576
|
+
hasOnChange: !!eventHandlers.onChange,
|
|
577
|
+
hasOnNavigateTo: !!eventHandlers.onNavigateTo,
|
|
578
|
+
hasOnNodeClick: !!eventHandlers.onNodeClick,
|
|
579
|
+
hasOnNodeContextMenu: !!eventHandlers.onNodeContextMenu,
|
|
580
|
+
hasOnCanvasContextMenu: !!eventHandlers.onCanvasContextMenu,
|
|
581
|
+
hasOnEdgeContextMenu: !!eventHandlers.onEdgeContextMenu,
|
|
582
|
+
hasOnContextMenu: !!eventHandlers.onNodeContextMenu || !!eventHandlers.onCanvasContextMenu || !!eventHandlers.onEdgeContextMenu,
|
|
583
|
+
hasOnEdgeClick: !!eventHandlers.onEdgeClick,
|
|
584
|
+
hasOnCanvasClick: !!eventHandlers.onCanvasClick || !!eventHandlers.onCanvasDblClick
|
|
585
|
+
};
|
|
586
|
+
const [state, setState] = useSetState({
|
|
587
|
+
viewportInitialized: false,
|
|
588
|
+
// User moved the viewport
|
|
589
|
+
viewportMoved: false,
|
|
590
|
+
hoveredNodeId: null,
|
|
591
|
+
hoveredEdgeId: null
|
|
592
|
+
});
|
|
593
|
+
const readonlyProps = {
|
|
594
|
+
readonly,
|
|
595
|
+
disableHovercards,
|
|
596
|
+
isNodeInteractive,
|
|
597
|
+
viewId: view.id,
|
|
598
|
+
viewLayout: view.autoLayout,
|
|
599
|
+
viewWidth: view.width,
|
|
600
|
+
viewHeight: view.height,
|
|
601
|
+
fitViewPadding
|
|
602
|
+
};
|
|
603
|
+
const _state = useCustomCompareMemo(
|
|
604
|
+
() => ({
|
|
605
|
+
...readonlyProps,
|
|
606
|
+
...hasEventHandlers,
|
|
607
|
+
...state
|
|
608
|
+
}),
|
|
609
|
+
[state, readonlyProps, hasEventHandlers],
|
|
610
|
+
shallowEqual
|
|
611
|
+
);
|
|
612
|
+
return [_state, setState];
|
|
613
|
+
};
|
|
614
|
+
const {
|
|
615
|
+
Provider: DiagramStateProvider,
|
|
616
|
+
useTracked: useDiagramStateTracked,
|
|
617
|
+
useTrackedState: useDiagramState,
|
|
618
|
+
useUpdate: useUpdateDiagramState,
|
|
619
|
+
useSelector: useDiagramStateSelector
|
|
620
|
+
} = /* @__PURE__ */ reactTracked.createContainer(useDiagramStateValue, {
|
|
621
|
+
concurrentMode: false,
|
|
622
|
+
stateContextName: "DiagramStateContext"
|
|
623
|
+
});
|
|
624
|
+
var wrapper = "_14qhjro0";
|
|
625
|
+
function KeepAspectRatio({
|
|
626
|
+
children,
|
|
627
|
+
width,
|
|
628
|
+
height,
|
|
629
|
+
enabled,
|
|
630
|
+
className,
|
|
631
|
+
style,
|
|
632
|
+
...rest
|
|
633
|
+
}) {
|
|
634
|
+
if (!enabled) {
|
|
635
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
|
|
636
|
+
}
|
|
637
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
638
|
+
core.Box,
|
|
639
|
+
{
|
|
640
|
+
...rest,
|
|
641
|
+
className: clsx(wrapper, className),
|
|
642
|
+
style: {
|
|
643
|
+
...style,
|
|
644
|
+
aspectRatio: `${width}/${height}`,
|
|
645
|
+
maxHeight: height
|
|
646
|
+
},
|
|
647
|
+
children
|
|
648
|
+
}
|
|
649
|
+
);
|
|
650
|
+
}
|
|
651
|
+
var __spreadArray = function(to, from, pack) {
|
|
652
|
+
if (pack || arguments.length === 2)
|
|
653
|
+
for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
654
|
+
if (ar || !(i in from)) {
|
|
655
|
+
if (!ar)
|
|
656
|
+
ar = Array.prototype.slice.call(from, 0, i);
|
|
657
|
+
ar[i] = from[i];
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
661
|
+
};
|
|
662
|
+
function purry(fn, args, lazyFactory) {
|
|
663
|
+
var callArgs = Array.from(args);
|
|
664
|
+
var diff = fn.length - args.length;
|
|
665
|
+
if (diff === 0) {
|
|
666
|
+
return fn.apply(void 0, callArgs);
|
|
667
|
+
}
|
|
668
|
+
if (diff === 1) {
|
|
669
|
+
var ret = function(data) {
|
|
670
|
+
return fn.apply(void 0, __spreadArray([data], callArgs, false));
|
|
671
|
+
};
|
|
672
|
+
var lazy = lazyFactory !== null && lazyFactory !== void 0 ? lazyFactory : fn.lazy;
|
|
673
|
+
return lazy === void 0 ? ret : Object.assign(ret, { lazy, lazyArgs: args });
|
|
674
|
+
}
|
|
675
|
+
throw new Error("Wrong number of arguments");
|
|
676
|
+
}
|
|
677
|
+
function isTruthy(data) {
|
|
678
|
+
return Boolean(data);
|
|
679
|
+
}
|
|
680
|
+
function hasAtLeast() {
|
|
681
|
+
var args = [];
|
|
682
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
683
|
+
args[_i] = arguments[_i];
|
|
684
|
+
}
|
|
685
|
+
return purry(hasAtLeastImplementation, args);
|
|
686
|
+
}
|
|
687
|
+
var hasAtLeastImplementation = function(data, minimum) {
|
|
688
|
+
return data.length >= minimum;
|
|
689
|
+
};
|
|
690
|
+
function isNullish(data) {
|
|
691
|
+
return data === null || data === void 0;
|
|
692
|
+
}
|
|
693
|
+
function keys() {
|
|
694
|
+
return purry(Object.keys, arguments);
|
|
695
|
+
}
|
|
696
|
+
(function(keys2) {
|
|
697
|
+
keys2.strict = keys2;
|
|
698
|
+
})(keys || (keys = {}));
|
|
699
|
+
function takeWhile() {
|
|
700
|
+
return purry(_takeWhile, arguments);
|
|
701
|
+
}
|
|
702
|
+
function _takeWhile(array, fn) {
|
|
703
|
+
var ret = [];
|
|
704
|
+
for (var _i = 0, array_1 = array; _i < array_1.length; _i++) {
|
|
705
|
+
var item = array_1[_i];
|
|
706
|
+
if (!fn(item)) {
|
|
707
|
+
break;
|
|
708
|
+
}
|
|
709
|
+
ret.push(item);
|
|
710
|
+
}
|
|
711
|
+
return ret;
|
|
712
|
+
}
|
|
713
|
+
var XYFlowNode;
|
|
714
|
+
((XYFlowNode2) => {
|
|
715
|
+
function isCompound(node) {
|
|
716
|
+
return react$1.isNode(node) && node.type === "compound";
|
|
717
|
+
}
|
|
718
|
+
XYFlowNode2.isCompound = isCompound;
|
|
719
|
+
function isElement(node) {
|
|
720
|
+
return react$1.isNode(node) && node.type === "element";
|
|
721
|
+
}
|
|
722
|
+
XYFlowNode2.isElement = isElement;
|
|
723
|
+
XYFlowNode2.is = (node) => isCompound(node) || isElement(node);
|
|
724
|
+
})(XYFlowNode || (XYFlowNode = {}));
|
|
725
|
+
var XYFlowEdge;
|
|
726
|
+
((XYFlowEdge2) => {
|
|
727
|
+
XYFlowEdge2.isRelationship = (e) => e.type === "relationship" && isTruthy(e.data);
|
|
728
|
+
})(XYFlowEdge || (XYFlowEdge = {}));
|
|
729
|
+
function createMap() {
|
|
730
|
+
return new IndexedMap();
|
|
731
|
+
}
|
|
732
|
+
class IndexedMap {
|
|
733
|
+
constructor() {
|
|
734
|
+
__publicField(this, "index", {});
|
|
735
|
+
__publicField(this, "array", []);
|
|
736
|
+
}
|
|
737
|
+
/**
|
|
738
|
+
* Returns the number of items in the array.
|
|
739
|
+
*/
|
|
740
|
+
size() {
|
|
741
|
+
return this.array.length;
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* Returns true if the array is empty.
|
|
745
|
+
*/
|
|
746
|
+
empty() {
|
|
747
|
+
return this.array.length === 0;
|
|
748
|
+
}
|
|
749
|
+
/**
|
|
750
|
+
* Returns the item at the given array index.
|
|
751
|
+
*
|
|
752
|
+
* @param index The integer index of the desired item.
|
|
753
|
+
*/
|
|
754
|
+
itemAt(index) {
|
|
755
|
+
return this.array[index];
|
|
756
|
+
}
|
|
757
|
+
/**
|
|
758
|
+
* Returns true if the key is in the array, false otherwise.
|
|
759
|
+
*
|
|
760
|
+
* @param key The key to locate in the array.
|
|
761
|
+
*/
|
|
762
|
+
contains(key) {
|
|
763
|
+
return this.index[key.id()] !== void 0;
|
|
764
|
+
}
|
|
765
|
+
/**
|
|
766
|
+
* Returns the pair associated with the given key, or undefined.
|
|
767
|
+
*
|
|
768
|
+
* @param key The key to locate in the array.
|
|
769
|
+
*/
|
|
770
|
+
find(key) {
|
|
771
|
+
const i = this.index[key.id()];
|
|
772
|
+
return i === void 0 ? void 0 : this.array[i];
|
|
773
|
+
}
|
|
774
|
+
/**
|
|
775
|
+
* Returns the pair associated with the key if it exists.
|
|
776
|
+
*
|
|
777
|
+
* If the key does not exist, a new pair will be created and
|
|
778
|
+
* inserted using the value created by the given factory.
|
|
779
|
+
*
|
|
780
|
+
* @param key The key to locate in the array.
|
|
781
|
+
* @param factory The function which creates the default value.
|
|
782
|
+
*/
|
|
783
|
+
setDefault(key, factory) {
|
|
784
|
+
const i = this.index[key.id()];
|
|
785
|
+
if (i === void 0) {
|
|
786
|
+
const pair = new Pair(key, factory());
|
|
787
|
+
this.index[key.id()] = this.array.length;
|
|
788
|
+
this.array.push(pair);
|
|
789
|
+
return pair;
|
|
790
|
+
} else {
|
|
791
|
+
return this.array[i];
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
/**
|
|
795
|
+
* Insert the pair into the array and return the pair.
|
|
796
|
+
*
|
|
797
|
+
* This will overwrite any existing entry in the array.
|
|
798
|
+
*
|
|
799
|
+
* @param key The key portion of the pair.
|
|
800
|
+
* @param value The value portion of the pair.
|
|
801
|
+
*/
|
|
802
|
+
insert(key, value) {
|
|
803
|
+
const pair = new Pair(key, value);
|
|
804
|
+
const i = this.index[key.id()];
|
|
805
|
+
if (i === void 0) {
|
|
806
|
+
this.index[key.id()] = this.array.length;
|
|
807
|
+
this.array.push(pair);
|
|
808
|
+
} else {
|
|
809
|
+
this.array[i] = pair;
|
|
810
|
+
}
|
|
811
|
+
return pair;
|
|
812
|
+
}
|
|
813
|
+
/**
|
|
814
|
+
* Removes and returns the pair for the given key, or undefined.
|
|
815
|
+
*
|
|
816
|
+
* @param key The key to remove from the map.
|
|
817
|
+
*/
|
|
818
|
+
erase(key) {
|
|
819
|
+
const i = this.index[key.id()];
|
|
820
|
+
if (i === void 0) {
|
|
821
|
+
return void 0;
|
|
822
|
+
}
|
|
823
|
+
this.index[key.id()] = void 0;
|
|
824
|
+
const pair = this.array[i];
|
|
825
|
+
const last = this.array.pop();
|
|
826
|
+
if (pair !== last) {
|
|
827
|
+
this.array[i] = last;
|
|
828
|
+
this.index[last.first.id()] = i;
|
|
829
|
+
}
|
|
830
|
+
return pair;
|
|
831
|
+
}
|
|
832
|
+
/**
|
|
833
|
+
* Create a copy of this associative array.
|
|
834
|
+
*/
|
|
835
|
+
copy() {
|
|
836
|
+
const copy = new IndexedMap();
|
|
837
|
+
for (let i = 0; i < this.array.length; i++) {
|
|
838
|
+
const pair = this.array[i].copy();
|
|
839
|
+
copy.array[i] = pair;
|
|
840
|
+
copy.index[pair.first.id()] = i;
|
|
841
|
+
}
|
|
842
|
+
return copy;
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
class Pair {
|
|
846
|
+
/**
|
|
847
|
+
* Construct a new Pair object.
|
|
848
|
+
*
|
|
849
|
+
* @param first The first item of the pair.
|
|
850
|
+
* @param second The second item of the pair.
|
|
851
|
+
*/
|
|
852
|
+
constructor(first, second) {
|
|
853
|
+
__publicField(this, "first");
|
|
854
|
+
__publicField(this, "second");
|
|
855
|
+
this.first = first;
|
|
856
|
+
this.second = second;
|
|
857
|
+
}
|
|
858
|
+
/**
|
|
859
|
+
* Create a copy of the pair.
|
|
860
|
+
*/
|
|
861
|
+
copy() {
|
|
862
|
+
return new Pair(this.first, this.second);
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
class Variable {
|
|
866
|
+
constructor(name = "") {
|
|
867
|
+
__publicField(this, "_name");
|
|
868
|
+
__publicField(this, "_value", 0);
|
|
869
|
+
__publicField(this, "_context", null);
|
|
870
|
+
__publicField(this, "_id", VarId++);
|
|
871
|
+
this._name = name;
|
|
872
|
+
}
|
|
873
|
+
/**
|
|
874
|
+
* Returns the unique id number of the variable.
|
|
875
|
+
* @private
|
|
876
|
+
*/
|
|
877
|
+
id() {
|
|
878
|
+
return this._id;
|
|
879
|
+
}
|
|
880
|
+
/**
|
|
881
|
+
* Returns the name of the variable.
|
|
882
|
+
*
|
|
883
|
+
* @return {String} name of the variable
|
|
884
|
+
*/
|
|
885
|
+
name() {
|
|
886
|
+
return this._name;
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* Set the name of the variable.
|
|
890
|
+
*
|
|
891
|
+
* @param {String} name Name of the variable
|
|
892
|
+
*/
|
|
893
|
+
setName(name) {
|
|
894
|
+
this._name = name;
|
|
895
|
+
}
|
|
896
|
+
/**
|
|
897
|
+
* Returns the user context object of the variable.
|
|
898
|
+
* @private
|
|
899
|
+
*/
|
|
900
|
+
context() {
|
|
901
|
+
return this._context;
|
|
902
|
+
}
|
|
903
|
+
/**
|
|
904
|
+
* Set the user context object of the variable.
|
|
905
|
+
* @private
|
|
906
|
+
*/
|
|
907
|
+
setContext(context) {
|
|
908
|
+
this._context = context;
|
|
909
|
+
}
|
|
910
|
+
/**
|
|
911
|
+
* Returns the value of the variable.
|
|
912
|
+
*
|
|
913
|
+
* @return {Number} Calculated value
|
|
914
|
+
*/
|
|
915
|
+
value() {
|
|
916
|
+
return this._value;
|
|
917
|
+
}
|
|
918
|
+
/**
|
|
919
|
+
* Set the value of the variable.
|
|
920
|
+
* @private
|
|
921
|
+
*/
|
|
922
|
+
setValue(value) {
|
|
923
|
+
this._value = value;
|
|
924
|
+
}
|
|
925
|
+
/**
|
|
926
|
+
* Creates a new Expression by adding a number, variable or expression
|
|
927
|
+
* to the variable.
|
|
928
|
+
*
|
|
929
|
+
* @param {Number|Variable|Expression} value Value to add.
|
|
930
|
+
* @return {Expression} expression
|
|
931
|
+
*/
|
|
932
|
+
plus(value) {
|
|
933
|
+
return new Expression(this, value);
|
|
934
|
+
}
|
|
935
|
+
/**
|
|
936
|
+
* Creates a new Expression by substracting a number, variable or expression
|
|
937
|
+
* from the variable.
|
|
938
|
+
*
|
|
939
|
+
* @param {Number|Variable|Expression} value Value to substract.
|
|
940
|
+
* @return {Expression} expression
|
|
941
|
+
*/
|
|
942
|
+
minus(value) {
|
|
943
|
+
return new Expression(this, typeof value === "number" ? -value : [-1, value]);
|
|
944
|
+
}
|
|
945
|
+
/**
|
|
946
|
+
* Creates a new Expression by multiplying with a fixed number.
|
|
947
|
+
*
|
|
948
|
+
* @param {Number} coefficient Coefficient to multiply with.
|
|
949
|
+
* @return {Expression} expression
|
|
950
|
+
*/
|
|
951
|
+
multiply(coefficient) {
|
|
952
|
+
return new Expression([coefficient, this]);
|
|
953
|
+
}
|
|
954
|
+
/**
|
|
955
|
+
* Creates a new Expression by dividing with a fixed number.
|
|
956
|
+
*
|
|
957
|
+
* @param {Number} coefficient Coefficient to divide by.
|
|
958
|
+
* @return {Expression} expression
|
|
959
|
+
*/
|
|
960
|
+
divide(coefficient) {
|
|
961
|
+
return new Expression([1 / coefficient, this]);
|
|
962
|
+
}
|
|
963
|
+
/**
|
|
964
|
+
* Returns the JSON representation of the variable.
|
|
965
|
+
* @private
|
|
966
|
+
*/
|
|
967
|
+
toJSON() {
|
|
968
|
+
return {
|
|
969
|
+
name: this._name,
|
|
970
|
+
value: this._value
|
|
971
|
+
};
|
|
972
|
+
}
|
|
973
|
+
toString() {
|
|
974
|
+
return this._context + "[" + this._name + ":" + this._value + "]";
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
let VarId = 0;
|
|
978
|
+
class Expression {
|
|
979
|
+
constructor() {
|
|
980
|
+
__publicField(this, "_terms");
|
|
981
|
+
__publicField(this, "_constant");
|
|
982
|
+
let parsed = parseArgs(arguments);
|
|
983
|
+
this._terms = parsed.terms;
|
|
984
|
+
this._constant = parsed.constant;
|
|
985
|
+
}
|
|
986
|
+
/**
|
|
987
|
+
* Returns the mapping of terms in the expression.
|
|
988
|
+
*
|
|
989
|
+
* This *must* be treated as const.
|
|
990
|
+
* @private
|
|
991
|
+
*/
|
|
992
|
+
terms() {
|
|
993
|
+
return this._terms;
|
|
994
|
+
}
|
|
995
|
+
/**
|
|
996
|
+
* Returns the constant of the expression.
|
|
997
|
+
* @private
|
|
998
|
+
*/
|
|
999
|
+
constant() {
|
|
1000
|
+
return this._constant;
|
|
1001
|
+
}
|
|
1002
|
+
/**
|
|
1003
|
+
* Returns the computed value of the expression.
|
|
1004
|
+
*
|
|
1005
|
+
* @private
|
|
1006
|
+
* @return {Number} computed value of the expression
|
|
1007
|
+
*/
|
|
1008
|
+
value() {
|
|
1009
|
+
let result = this._constant;
|
|
1010
|
+
for (let i = 0, n = this._terms.size(); i < n; i++) {
|
|
1011
|
+
let pair = this._terms.itemAt(i);
|
|
1012
|
+
result += pair.first.value() * pair.second;
|
|
1013
|
+
}
|
|
1014
|
+
return result;
|
|
1015
|
+
}
|
|
1016
|
+
/**
|
|
1017
|
+
* Creates a new Expression by adding a number, variable or expression
|
|
1018
|
+
* to the expression.
|
|
1019
|
+
*
|
|
1020
|
+
* @param {Number|Variable|Expression} value Value to add.
|
|
1021
|
+
* @return {Expression} expression
|
|
1022
|
+
*/
|
|
1023
|
+
plus(value) {
|
|
1024
|
+
return new Expression(this, value);
|
|
1025
|
+
}
|
|
1026
|
+
/**
|
|
1027
|
+
* Creates a new Expression by substracting a number, variable or expression
|
|
1028
|
+
* from the expression.
|
|
1029
|
+
*
|
|
1030
|
+
* @param {Number|Variable|Expression} value Value to substract.
|
|
1031
|
+
* @return {Expression} expression
|
|
1032
|
+
*/
|
|
1033
|
+
minus(value) {
|
|
1034
|
+
return new Expression(this, typeof value === "number" ? -value : [-1, value]);
|
|
1035
|
+
}
|
|
1036
|
+
/**
|
|
1037
|
+
* Creates a new Expression by multiplying with a fixed number.
|
|
1038
|
+
*
|
|
1039
|
+
* @param {Number} coefficient Coefficient to multiply with.
|
|
1040
|
+
* @return {Expression} expression
|
|
1041
|
+
*/
|
|
1042
|
+
multiply(coefficient) {
|
|
1043
|
+
return new Expression([coefficient, this]);
|
|
1044
|
+
}
|
|
1045
|
+
/**
|
|
1046
|
+
* Creates a new Expression by dividing with a fixed number.
|
|
1047
|
+
*
|
|
1048
|
+
* @param {Number} coefficient Coefficient to divide by.
|
|
1049
|
+
* @return {Expression} expression
|
|
1050
|
+
*/
|
|
1051
|
+
divide(coefficient) {
|
|
1052
|
+
return new Expression([1 / coefficient, this]);
|
|
1053
|
+
}
|
|
1054
|
+
isConstant() {
|
|
1055
|
+
return this._terms.size() == 0;
|
|
1056
|
+
}
|
|
1057
|
+
toString() {
|
|
1058
|
+
let result = this._terms.array.map(function(pair) {
|
|
1059
|
+
return pair.second + "*" + pair.first.toString();
|
|
1060
|
+
}).join(" + ");
|
|
1061
|
+
if (!this.isConstant() && this._constant !== 0) {
|
|
1062
|
+
result += " + ";
|
|
1063
|
+
}
|
|
1064
|
+
result += this._constant;
|
|
1065
|
+
return result;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
function parseArgs(args) {
|
|
1069
|
+
let constant = 0;
|
|
1070
|
+
let factory = () => 0;
|
|
1071
|
+
let terms = createMap();
|
|
1072
|
+
for (let i = 0, n = args.length; i < n; ++i) {
|
|
1073
|
+
let item = args[i];
|
|
1074
|
+
if (typeof item === "number") {
|
|
1075
|
+
constant += item;
|
|
1076
|
+
} else if (item instanceof Variable) {
|
|
1077
|
+
terms.setDefault(item, factory).second += 1;
|
|
1078
|
+
} else if (item instanceof Expression) {
|
|
1079
|
+
constant += item.constant();
|
|
1080
|
+
let terms2 = item.terms();
|
|
1081
|
+
for (let j = 0, k = terms2.size(); j < k; j++) {
|
|
1082
|
+
let termPair = terms2.itemAt(j);
|
|
1083
|
+
terms.setDefault(termPair.first, factory).second += termPair.second;
|
|
1084
|
+
}
|
|
1085
|
+
} else if (item instanceof Array) {
|
|
1086
|
+
if (item.length !== 2) {
|
|
1087
|
+
throw new Error("array must have length 2");
|
|
1088
|
+
}
|
|
1089
|
+
let value = item[0];
|
|
1090
|
+
let value2 = item[1];
|
|
1091
|
+
if (typeof value !== "number") {
|
|
1092
|
+
throw new Error("array item 0 must be a number");
|
|
1093
|
+
}
|
|
1094
|
+
if (value2 instanceof Variable) {
|
|
1095
|
+
terms.setDefault(value2, factory).second += value;
|
|
1096
|
+
} else if (value2 instanceof Expression) {
|
|
1097
|
+
constant += value2.constant() * value;
|
|
1098
|
+
let terms2 = value2.terms();
|
|
1099
|
+
for (let j = 0, k = terms2.size(); j < k; j++) {
|
|
1100
|
+
let termPair = terms2.itemAt(j);
|
|
1101
|
+
terms.setDefault(termPair.first, factory).second += termPair.second * value;
|
|
1102
|
+
}
|
|
1103
|
+
} else {
|
|
1104
|
+
throw new Error("array item 1 must be a variable or expression");
|
|
1105
|
+
}
|
|
1106
|
+
} else {
|
|
1107
|
+
throw new Error("invalid Expression argument: " + item);
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
return { terms, constant };
|
|
1111
|
+
}
|
|
1112
|
+
const _Strength = class _Strength {
|
|
1113
|
+
/**
|
|
1114
|
+
* Create a new symbolic strength.
|
|
1115
|
+
*
|
|
1116
|
+
* @param a strong
|
|
1117
|
+
* @param b medium
|
|
1118
|
+
* @param c weak
|
|
1119
|
+
* @param [w] weight
|
|
1120
|
+
* @return strength
|
|
1121
|
+
*/
|
|
1122
|
+
static create(a, b, c, w = 1) {
|
|
1123
|
+
let result = 0;
|
|
1124
|
+
result += Math.max(0, Math.min(1e3, a * w)) * 1e6;
|
|
1125
|
+
result += Math.max(0, Math.min(1e3, b * w)) * 1e3;
|
|
1126
|
+
result += Math.max(0, Math.min(1e3, c * w));
|
|
1127
|
+
return result;
|
|
1128
|
+
}
|
|
1129
|
+
/**
|
|
1130
|
+
* Clip a symbolic strength to the allowed min and max.
|
|
1131
|
+
* @private
|
|
1132
|
+
*/
|
|
1133
|
+
static clip(value) {
|
|
1134
|
+
return Math.max(0, Math.min(_Strength.required, value));
|
|
1135
|
+
}
|
|
1136
|
+
};
|
|
1137
|
+
/**
|
|
1138
|
+
* The 'required' symbolic strength.
|
|
1139
|
+
*/
|
|
1140
|
+
__publicField(_Strength, "required", _Strength.create(1e3, 1e3, 1e3));
|
|
1141
|
+
/**
|
|
1142
|
+
* The 'strong' symbolic strength.
|
|
1143
|
+
*/
|
|
1144
|
+
__publicField(_Strength, "strong", _Strength.create(1, 0, 0));
|
|
1145
|
+
/**
|
|
1146
|
+
* The 'medium' symbolic strength.
|
|
1147
|
+
*/
|
|
1148
|
+
__publicField(_Strength, "medium", _Strength.create(0, 1, 0));
|
|
1149
|
+
/**
|
|
1150
|
+
* The 'weak' symbolic strength.
|
|
1151
|
+
*/
|
|
1152
|
+
__publicField(_Strength, "weak", _Strength.create(0, 0, 1));
|
|
1153
|
+
let Strength = _Strength;
|
|
1154
|
+
var Operator;
|
|
1155
|
+
(function(Operator2) {
|
|
1156
|
+
Operator2[Operator2["Le"] = 0] = "Le";
|
|
1157
|
+
Operator2[Operator2["Ge"] = 1] = "Ge";
|
|
1158
|
+
Operator2[Operator2["Eq"] = 2] = "Eq";
|
|
1159
|
+
})(Operator || (Operator = {}));
|
|
1160
|
+
class Constraint {
|
|
1161
|
+
constructor(expression, operator, rhs, strength = Strength.required) {
|
|
1162
|
+
__publicField(this, "_expression");
|
|
1163
|
+
__publicField(this, "_operator");
|
|
1164
|
+
__publicField(this, "_strength");
|
|
1165
|
+
__publicField(this, "_id", CnId++);
|
|
1166
|
+
this._operator = operator;
|
|
1167
|
+
this._strength = Strength.clip(strength);
|
|
1168
|
+
if (rhs === void 0 && expression instanceof Expression) {
|
|
1169
|
+
this._expression = expression;
|
|
1170
|
+
} else {
|
|
1171
|
+
this._expression = expression.minus(rhs);
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
/**
|
|
1175
|
+
* Returns the unique id number of the constraint.
|
|
1176
|
+
* @private
|
|
1177
|
+
*/
|
|
1178
|
+
id() {
|
|
1179
|
+
return this._id;
|
|
1180
|
+
}
|
|
1181
|
+
/**
|
|
1182
|
+
* Returns the expression of the constraint.
|
|
1183
|
+
*
|
|
1184
|
+
* @return {Expression} expression
|
|
1185
|
+
*/
|
|
1186
|
+
expression() {
|
|
1187
|
+
return this._expression;
|
|
1188
|
+
}
|
|
1189
|
+
/**
|
|
1190
|
+
* Returns the relational operator of the constraint.
|
|
1191
|
+
*
|
|
1192
|
+
* @return {Operator} linear constraint operator
|
|
1193
|
+
*/
|
|
1194
|
+
op() {
|
|
1195
|
+
return this._operator;
|
|
1196
|
+
}
|
|
1197
|
+
/**
|
|
1198
|
+
* Returns the strength of the constraint.
|
|
1199
|
+
*
|
|
1200
|
+
* @return {Number} strength
|
|
1201
|
+
*/
|
|
1202
|
+
strength() {
|
|
1203
|
+
return this._strength;
|
|
1204
|
+
}
|
|
1205
|
+
toString() {
|
|
1206
|
+
return this._expression.toString() + " " + ["<=", ">=", "="][this._operator] + " 0 (" + this._strength.toString() + ")";
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
let CnId = 0;
|
|
1210
|
+
class Solver {
|
|
1211
|
+
/**
|
|
1212
|
+
* Construct a new Solver.
|
|
1213
|
+
*/
|
|
1214
|
+
constructor() {
|
|
1215
|
+
/**
|
|
1216
|
+
* @type {number} - The max number of solver iterations before an error
|
|
1217
|
+
* is thrown, in order to prevent infinite iteration. Default: `10,000`.
|
|
1218
|
+
*/
|
|
1219
|
+
__publicField(this, "maxIterations", 1e3);
|
|
1220
|
+
__publicField(this, "_cnMap", createCnMap());
|
|
1221
|
+
__publicField(this, "_rowMap", createRowMap());
|
|
1222
|
+
__publicField(this, "_varMap", createVarMap());
|
|
1223
|
+
__publicField(this, "_editMap", createEditMap());
|
|
1224
|
+
__publicField(this, "_infeasibleRows", []);
|
|
1225
|
+
__publicField(this, "_objective", new Row());
|
|
1226
|
+
__publicField(this, "_artificial", null);
|
|
1227
|
+
__publicField(this, "_idTick", 0);
|
|
1228
|
+
}
|
|
1229
|
+
/**
|
|
1230
|
+
* Creates and add a constraint to the solver.
|
|
1231
|
+
*
|
|
1232
|
+
* @param {Expression|Variable} lhs Left hand side of the expression
|
|
1233
|
+
* @param {Operator} operator Operator
|
|
1234
|
+
* @param {Expression|Variable|Number} rhs Right hand side of the expression
|
|
1235
|
+
* @param {Number} [strength=Strength.required] Strength
|
|
1236
|
+
*/
|
|
1237
|
+
createConstraint(lhs, operator, rhs, strength = Strength.required) {
|
|
1238
|
+
let cn = new Constraint(lhs, operator, rhs, strength);
|
|
1239
|
+
this.addConstraint(cn);
|
|
1240
|
+
return cn;
|
|
1241
|
+
}
|
|
1242
|
+
/**
|
|
1243
|
+
* Add a constraint to the solver.
|
|
1244
|
+
*
|
|
1245
|
+
* @param {Constraint} constraint Constraint to add to the solver
|
|
1246
|
+
*/
|
|
1247
|
+
addConstraint(constraint) {
|
|
1248
|
+
let cnPair = this._cnMap.find(constraint);
|
|
1249
|
+
if (cnPair !== void 0) {
|
|
1250
|
+
throw new Error("duplicate constraint");
|
|
1251
|
+
}
|
|
1252
|
+
let data = this._createRow(constraint);
|
|
1253
|
+
let row = data.row;
|
|
1254
|
+
let tag = data.tag;
|
|
1255
|
+
let subject = this._chooseSubject(row, tag);
|
|
1256
|
+
if (subject.type() === SymbolType.Invalid && row.allDummies()) {
|
|
1257
|
+
if (!nearZero(row.constant())) {
|
|
1258
|
+
throw new Error("unsatisfiable constraint");
|
|
1259
|
+
} else {
|
|
1260
|
+
subject = tag.marker;
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
if (subject.type() === SymbolType.Invalid) {
|
|
1264
|
+
if (!this._addWithArtificialVariable(row)) {
|
|
1265
|
+
throw new Error("unsatisfiable constraint");
|
|
1266
|
+
}
|
|
1267
|
+
} else {
|
|
1268
|
+
row.solveFor(subject);
|
|
1269
|
+
this._substitute(subject, row);
|
|
1270
|
+
this._rowMap.insert(subject, row);
|
|
1271
|
+
}
|
|
1272
|
+
this._cnMap.insert(constraint, tag);
|
|
1273
|
+
this._optimize(this._objective);
|
|
1274
|
+
}
|
|
1275
|
+
/**
|
|
1276
|
+
* Remove a constraint from the solver.
|
|
1277
|
+
*
|
|
1278
|
+
* @param {Constraint} constraint Constraint to remove from the solver
|
|
1279
|
+
*/
|
|
1280
|
+
removeConstraint(constraint) {
|
|
1281
|
+
let cnPair = this._cnMap.erase(constraint);
|
|
1282
|
+
if (cnPair === void 0) {
|
|
1283
|
+
throw new Error("unknown constraint");
|
|
1284
|
+
}
|
|
1285
|
+
this._removeConstraintEffects(constraint, cnPair.second);
|
|
1286
|
+
let marker = cnPair.second.marker;
|
|
1287
|
+
let rowPair = this._rowMap.erase(marker);
|
|
1288
|
+
if (rowPair === void 0) {
|
|
1289
|
+
let leaving = this._getMarkerLeavingSymbol(marker);
|
|
1290
|
+
if (leaving.type() === SymbolType.Invalid) {
|
|
1291
|
+
throw new Error("failed to find leaving row");
|
|
1292
|
+
}
|
|
1293
|
+
rowPair = this._rowMap.erase(leaving);
|
|
1294
|
+
rowPair.second.solveForEx(leaving, marker);
|
|
1295
|
+
this._substitute(marker, rowPair.second);
|
|
1296
|
+
}
|
|
1297
|
+
this._optimize(this._objective);
|
|
1298
|
+
}
|
|
1299
|
+
/**
|
|
1300
|
+
* Test whether the solver contains the constraint.
|
|
1301
|
+
*
|
|
1302
|
+
* @param {Constraint} constraint Constraint to test for
|
|
1303
|
+
* @return {Bool} true or false
|
|
1304
|
+
*/
|
|
1305
|
+
hasConstraint(constraint) {
|
|
1306
|
+
return this._cnMap.contains(constraint);
|
|
1307
|
+
}
|
|
1308
|
+
/**
|
|
1309
|
+
* Get an array of the current constraints.
|
|
1310
|
+
*
|
|
1311
|
+
* @return {Constraint[]}
|
|
1312
|
+
*/
|
|
1313
|
+
getConstraints() {
|
|
1314
|
+
return this._cnMap.array.map(({ first }) => first);
|
|
1315
|
+
}
|
|
1316
|
+
/**
|
|
1317
|
+
* Add an edit variable to the solver.
|
|
1318
|
+
*
|
|
1319
|
+
* @param {Variable} variable Edit variable to add to the solver
|
|
1320
|
+
* @param {Number} strength Strength, should be less than `Strength.required`
|
|
1321
|
+
*/
|
|
1322
|
+
addEditVariable(variable, strength) {
|
|
1323
|
+
let editPair = this._editMap.find(variable);
|
|
1324
|
+
if (editPair !== void 0) {
|
|
1325
|
+
throw new Error("duplicate edit variable");
|
|
1326
|
+
}
|
|
1327
|
+
strength = Strength.clip(strength);
|
|
1328
|
+
if (strength === Strength.required) {
|
|
1329
|
+
throw new Error("bad required strength");
|
|
1330
|
+
}
|
|
1331
|
+
let expr = new Expression(variable);
|
|
1332
|
+
let cn = new Constraint(expr, Operator.Eq, void 0, strength);
|
|
1333
|
+
this.addConstraint(cn);
|
|
1334
|
+
let tag = this._cnMap.find(cn).second;
|
|
1335
|
+
let info = { tag, constraint: cn, constant: 0 };
|
|
1336
|
+
this._editMap.insert(variable, info);
|
|
1337
|
+
}
|
|
1338
|
+
/**
|
|
1339
|
+
* Remove an edit variable from the solver.
|
|
1340
|
+
*
|
|
1341
|
+
* @param {Variable} variable Edit variable to remove from the solver
|
|
1342
|
+
*/
|
|
1343
|
+
removeEditVariable(variable) {
|
|
1344
|
+
let editPair = this._editMap.erase(variable);
|
|
1345
|
+
if (editPair === void 0) {
|
|
1346
|
+
throw new Error("unknown edit variable");
|
|
1347
|
+
}
|
|
1348
|
+
this.removeConstraint(editPair.second.constraint);
|
|
1349
|
+
}
|
|
1350
|
+
/**
|
|
1351
|
+
* Test whether the solver contains the edit variable.
|
|
1352
|
+
*
|
|
1353
|
+
* @param {Variable} variable Edit variable to test for
|
|
1354
|
+
* @return {Bool} true or false
|
|
1355
|
+
*/
|
|
1356
|
+
hasEditVariable(variable) {
|
|
1357
|
+
return this._editMap.contains(variable);
|
|
1358
|
+
}
|
|
1359
|
+
/**
|
|
1360
|
+
* Suggest the value of an edit variable.
|
|
1361
|
+
*
|
|
1362
|
+
* @param {Variable} variable Edit variable to suggest a value for
|
|
1363
|
+
* @param {Number} value Suggested value
|
|
1364
|
+
*/
|
|
1365
|
+
suggestValue(variable, value) {
|
|
1366
|
+
let editPair = this._editMap.find(variable);
|
|
1367
|
+
if (editPair === void 0) {
|
|
1368
|
+
throw new Error("unknown edit variable");
|
|
1369
|
+
}
|
|
1370
|
+
let rows = this._rowMap;
|
|
1371
|
+
let info = editPair.second;
|
|
1372
|
+
let delta = value - info.constant;
|
|
1373
|
+
info.constant = value;
|
|
1374
|
+
let marker = info.tag.marker;
|
|
1375
|
+
let rowPair = rows.find(marker);
|
|
1376
|
+
if (rowPair !== void 0) {
|
|
1377
|
+
if (rowPair.second.add(-delta) < 0) {
|
|
1378
|
+
this._infeasibleRows.push(marker);
|
|
1379
|
+
}
|
|
1380
|
+
this._dualOptimize();
|
|
1381
|
+
return;
|
|
1382
|
+
}
|
|
1383
|
+
let other = info.tag.other;
|
|
1384
|
+
rowPair = rows.find(other);
|
|
1385
|
+
if (rowPair !== void 0) {
|
|
1386
|
+
if (rowPair.second.add(delta) < 0) {
|
|
1387
|
+
this._infeasibleRows.push(other);
|
|
1388
|
+
}
|
|
1389
|
+
this._dualOptimize();
|
|
1390
|
+
return;
|
|
1391
|
+
}
|
|
1392
|
+
for (let i = 0, n = rows.size(); i < n; ++i) {
|
|
1393
|
+
let rowPair2 = rows.itemAt(i);
|
|
1394
|
+
let row = rowPair2.second;
|
|
1395
|
+
let coeff = row.coefficientFor(marker);
|
|
1396
|
+
if (coeff !== 0 && row.add(delta * coeff) < 0 && rowPair2.first.type() !== SymbolType.External) {
|
|
1397
|
+
this._infeasibleRows.push(rowPair2.first);
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
this._dualOptimize();
|
|
1401
|
+
}
|
|
1402
|
+
/**
|
|
1403
|
+
* Update the values of the variables.
|
|
1404
|
+
*/
|
|
1405
|
+
updateVariables() {
|
|
1406
|
+
let vars2 = this._varMap;
|
|
1407
|
+
let rows = this._rowMap;
|
|
1408
|
+
for (let i = 0, n = vars2.size(); i < n; ++i) {
|
|
1409
|
+
let pair = vars2.itemAt(i);
|
|
1410
|
+
let rowPair = rows.find(pair.second);
|
|
1411
|
+
if (rowPair !== void 0) {
|
|
1412
|
+
pair.first.setValue(rowPair.second.constant());
|
|
1413
|
+
} else {
|
|
1414
|
+
pair.first.setValue(0);
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
/**
|
|
1419
|
+
* Get the symbol for the given variable.
|
|
1420
|
+
*
|
|
1421
|
+
* If a symbol does not exist for the variable, one will be created.
|
|
1422
|
+
* @private
|
|
1423
|
+
*/
|
|
1424
|
+
_getVarSymbol(variable) {
|
|
1425
|
+
let factory = () => this._makeSymbol(SymbolType.External);
|
|
1426
|
+
return this._varMap.setDefault(variable, factory).second;
|
|
1427
|
+
}
|
|
1428
|
+
/**
|
|
1429
|
+
* Create a new Row object for the given constraint.
|
|
1430
|
+
*
|
|
1431
|
+
* The terms in the constraint will be converted to cells in the row.
|
|
1432
|
+
* Any term in the constraint with a coefficient of zero is ignored.
|
|
1433
|
+
* This method uses the `_getVarSymbol` method to get the symbol for
|
|
1434
|
+
* the variables added to the row. If the symbol for a given cell
|
|
1435
|
+
* variable is basic, the cell variable will be substituted with the
|
|
1436
|
+
* basic row.
|
|
1437
|
+
*
|
|
1438
|
+
* The necessary slack and error variables will be added to the row.
|
|
1439
|
+
* If the constant for the row is negative, the sign for the row
|
|
1440
|
+
* will be inverted so the constant becomes positive.
|
|
1441
|
+
*
|
|
1442
|
+
* Returns the created Row and the tag for tracking the constraint.
|
|
1443
|
+
* @private
|
|
1444
|
+
*/
|
|
1445
|
+
_createRow(constraint) {
|
|
1446
|
+
let expr = constraint.expression();
|
|
1447
|
+
let row = new Row(expr.constant());
|
|
1448
|
+
let terms = expr.terms();
|
|
1449
|
+
for (let i = 0, n = terms.size(); i < n; ++i) {
|
|
1450
|
+
let termPair = terms.itemAt(i);
|
|
1451
|
+
if (!nearZero(termPair.second)) {
|
|
1452
|
+
let symbol = this._getVarSymbol(termPair.first);
|
|
1453
|
+
let basicPair = this._rowMap.find(symbol);
|
|
1454
|
+
if (basicPair !== void 0) {
|
|
1455
|
+
row.insertRow(basicPair.second, termPair.second);
|
|
1456
|
+
} else {
|
|
1457
|
+
row.insertSymbol(symbol, termPair.second);
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
let objective = this._objective;
|
|
1462
|
+
let strength = constraint.strength();
|
|
1463
|
+
let tag = { marker: INVALID_SYMBOL, other: INVALID_SYMBOL };
|
|
1464
|
+
switch (constraint.op()) {
|
|
1465
|
+
case Operator.Le:
|
|
1466
|
+
case Operator.Ge: {
|
|
1467
|
+
let coeff = constraint.op() === Operator.Le ? 1 : -1;
|
|
1468
|
+
let slack = this._makeSymbol(SymbolType.Slack);
|
|
1469
|
+
tag.marker = slack;
|
|
1470
|
+
row.insertSymbol(slack, coeff);
|
|
1471
|
+
if (strength < Strength.required) {
|
|
1472
|
+
let error = this._makeSymbol(SymbolType.Error);
|
|
1473
|
+
tag.other = error;
|
|
1474
|
+
row.insertSymbol(error, -coeff);
|
|
1475
|
+
objective.insertSymbol(error, strength);
|
|
1476
|
+
}
|
|
1477
|
+
break;
|
|
1478
|
+
}
|
|
1479
|
+
case Operator.Eq: {
|
|
1480
|
+
if (strength < Strength.required) {
|
|
1481
|
+
let errplus = this._makeSymbol(SymbolType.Error);
|
|
1482
|
+
let errminus = this._makeSymbol(SymbolType.Error);
|
|
1483
|
+
tag.marker = errplus;
|
|
1484
|
+
tag.other = errminus;
|
|
1485
|
+
row.insertSymbol(errplus, -1);
|
|
1486
|
+
row.insertSymbol(errminus, 1);
|
|
1487
|
+
objective.insertSymbol(errplus, strength);
|
|
1488
|
+
objective.insertSymbol(errminus, strength);
|
|
1489
|
+
} else {
|
|
1490
|
+
let dummy = this._makeSymbol(SymbolType.Dummy);
|
|
1491
|
+
tag.marker = dummy;
|
|
1492
|
+
row.insertSymbol(dummy);
|
|
1493
|
+
}
|
|
1494
|
+
break;
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
if (row.constant() < 0) {
|
|
1498
|
+
row.reverseSign();
|
|
1499
|
+
}
|
|
1500
|
+
return { row, tag };
|
|
1501
|
+
}
|
|
1502
|
+
/**
|
|
1503
|
+
* Choose the subject for solving for the row.
|
|
1504
|
+
*
|
|
1505
|
+
* This method will choose the best subject for using as the solve
|
|
1506
|
+
* target for the row. An invalid symbol will be returned if there
|
|
1507
|
+
* is no valid target.
|
|
1508
|
+
*
|
|
1509
|
+
* The symbols are chosen according to the following precedence:
|
|
1510
|
+
*
|
|
1511
|
+
* 1) The first symbol representing an external variable.
|
|
1512
|
+
* 2) A negative slack or error tag variable.
|
|
1513
|
+
*
|
|
1514
|
+
* If a subject cannot be found, an invalid symbol will be returned.
|
|
1515
|
+
*
|
|
1516
|
+
* @private
|
|
1517
|
+
*/
|
|
1518
|
+
_chooseSubject(row, tag) {
|
|
1519
|
+
let cells = row.cells();
|
|
1520
|
+
for (let i = 0, n = cells.size(); i < n; ++i) {
|
|
1521
|
+
let pair = cells.itemAt(i);
|
|
1522
|
+
if (pair.first.type() === SymbolType.External) {
|
|
1523
|
+
return pair.first;
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
let type = tag.marker.type();
|
|
1527
|
+
if (type === SymbolType.Slack || type === SymbolType.Error) {
|
|
1528
|
+
if (row.coefficientFor(tag.marker) < 0) {
|
|
1529
|
+
return tag.marker;
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
type = tag.other.type();
|
|
1533
|
+
if (type === SymbolType.Slack || type === SymbolType.Error) {
|
|
1534
|
+
if (row.coefficientFor(tag.other) < 0) {
|
|
1535
|
+
return tag.other;
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
return INVALID_SYMBOL;
|
|
1539
|
+
}
|
|
1540
|
+
/**
|
|
1541
|
+
* Add the row to the tableau using an artificial variable.
|
|
1542
|
+
*
|
|
1543
|
+
* This will return false if the constraint cannot be satisfied.
|
|
1544
|
+
*
|
|
1545
|
+
* @private
|
|
1546
|
+
*/
|
|
1547
|
+
_addWithArtificialVariable(row) {
|
|
1548
|
+
let art = this._makeSymbol(SymbolType.Slack);
|
|
1549
|
+
this._rowMap.insert(art, row.copy());
|
|
1550
|
+
this._artificial = row.copy();
|
|
1551
|
+
this._optimize(this._artificial);
|
|
1552
|
+
let success = nearZero(this._artificial.constant());
|
|
1553
|
+
this._artificial = null;
|
|
1554
|
+
let pair = this._rowMap.erase(art);
|
|
1555
|
+
if (pair !== void 0) {
|
|
1556
|
+
let basicRow = pair.second;
|
|
1557
|
+
if (basicRow.isConstant()) {
|
|
1558
|
+
return success;
|
|
1559
|
+
}
|
|
1560
|
+
let entering = this._anyPivotableSymbol(basicRow);
|
|
1561
|
+
if (entering.type() === SymbolType.Invalid) {
|
|
1562
|
+
return false;
|
|
1563
|
+
}
|
|
1564
|
+
basicRow.solveForEx(art, entering);
|
|
1565
|
+
this._substitute(entering, basicRow);
|
|
1566
|
+
this._rowMap.insert(entering, basicRow);
|
|
1567
|
+
}
|
|
1568
|
+
let rows = this._rowMap;
|
|
1569
|
+
for (let i = 0, n = rows.size(); i < n; ++i) {
|
|
1570
|
+
rows.itemAt(i).second.removeSymbol(art);
|
|
1571
|
+
}
|
|
1572
|
+
this._objective.removeSymbol(art);
|
|
1573
|
+
return success;
|
|
1574
|
+
}
|
|
1575
|
+
/**
|
|
1576
|
+
* Substitute the parametric symbol with the given row.
|
|
1577
|
+
*
|
|
1578
|
+
* This method will substitute all instances of the parametric symbol
|
|
1579
|
+
* in the tableau and the objective function with the given row.
|
|
1580
|
+
*
|
|
1581
|
+
* @private
|
|
1582
|
+
*/
|
|
1583
|
+
_substitute(symbol, row) {
|
|
1584
|
+
let rows = this._rowMap;
|
|
1585
|
+
for (let i = 0, n = rows.size(); i < n; ++i) {
|
|
1586
|
+
let pair = rows.itemAt(i);
|
|
1587
|
+
pair.second.substitute(symbol, row);
|
|
1588
|
+
if (pair.second.constant() < 0 && pair.first.type() !== SymbolType.External) {
|
|
1589
|
+
this._infeasibleRows.push(pair.first);
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
this._objective.substitute(symbol, row);
|
|
1593
|
+
if (this._artificial) {
|
|
1594
|
+
this._artificial.substitute(symbol, row);
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
/**
|
|
1598
|
+
* Optimize the system for the given objective function.
|
|
1599
|
+
*
|
|
1600
|
+
* This method performs iterations of Phase 2 of the simplex method
|
|
1601
|
+
* until the objective function reaches a minimum.
|
|
1602
|
+
*
|
|
1603
|
+
* @private
|
|
1604
|
+
*/
|
|
1605
|
+
_optimize(objective) {
|
|
1606
|
+
let iterations = 0;
|
|
1607
|
+
while (iterations < this.maxIterations) {
|
|
1608
|
+
let entering = this._getEnteringSymbol(objective);
|
|
1609
|
+
if (entering.type() === SymbolType.Invalid) {
|
|
1610
|
+
return;
|
|
1611
|
+
}
|
|
1612
|
+
let leaving = this._getLeavingSymbol(entering);
|
|
1613
|
+
if (leaving.type() === SymbolType.Invalid) {
|
|
1614
|
+
throw new Error("the objective is unbounded");
|
|
1615
|
+
}
|
|
1616
|
+
let row = this._rowMap.erase(leaving).second;
|
|
1617
|
+
row.solveForEx(leaving, entering);
|
|
1618
|
+
this._substitute(entering, row);
|
|
1619
|
+
this._rowMap.insert(entering, row);
|
|
1620
|
+
iterations++;
|
|
1621
|
+
}
|
|
1622
|
+
throw new Error("solver iterations exceeded");
|
|
1623
|
+
}
|
|
1624
|
+
/**
|
|
1625
|
+
* Optimize the system using the dual of the simplex method.
|
|
1626
|
+
*
|
|
1627
|
+
* The current state of the system should be such that the objective
|
|
1628
|
+
* function is optimal, but not feasible. This method will perform
|
|
1629
|
+
* an iteration of the dual simplex method to make the solution both
|
|
1630
|
+
* optimal and feasible.
|
|
1631
|
+
*
|
|
1632
|
+
* @private
|
|
1633
|
+
*/
|
|
1634
|
+
_dualOptimize() {
|
|
1635
|
+
let rows = this._rowMap;
|
|
1636
|
+
let infeasible = this._infeasibleRows;
|
|
1637
|
+
while (infeasible.length !== 0) {
|
|
1638
|
+
let leaving = infeasible.pop();
|
|
1639
|
+
let pair = rows.find(leaving);
|
|
1640
|
+
if (pair !== void 0 && pair.second.constant() < 0) {
|
|
1641
|
+
let entering = this._getDualEnteringSymbol(pair.second);
|
|
1642
|
+
if (entering.type() === SymbolType.Invalid) {
|
|
1643
|
+
throw new Error("dual optimize failed");
|
|
1644
|
+
}
|
|
1645
|
+
let row = pair.second;
|
|
1646
|
+
rows.erase(leaving);
|
|
1647
|
+
row.solveForEx(leaving, entering);
|
|
1648
|
+
this._substitute(entering, row);
|
|
1649
|
+
rows.insert(entering, row);
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
}
|
|
1653
|
+
/**
|
|
1654
|
+
* Compute the entering variable for a pivot operation.
|
|
1655
|
+
*
|
|
1656
|
+
* This method will return first symbol in the objective function which
|
|
1657
|
+
* is non-dummy and has a coefficient less than zero. If no symbol meets
|
|
1658
|
+
* the criteria, it means the objective function is at a minimum, and an
|
|
1659
|
+
* invalid symbol is returned.
|
|
1660
|
+
*
|
|
1661
|
+
* @private
|
|
1662
|
+
*/
|
|
1663
|
+
_getEnteringSymbol(objective) {
|
|
1664
|
+
let cells = objective.cells();
|
|
1665
|
+
for (let i = 0, n = cells.size(); i < n; ++i) {
|
|
1666
|
+
let pair = cells.itemAt(i);
|
|
1667
|
+
let symbol = pair.first;
|
|
1668
|
+
if (pair.second < 0 && symbol.type() !== SymbolType.Dummy) {
|
|
1669
|
+
return symbol;
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
return INVALID_SYMBOL;
|
|
1673
|
+
}
|
|
1674
|
+
/**
|
|
1675
|
+
* Compute the entering symbol for the dual optimize operation.
|
|
1676
|
+
*
|
|
1677
|
+
* This method will return the symbol in the row which has a positive
|
|
1678
|
+
* coefficient and yields the minimum ratio for its respective symbol
|
|
1679
|
+
* in the objective function. The provided row *must* be infeasible.
|
|
1680
|
+
* If no symbol is found which meats the criteria, an invalid symbol
|
|
1681
|
+
* is returned.
|
|
1682
|
+
*
|
|
1683
|
+
* @private
|
|
1684
|
+
*/
|
|
1685
|
+
_getDualEnteringSymbol(row) {
|
|
1686
|
+
let ratio = Number.MAX_VALUE;
|
|
1687
|
+
let entering = INVALID_SYMBOL;
|
|
1688
|
+
let cells = row.cells();
|
|
1689
|
+
for (let i = 0, n = cells.size(); i < n; ++i) {
|
|
1690
|
+
let pair = cells.itemAt(i);
|
|
1691
|
+
let symbol = pair.first;
|
|
1692
|
+
let c = pair.second;
|
|
1693
|
+
if (c > 0 && symbol.type() !== SymbolType.Dummy) {
|
|
1694
|
+
let coeff = this._objective.coefficientFor(symbol);
|
|
1695
|
+
let r = coeff / c;
|
|
1696
|
+
if (r < ratio) {
|
|
1697
|
+
ratio = r;
|
|
1698
|
+
entering = symbol;
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
return entering;
|
|
1703
|
+
}
|
|
1704
|
+
/**
|
|
1705
|
+
* Compute the symbol for pivot exit row.
|
|
1706
|
+
*
|
|
1707
|
+
* This method will return the symbol for the exit row in the row
|
|
1708
|
+
* map. If no appropriate exit symbol is found, an invalid symbol
|
|
1709
|
+
* will be returned. This indicates that the objective function is
|
|
1710
|
+
* unbounded.
|
|
1711
|
+
*
|
|
1712
|
+
* @private
|
|
1713
|
+
*/
|
|
1714
|
+
_getLeavingSymbol(entering) {
|
|
1715
|
+
let ratio = Number.MAX_VALUE;
|
|
1716
|
+
let found = INVALID_SYMBOL;
|
|
1717
|
+
let rows = this._rowMap;
|
|
1718
|
+
for (let i = 0, n = rows.size(); i < n; ++i) {
|
|
1719
|
+
let pair = rows.itemAt(i);
|
|
1720
|
+
let symbol = pair.first;
|
|
1721
|
+
if (symbol.type() !== SymbolType.External) {
|
|
1722
|
+
let row = pair.second;
|
|
1723
|
+
let temp = row.coefficientFor(entering);
|
|
1724
|
+
if (temp < 0) {
|
|
1725
|
+
let temp_ratio = -row.constant() / temp;
|
|
1726
|
+
if (temp_ratio < ratio) {
|
|
1727
|
+
ratio = temp_ratio;
|
|
1728
|
+
found = symbol;
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
return found;
|
|
1734
|
+
}
|
|
1735
|
+
/**
|
|
1736
|
+
* Compute the leaving symbol for a marker variable.
|
|
1737
|
+
*
|
|
1738
|
+
* This method will return a symbol corresponding to a basic row
|
|
1739
|
+
* which holds the given marker variable. The row will be chosen
|
|
1740
|
+
* according to the following precedence:
|
|
1741
|
+
*
|
|
1742
|
+
* 1) The row with a restricted basic varible and a negative coefficient
|
|
1743
|
+
* for the marker with the smallest ratio of -constant / coefficient.
|
|
1744
|
+
*
|
|
1745
|
+
* 2) The row with a restricted basic variable and the smallest ratio
|
|
1746
|
+
* of constant / coefficient.
|
|
1747
|
+
*
|
|
1748
|
+
* 3) The last unrestricted row which contains the marker.
|
|
1749
|
+
*
|
|
1750
|
+
* If the marker does not exist in any row, an invalid symbol will be
|
|
1751
|
+
* returned. This indicates an internal solver error since the marker
|
|
1752
|
+
* *should* exist somewhere in the tableau.
|
|
1753
|
+
*
|
|
1754
|
+
* @private
|
|
1755
|
+
*/
|
|
1756
|
+
_getMarkerLeavingSymbol(marker) {
|
|
1757
|
+
let dmax = Number.MAX_VALUE;
|
|
1758
|
+
let r1 = dmax;
|
|
1759
|
+
let r2 = dmax;
|
|
1760
|
+
let invalid = INVALID_SYMBOL;
|
|
1761
|
+
let first = invalid;
|
|
1762
|
+
let second = invalid;
|
|
1763
|
+
let third = invalid;
|
|
1764
|
+
let rows = this._rowMap;
|
|
1765
|
+
for (let i = 0, n = rows.size(); i < n; ++i) {
|
|
1766
|
+
let pair = rows.itemAt(i);
|
|
1767
|
+
let row = pair.second;
|
|
1768
|
+
let c = row.coefficientFor(marker);
|
|
1769
|
+
if (c === 0) {
|
|
1770
|
+
continue;
|
|
1771
|
+
}
|
|
1772
|
+
let symbol = pair.first;
|
|
1773
|
+
if (symbol.type() === SymbolType.External) {
|
|
1774
|
+
third = symbol;
|
|
1775
|
+
} else if (c < 0) {
|
|
1776
|
+
let r = -row.constant() / c;
|
|
1777
|
+
if (r < r1) {
|
|
1778
|
+
r1 = r;
|
|
1779
|
+
first = symbol;
|
|
1780
|
+
}
|
|
1781
|
+
} else {
|
|
1782
|
+
let r = row.constant() / c;
|
|
1783
|
+
if (r < r2) {
|
|
1784
|
+
r2 = r;
|
|
1785
|
+
second = symbol;
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
}
|
|
1789
|
+
if (first !== invalid) {
|
|
1790
|
+
return first;
|
|
1791
|
+
}
|
|
1792
|
+
if (second !== invalid) {
|
|
1793
|
+
return second;
|
|
1794
|
+
}
|
|
1795
|
+
return third;
|
|
1796
|
+
}
|
|
1797
|
+
/**
|
|
1798
|
+
* Remove the effects of a constraint on the objective function.
|
|
1799
|
+
*
|
|
1800
|
+
* @private
|
|
1801
|
+
*/
|
|
1802
|
+
_removeConstraintEffects(cn, tag) {
|
|
1803
|
+
if (tag.marker.type() === SymbolType.Error) {
|
|
1804
|
+
this._removeMarkerEffects(tag.marker, cn.strength());
|
|
1805
|
+
}
|
|
1806
|
+
if (tag.other.type() === SymbolType.Error) {
|
|
1807
|
+
this._removeMarkerEffects(tag.other, cn.strength());
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
/**
|
|
1811
|
+
* Remove the effects of an error marker on the objective function.
|
|
1812
|
+
*
|
|
1813
|
+
* @private
|
|
1814
|
+
*/
|
|
1815
|
+
_removeMarkerEffects(marker, strength) {
|
|
1816
|
+
let pair = this._rowMap.find(marker);
|
|
1817
|
+
if (pair !== void 0) {
|
|
1818
|
+
this._objective.insertRow(pair.second, -strength);
|
|
1819
|
+
} else {
|
|
1820
|
+
this._objective.insertSymbol(marker, -strength);
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
/**
|
|
1824
|
+
* Get the first Slack or Error symbol in the row.
|
|
1825
|
+
*
|
|
1826
|
+
* If no such symbol is present, an invalid symbol will be returned.
|
|
1827
|
+
*
|
|
1828
|
+
* @private
|
|
1829
|
+
*/
|
|
1830
|
+
_anyPivotableSymbol(row) {
|
|
1831
|
+
let cells = row.cells();
|
|
1832
|
+
for (let i = 0, n = cells.size(); i < n; ++i) {
|
|
1833
|
+
let pair = cells.itemAt(i);
|
|
1834
|
+
let type = pair.first.type();
|
|
1835
|
+
if (type === SymbolType.Slack || type === SymbolType.Error) {
|
|
1836
|
+
return pair.first;
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
return INVALID_SYMBOL;
|
|
1840
|
+
}
|
|
1841
|
+
/**
|
|
1842
|
+
* Returns a new Symbol of the given type.
|
|
1843
|
+
*
|
|
1844
|
+
* @private
|
|
1845
|
+
*/
|
|
1846
|
+
_makeSymbol(type) {
|
|
1847
|
+
return new Symbol$1(type, this._idTick++);
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
function nearZero(value) {
|
|
1851
|
+
let eps = 1e-8;
|
|
1852
|
+
return value < 0 ? -value < eps : value < eps;
|
|
1853
|
+
}
|
|
1854
|
+
function createCnMap() {
|
|
1855
|
+
return createMap();
|
|
1856
|
+
}
|
|
1857
|
+
function createRowMap() {
|
|
1858
|
+
return createMap();
|
|
1859
|
+
}
|
|
1860
|
+
function createVarMap() {
|
|
1861
|
+
return createMap();
|
|
1862
|
+
}
|
|
1863
|
+
function createEditMap() {
|
|
1864
|
+
return createMap();
|
|
1865
|
+
}
|
|
1866
|
+
var SymbolType;
|
|
1867
|
+
(function(SymbolType2) {
|
|
1868
|
+
SymbolType2[SymbolType2["Invalid"] = 0] = "Invalid";
|
|
1869
|
+
SymbolType2[SymbolType2["External"] = 1] = "External";
|
|
1870
|
+
SymbolType2[SymbolType2["Slack"] = 2] = "Slack";
|
|
1871
|
+
SymbolType2[SymbolType2["Error"] = 3] = "Error";
|
|
1872
|
+
SymbolType2[SymbolType2["Dummy"] = 4] = "Dummy";
|
|
1873
|
+
})(SymbolType || (SymbolType = {}));
|
|
1874
|
+
let Symbol$1 = class Symbol2 {
|
|
1875
|
+
/**
|
|
1876
|
+
* Construct a new Symbol
|
|
1877
|
+
*
|
|
1878
|
+
* @param [type] The type of the symbol.
|
|
1879
|
+
* @param [id] The unique id number of the symbol.
|
|
1880
|
+
*/
|
|
1881
|
+
constructor(type, id) {
|
|
1882
|
+
__publicField(this, "_id");
|
|
1883
|
+
__publicField(this, "_type");
|
|
1884
|
+
this._id = id;
|
|
1885
|
+
this._type = type;
|
|
1886
|
+
}
|
|
1887
|
+
/**
|
|
1888
|
+
* Returns the unique id number of the symbol.
|
|
1889
|
+
*/
|
|
1890
|
+
id() {
|
|
1891
|
+
return this._id;
|
|
1892
|
+
}
|
|
1893
|
+
/**
|
|
1894
|
+
* Returns the type of the symbol.
|
|
1895
|
+
*/
|
|
1896
|
+
type() {
|
|
1897
|
+
return this._type;
|
|
1898
|
+
}
|
|
1899
|
+
};
|
|
1900
|
+
let INVALID_SYMBOL = new Symbol$1(SymbolType.Invalid, -1);
|
|
1901
|
+
class Row {
|
|
1902
|
+
/**
|
|
1903
|
+
* Construct a new Row.
|
|
1904
|
+
*/
|
|
1905
|
+
constructor(constant = 0) {
|
|
1906
|
+
__publicField(this, "_cellMap", createMap());
|
|
1907
|
+
__publicField(this, "_constant");
|
|
1908
|
+
this._constant = constant;
|
|
1909
|
+
}
|
|
1910
|
+
/**
|
|
1911
|
+
* Returns the mapping of symbols to coefficients.
|
|
1912
|
+
*/
|
|
1913
|
+
cells() {
|
|
1914
|
+
return this._cellMap;
|
|
1915
|
+
}
|
|
1916
|
+
/**
|
|
1917
|
+
* Returns the constant for the row.
|
|
1918
|
+
*/
|
|
1919
|
+
constant() {
|
|
1920
|
+
return this._constant;
|
|
1921
|
+
}
|
|
1922
|
+
/**
|
|
1923
|
+
* Returns true if the row is a constant value.
|
|
1924
|
+
*/
|
|
1925
|
+
isConstant() {
|
|
1926
|
+
return this._cellMap.empty();
|
|
1927
|
+
}
|
|
1928
|
+
/**
|
|
1929
|
+
* Returns true if the Row has all dummy symbols.
|
|
1930
|
+
*/
|
|
1931
|
+
allDummies() {
|
|
1932
|
+
let cells = this._cellMap;
|
|
1933
|
+
for (let i = 0, n = cells.size(); i < n; ++i) {
|
|
1934
|
+
let pair = cells.itemAt(i);
|
|
1935
|
+
if (pair.first.type() !== SymbolType.Dummy) {
|
|
1936
|
+
return false;
|
|
1937
|
+
}
|
|
1938
|
+
}
|
|
1939
|
+
return true;
|
|
1940
|
+
}
|
|
1941
|
+
/**
|
|
1942
|
+
* Create a copy of the row.
|
|
1943
|
+
*/
|
|
1944
|
+
copy() {
|
|
1945
|
+
let theCopy = new Row(this._constant);
|
|
1946
|
+
theCopy._cellMap = this._cellMap.copy();
|
|
1947
|
+
return theCopy;
|
|
1948
|
+
}
|
|
1949
|
+
/**
|
|
1950
|
+
* Add a constant value to the row constant.
|
|
1951
|
+
*
|
|
1952
|
+
* Returns the new value of the constant.
|
|
1953
|
+
*/
|
|
1954
|
+
add(value) {
|
|
1955
|
+
return this._constant += value;
|
|
1956
|
+
}
|
|
1957
|
+
/**
|
|
1958
|
+
* Insert the symbol into the row with the given coefficient.
|
|
1959
|
+
*
|
|
1960
|
+
* If the symbol already exists in the row, the coefficient
|
|
1961
|
+
* will be added to the existing coefficient. If the resulting
|
|
1962
|
+
* coefficient is zero, the symbol will be removed from the row.
|
|
1963
|
+
*/
|
|
1964
|
+
insertSymbol(symbol, coefficient = 1) {
|
|
1965
|
+
let pair = this._cellMap.setDefault(symbol, () => 0);
|
|
1966
|
+
if (nearZero(pair.second += coefficient)) {
|
|
1967
|
+
this._cellMap.erase(symbol);
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1970
|
+
/**
|
|
1971
|
+
* Insert a row into this row with a given coefficient.
|
|
1972
|
+
*
|
|
1973
|
+
* The constant and the cells of the other row will be
|
|
1974
|
+
* multiplied by the coefficient and added to this row. Any
|
|
1975
|
+
* cell with a resulting coefficient of zero will be removed
|
|
1976
|
+
* from the row.
|
|
1977
|
+
*/
|
|
1978
|
+
insertRow(other, coefficient = 1) {
|
|
1979
|
+
this._constant += other._constant * coefficient;
|
|
1980
|
+
let cells = other._cellMap;
|
|
1981
|
+
for (let i = 0, n = cells.size(); i < n; ++i) {
|
|
1982
|
+
let pair = cells.itemAt(i);
|
|
1983
|
+
this.insertSymbol(pair.first, pair.second * coefficient);
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
/**
|
|
1987
|
+
* Remove a symbol from the row.
|
|
1988
|
+
*/
|
|
1989
|
+
removeSymbol(symbol) {
|
|
1990
|
+
this._cellMap.erase(symbol);
|
|
1991
|
+
}
|
|
1992
|
+
/**
|
|
1993
|
+
* Reverse the sign of the constant and cells in the row.
|
|
1994
|
+
*/
|
|
1995
|
+
reverseSign() {
|
|
1996
|
+
this._constant = -this._constant;
|
|
1997
|
+
let cells = this._cellMap;
|
|
1998
|
+
for (let i = 0, n = cells.size(); i < n; ++i) {
|
|
1999
|
+
let pair = cells.itemAt(i);
|
|
2000
|
+
pair.second = -pair.second;
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
2003
|
+
/**
|
|
2004
|
+
* Solve the row for the given symbol.
|
|
2005
|
+
*
|
|
2006
|
+
* This method assumes the row is of the form
|
|
2007
|
+
* a * x + b * y + c = 0 and (assuming solve for x) will modify
|
|
2008
|
+
* the row to represent the right hand side of
|
|
2009
|
+
* x = -b/a * y - c / a. The target symbol will be removed from
|
|
2010
|
+
* the row, and the constant and other cells will be multiplied
|
|
2011
|
+
* by the negative inverse of the target coefficient.
|
|
2012
|
+
*
|
|
2013
|
+
* The given symbol *must* exist in the row.
|
|
2014
|
+
*/
|
|
2015
|
+
solveFor(symbol) {
|
|
2016
|
+
let cells = this._cellMap;
|
|
2017
|
+
let pair = cells.erase(symbol);
|
|
2018
|
+
let coeff = -1 / pair.second;
|
|
2019
|
+
this._constant *= coeff;
|
|
2020
|
+
for (let i = 0, n = cells.size(); i < n; ++i) {
|
|
2021
|
+
cells.itemAt(i).second *= coeff;
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
/**
|
|
2025
|
+
* Solve the row for the given symbols.
|
|
2026
|
+
*
|
|
2027
|
+
* This method assumes the row is of the form
|
|
2028
|
+
* x = b * y + c and will solve the row such that
|
|
2029
|
+
* y = x / b - c / b. The rhs symbol will be removed from the
|
|
2030
|
+
* row, the lhs added, and the result divided by the negative
|
|
2031
|
+
* inverse of the rhs coefficient.
|
|
2032
|
+
*
|
|
2033
|
+
* The lhs symbol *must not* exist in the row, and the rhs
|
|
2034
|
+
* symbol must* exist in the row.
|
|
2035
|
+
*/
|
|
2036
|
+
solveForEx(lhs, rhs) {
|
|
2037
|
+
this.insertSymbol(lhs, -1);
|
|
2038
|
+
this.solveFor(rhs);
|
|
2039
|
+
}
|
|
2040
|
+
/**
|
|
2041
|
+
* Returns the coefficient for the given symbol.
|
|
2042
|
+
*/
|
|
2043
|
+
coefficientFor(symbol) {
|
|
2044
|
+
let pair = this._cellMap.find(symbol);
|
|
2045
|
+
return pair !== void 0 ? pair.second : 0;
|
|
2046
|
+
}
|
|
2047
|
+
/**
|
|
2048
|
+
* Substitute a symbol with the data from another row.
|
|
2049
|
+
*
|
|
2050
|
+
* Given a row of the form a * x + b and a substitution of the
|
|
2051
|
+
* form x = 3 * y + c the row will be updated to reflect the
|
|
2052
|
+
* expression 3 * a * y + a * c + b.
|
|
2053
|
+
*
|
|
2054
|
+
* If the symbol does not exist in the row, this is a no-op.
|
|
2055
|
+
*/
|
|
2056
|
+
substitute(symbol, row) {
|
|
2057
|
+
let pair = this._cellMap.erase(symbol);
|
|
2058
|
+
if (pair !== void 0) {
|
|
2059
|
+
this.insertRow(row, pair.second);
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
2063
|
+
class Rect {
|
|
2064
|
+
constructor() {
|
|
2065
|
+
__publicField(this, "id");
|
|
2066
|
+
__publicField(this, "minX", new Variable());
|
|
2067
|
+
__publicField(this, "minY", new Variable());
|
|
2068
|
+
__publicField(this, "maxX", new Variable());
|
|
2069
|
+
__publicField(this, "maxY", new Variable());
|
|
2070
|
+
}
|
|
2071
|
+
get x() {
|
|
2072
|
+
return this.minX;
|
|
2073
|
+
}
|
|
2074
|
+
get y() {
|
|
2075
|
+
return this.minY;
|
|
2076
|
+
}
|
|
2077
|
+
get positionAbsolute() {
|
|
2078
|
+
return {
|
|
2079
|
+
x: this.x.value(),
|
|
2080
|
+
y: this.y.value()
|
|
2081
|
+
};
|
|
2082
|
+
}
|
|
2083
|
+
// Position relative to parent
|
|
2084
|
+
get position() {
|
|
2085
|
+
const positionAbsolute = this.positionAbsolute;
|
|
2086
|
+
return this.parent ? {
|
|
2087
|
+
x: positionAbsolute.x - this.parent.x.value(),
|
|
2088
|
+
y: positionAbsolute.y - this.parent.y.value()
|
|
2089
|
+
} : positionAbsolute;
|
|
2090
|
+
}
|
|
2091
|
+
}
|
|
2092
|
+
class Compound extends Rect {
|
|
2093
|
+
constructor(solver, xynode, parent = null) {
|
|
2094
|
+
super();
|
|
2095
|
+
__publicField(this, "children", []);
|
|
2096
|
+
this.solver = solver;
|
|
2097
|
+
this.parent = parent;
|
|
2098
|
+
this.id = xynode.id;
|
|
2099
|
+
solver.createConstraint(this.maxX, Operator.Ge, this.minX);
|
|
2100
|
+
solver.createConstraint(this.maxY, Operator.Ge, this.minY);
|
|
2101
|
+
if (parent) {
|
|
2102
|
+
parent.addChild(this);
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
addChild(rect) {
|
|
2106
|
+
this.children.push(rect);
|
|
2107
|
+
const leftPadding = new Expression(
|
|
2108
|
+
rect.minX,
|
|
2109
|
+
[-1, this.minX]
|
|
2110
|
+
);
|
|
2111
|
+
const { weak } = Strength;
|
|
2112
|
+
this.solver.createConstraint(leftPadding, Operator.Ge, 40);
|
|
2113
|
+
this.solver.createConstraint(leftPadding, Operator.Eq, 40, weak);
|
|
2114
|
+
const topPadding = new Expression(
|
|
2115
|
+
rect.minY,
|
|
2116
|
+
[-1, this.minY]
|
|
2117
|
+
);
|
|
2118
|
+
this.solver.createConstraint(topPadding, Operator.Ge, 60);
|
|
2119
|
+
this.solver.createConstraint(topPadding, Operator.Eq, 60, weak);
|
|
2120
|
+
const rightPadding = new Expression(
|
|
2121
|
+
this.maxX,
|
|
2122
|
+
[-1, rect.maxX]
|
|
2123
|
+
);
|
|
2124
|
+
this.solver.createConstraint(rightPadding, Operator.Ge, 40);
|
|
2125
|
+
this.solver.createConstraint(rightPadding, Operator.Eq, 40, weak);
|
|
2126
|
+
const bottomPadding = new Expression(
|
|
2127
|
+
this.maxY,
|
|
2128
|
+
[-1, rect.maxY]
|
|
2129
|
+
);
|
|
2130
|
+
this.solver.createConstraint(bottomPadding, Operator.Ge, 40);
|
|
2131
|
+
this.solver.createConstraint(bottomPadding, Operator.Eq, 40, weak);
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2134
|
+
class Leaf extends Rect {
|
|
2135
|
+
constructor(solver, xynode, parent = null, isEditing = false) {
|
|
2136
|
+
var _a, _b, _c;
|
|
2137
|
+
super();
|
|
2138
|
+
__publicField(this, "id");
|
|
2139
|
+
this.parent = parent;
|
|
2140
|
+
this.isEditing = isEditing;
|
|
2141
|
+
this.id = xynode.id;
|
|
2142
|
+
const pos = ((_a = xynode.computed) == null ? void 0 : _a.positionAbsolute) ?? {
|
|
2143
|
+
x: xynode.data.element.position[0],
|
|
2144
|
+
y: xynode.data.element.position[1]
|
|
2145
|
+
};
|
|
2146
|
+
const width = ((_b = xynode.computed) == null ? void 0 : _b.width) ?? xynode.data.element.width;
|
|
2147
|
+
const height = ((_c = xynode.computed) == null ? void 0 : _c.height) ?? xynode.data.element.height;
|
|
2148
|
+
this.maxX = new Expression(this.minX, width);
|
|
2149
|
+
this.maxY = new Expression(this.minY, height);
|
|
2150
|
+
if (isEditing) {
|
|
2151
|
+
const superStrong = Strength.create(100, 0, 0);
|
|
2152
|
+
solver.addEditVariable(this.minX, superStrong);
|
|
2153
|
+
solver.addEditVariable(this.minY, superStrong);
|
|
2154
|
+
solver.suggestValue(this.minX, pos.x);
|
|
2155
|
+
solver.suggestValue(this.minY, pos.y);
|
|
2156
|
+
} else {
|
|
2157
|
+
const halfMedium = Strength.create(0, 1, 0, 0.5);
|
|
2158
|
+
solver.createConstraint(this.minX, Operator.Eq, pos.x, halfMedium);
|
|
2159
|
+
solver.createConstraint(this.minY, Operator.Eq, pos.y, halfMedium);
|
|
2160
|
+
}
|
|
2161
|
+
if (parent) {
|
|
2162
|
+
parent.addChild(this);
|
|
2163
|
+
}
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2166
|
+
function createLayoutConstraints(xyflow, draggingNodeId) {
|
|
2167
|
+
const solver = new Solver();
|
|
2168
|
+
const rects = /* @__PURE__ */ new Map();
|
|
2169
|
+
const xynodes = xyflow.getNodes();
|
|
2170
|
+
const rootNodes = xynodes.filter((n) => isNullish(n.parentNode));
|
|
2171
|
+
const traverse = rootNodes.map((xynode) => ({
|
|
2172
|
+
xynode,
|
|
2173
|
+
parent: null
|
|
2174
|
+
}));
|
|
2175
|
+
while (traverse.length > 0) {
|
|
2176
|
+
const { xynode, parent } = traverse.pop();
|
|
2177
|
+
const isDragging = xynode.dragging === true || xynode.id === draggingNodeId;
|
|
2178
|
+
const isCompound = !isDragging && xynode.type === "compound" && core$1.isAncestor(xynode.id, draggingNodeId);
|
|
2179
|
+
const rect = isCompound ? new Compound(solver, xynode, parent) : new Leaf(solver, xynode, parent, isDragging);
|
|
2180
|
+
rects.set(xynode.id, rect);
|
|
2181
|
+
if (isCompound) {
|
|
2182
|
+
const children = xynodes.flatMap(
|
|
2183
|
+
(child) => child.parentNode === xynode.id ? {
|
|
2184
|
+
xynode: child,
|
|
2185
|
+
parent: rect
|
|
2186
|
+
} : []
|
|
2187
|
+
);
|
|
2188
|
+
traverse.push(
|
|
2189
|
+
...children
|
|
2190
|
+
);
|
|
2191
|
+
}
|
|
2192
|
+
}
|
|
2193
|
+
solver.updateVariables();
|
|
2194
|
+
solver.maxIterations = 1e3;
|
|
2195
|
+
function updateXYFlowNodes() {
|
|
2196
|
+
solver.updateVariables();
|
|
2197
|
+
xyflow.setNodes(
|
|
2198
|
+
(nodes) => nodes.map((n) => {
|
|
2199
|
+
if (n.id === draggingNodeId || n.dragging === true) {
|
|
2200
|
+
return n;
|
|
2201
|
+
}
|
|
2202
|
+
const rect = rects.get(n.id);
|
|
2203
|
+
if (!rect) {
|
|
2204
|
+
return n;
|
|
2205
|
+
}
|
|
2206
|
+
const newPosition = rect.position;
|
|
2207
|
+
n.position.x = newPosition.x;
|
|
2208
|
+
n.position.y = newPosition.y;
|
|
2209
|
+
n.width = rect.maxX.value() - rect.minX.value();
|
|
2210
|
+
n.height = rect.maxY.value() - rect.minY.value();
|
|
2211
|
+
return n;
|
|
2212
|
+
})
|
|
2213
|
+
);
|
|
2214
|
+
}
|
|
2215
|
+
let animationFrameId = null;
|
|
2216
|
+
function onNodeDrag(xynode) {
|
|
2217
|
+
var _a;
|
|
2218
|
+
const pos = core$1.nonNullable((_a = xynode.computed) == null ? void 0 : _a.positionAbsolute, "No positionAbsolute");
|
|
2219
|
+
const rect = core$1.nonNullable(rects.get(xynode.id));
|
|
2220
|
+
solver.suggestValue(rect.minX, pos.x);
|
|
2221
|
+
solver.suggestValue(rect.minY, pos.y);
|
|
2222
|
+
animationFrameId ?? (animationFrameId = window.requestAnimationFrame(() => {
|
|
2223
|
+
updateXYFlowNodes();
|
|
2224
|
+
animationFrameId = null;
|
|
2225
|
+
}));
|
|
2226
|
+
}
|
|
2227
|
+
return {
|
|
2228
|
+
onNodeDrag,
|
|
2229
|
+
updateXYFlowNodes
|
|
2230
|
+
};
|
|
2231
|
+
}
|
|
2232
|
+
function useLayoutConstraints(xyflow) {
|
|
2233
|
+
const solverRef = react.useRef();
|
|
2234
|
+
const constraintsRef = react.useRef();
|
|
2235
|
+
constraintsRef.current ?? (constraintsRef.current = {
|
|
2236
|
+
onNodeDragStart: (event, xynode) => {
|
|
2237
|
+
core$1.invariant(xyflow.current, "xyflow.current should be defined");
|
|
2238
|
+
core$1.invariant(!solverRef.current, "solverRef.current should be undefined");
|
|
2239
|
+
solverRef.current = createLayoutConstraints(xyflow.current, xynode.id);
|
|
2240
|
+
},
|
|
2241
|
+
onNodeDrag: (event, xynode) => {
|
|
2242
|
+
var _a;
|
|
2243
|
+
core$1.invariant(solverRef.current, "solverRef.current should be defined");
|
|
2244
|
+
(_a = solverRef.current) == null ? void 0 : _a.onNodeDrag(xynode);
|
|
2245
|
+
},
|
|
2246
|
+
onNodeDragStop: (event, xynode) => {
|
|
2247
|
+
solverRef.current = void 0;
|
|
2248
|
+
}
|
|
2249
|
+
});
|
|
2250
|
+
return constraintsRef.current;
|
|
2251
|
+
}
|
|
2252
|
+
const useXYFlow = react$1.useReactFlow;
|
|
2253
|
+
const useXYNodesData = react$1.useNodesData;
|
|
2254
|
+
const EventHandlersContext = react.createContext(null);
|
|
2255
|
+
function useXYFlowEvents() {
|
|
2256
|
+
const ctx = react.useContext(EventHandlersContext);
|
|
2257
|
+
return core$1.nonNullable(ctx, "useXYFlowEvents could be used only inside XYFlowEventHandlers");
|
|
2258
|
+
}
|
|
2259
|
+
function XYFlowEventHandlers({
|
|
2260
|
+
children,
|
|
2261
|
+
eventHandlers
|
|
2262
|
+
}) {
|
|
2263
|
+
const originalsRef = react.useRef(eventHandlers);
|
|
2264
|
+
originalsRef.current = eventHandlers;
|
|
2265
|
+
const xyflowRef = useSyncedRef(useXYFlow());
|
|
2266
|
+
const dblclickTimeout = react.useRef();
|
|
2267
|
+
const [xyFlowEvents] = react.useState(() => ({
|
|
2268
|
+
onPanelClick: (event) => {
|
|
2269
|
+
var _a, _b;
|
|
2270
|
+
if (!originalsRef.current.onCanvasDblClick) {
|
|
2271
|
+
(_b = (_a = originalsRef.current).onCanvasClick) == null ? void 0 : _b.call(_a, event);
|
|
2272
|
+
return;
|
|
2273
|
+
}
|
|
2274
|
+
if (dblclickTimeout.current) {
|
|
2275
|
+
window.clearTimeout(dblclickTimeout.current);
|
|
2276
|
+
dblclickTimeout.current = void 0;
|
|
2277
|
+
originalsRef.current.onCanvasDblClick(event);
|
|
2278
|
+
return;
|
|
2279
|
+
}
|
|
2280
|
+
dblclickTimeout.current = window.setTimeout(() => {
|
|
2281
|
+
var _a2, _b2;
|
|
2282
|
+
dblclickTimeout.current = void 0;
|
|
2283
|
+
(_b2 = (_a2 = originalsRef.current).onCanvasClick) == null ? void 0 : _b2.call(_a2, event);
|
|
2284
|
+
}, 300);
|
|
2285
|
+
},
|
|
2286
|
+
onNodeContextMenu: (event, xynode) => {
|
|
2287
|
+
var _a, _b;
|
|
2288
|
+
(_b = (_a = originalsRef.current).onNodeContextMenu) == null ? void 0 : _b.call(_a, {
|
|
2289
|
+
element: xynode.data.element,
|
|
2290
|
+
xynode,
|
|
2291
|
+
event
|
|
2292
|
+
});
|
|
2293
|
+
},
|
|
2294
|
+
onPaneContextMenu: (event) => {
|
|
2295
|
+
var _a, _b;
|
|
2296
|
+
(_b = (_a = originalsRef.current).onCanvasContextMenu) == null ? void 0 : _b.call(_a, event);
|
|
2297
|
+
},
|
|
2298
|
+
onEdgeContextMenu: (event, xyedge) => {
|
|
2299
|
+
var _a, _b;
|
|
2300
|
+
(_b = (_a = originalsRef.current).onEdgeContextMenu) == null ? void 0 : _b.call(_a, {
|
|
2301
|
+
relation: xyedge.data.edge,
|
|
2302
|
+
xyedge,
|
|
2303
|
+
event
|
|
2304
|
+
});
|
|
2305
|
+
},
|
|
2306
|
+
onNodeClick: (event, xynode) => {
|
|
2307
|
+
var _a, _b;
|
|
2308
|
+
(_b = (_a = originalsRef.current).onNodeClick) == null ? void 0 : _b.call(_a, {
|
|
2309
|
+
element: xynode.data.element,
|
|
2310
|
+
xynode,
|
|
2311
|
+
event
|
|
2312
|
+
});
|
|
2313
|
+
},
|
|
2314
|
+
onEdgeClick: (event, xyedge) => {
|
|
2315
|
+
var _a, _b;
|
|
2316
|
+
(_b = (_a = originalsRef.current).onEdgeClick) == null ? void 0 : _b.call(_a, {
|
|
2317
|
+
relation: xyedge.data.edge,
|
|
2318
|
+
xyedge,
|
|
2319
|
+
event
|
|
2320
|
+
});
|
|
2321
|
+
},
|
|
2322
|
+
onNavigateTo: (xynodeId, event) => {
|
|
2323
|
+
if (!originalsRef.current.onNavigateTo) {
|
|
2324
|
+
return;
|
|
2325
|
+
}
|
|
2326
|
+
const xynode = xyflowRef.current.getNode(xynodeId);
|
|
2327
|
+
core$1.invariant(xynode, `node not found: ${xynodeId}`);
|
|
2328
|
+
const navigateTo = xynode.data.element.navigateTo;
|
|
2329
|
+
core$1.invariant(navigateTo, `node is not navigable: ${xynodeId}`);
|
|
2330
|
+
originalsRef.current.onNavigateTo({
|
|
2331
|
+
element: xynode.data.element,
|
|
2332
|
+
xynode,
|
|
2333
|
+
event
|
|
2334
|
+
});
|
|
2335
|
+
},
|
|
2336
|
+
onChange: (change2) => {
|
|
2337
|
+
var _a, _b;
|
|
2338
|
+
const changes = Array.isArray(change2) ? change2 : [change2];
|
|
2339
|
+
core$1.invariant(core$1.hasAtLeast(changes, 1), "no changes");
|
|
2340
|
+
(_b = (_a = originalsRef.current).onChange) == null ? void 0 : _b.call(_a, { changes });
|
|
2341
|
+
}
|
|
2342
|
+
}));
|
|
2343
|
+
return /* @__PURE__ */ jsxRuntime.jsx(EventHandlersContext.Provider, { value: xyFlowEvents, children });
|
|
2344
|
+
}
|
|
2345
|
+
const {
|
|
2346
|
+
primary,
|
|
2347
|
+
secondary,
|
|
2348
|
+
muted,
|
|
2349
|
+
...otherColors
|
|
2350
|
+
} = core$1.defaultTheme.elements;
|
|
2351
|
+
const themedColors = [
|
|
2352
|
+
{ key: "primary", value: primary.fill },
|
|
2353
|
+
{ key: "secondary", value: secondary.fill },
|
|
2354
|
+
{ key: "muted", value: muted.fill }
|
|
2355
|
+
];
|
|
2356
|
+
const colors = keys.strict(otherColors).map((key) => ({
|
|
2357
|
+
key,
|
|
2358
|
+
value: core$1.defaultTheme.elements[key].fill
|
|
2359
|
+
}));
|
|
2360
|
+
function NodeOptions({ selectedNodeIds }) {
|
|
2361
|
+
const { onChange } = useXYFlowEvents();
|
|
2362
|
+
const nodes = useXYNodesData(selectedNodeIds);
|
|
2363
|
+
const api = useXYFlow();
|
|
2364
|
+
if (!hasAtLeast(nodes, 1)) {
|
|
2365
|
+
return null;
|
|
2366
|
+
}
|
|
2367
|
+
const showShapeOption = nodes.some((node) => node.type === "element");
|
|
2368
|
+
const [firstNode, ...rest] = nodes;
|
|
2369
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(core.Stack, { children: [
|
|
2370
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Box, { maw: 200, children: /* @__PURE__ */ jsxRuntime.jsx(core.Text, { size: "xs", c: rest.length > 0 ? "dimmed" : "", truncate: true, children: rest.length === 0 ? firstNode.data.element.title : `[ multiple ]` }) }),
|
|
2371
|
+
showShapeOption && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2372
|
+
ShapeOption,
|
|
2373
|
+
{
|
|
2374
|
+
nodes,
|
|
2375
|
+
onShapeChange: (shape) => {
|
|
2376
|
+
const targets = [];
|
|
2377
|
+
for (const nd of nodes) {
|
|
2378
|
+
api.updateNodeData(nd.id, ({ data }) => {
|
|
2379
|
+
if (data.element.shape === shape) {
|
|
2380
|
+
return data;
|
|
2381
|
+
}
|
|
2382
|
+
return {
|
|
2383
|
+
...data,
|
|
2384
|
+
element: {
|
|
2385
|
+
...data.element,
|
|
2386
|
+
shape
|
|
2387
|
+
}
|
|
2388
|
+
};
|
|
2389
|
+
});
|
|
2390
|
+
targets.push(nd.data.element.id);
|
|
2391
|
+
}
|
|
2392
|
+
if (hasAtLeast(targets, 1)) {
|
|
2393
|
+
onChange({
|
|
2394
|
+
op: "change-shape",
|
|
2395
|
+
shape,
|
|
2396
|
+
targets
|
|
2397
|
+
});
|
|
2398
|
+
}
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
),
|
|
2402
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2403
|
+
Colors,
|
|
2404
|
+
{
|
|
2405
|
+
nodes,
|
|
2406
|
+
onColorChange: (color) => {
|
|
2407
|
+
const targets = [];
|
|
2408
|
+
for (const nd of nodes) {
|
|
2409
|
+
api.updateNodeData(nd.id, ({ data }) => {
|
|
2410
|
+
if (data.element.color === color) {
|
|
2411
|
+
return data;
|
|
2412
|
+
}
|
|
2413
|
+
return {
|
|
2414
|
+
...data,
|
|
2415
|
+
element: {
|
|
2416
|
+
...data.element,
|
|
2417
|
+
color
|
|
2418
|
+
}
|
|
2419
|
+
};
|
|
2420
|
+
});
|
|
2421
|
+
targets.push(nd.data.element.id);
|
|
2422
|
+
}
|
|
2423
|
+
if (hasAtLeast(targets, 1)) {
|
|
2424
|
+
onChange({
|
|
2425
|
+
op: "change-color",
|
|
2426
|
+
color,
|
|
2427
|
+
targets
|
|
2428
|
+
});
|
|
2429
|
+
}
|
|
2430
|
+
}
|
|
2431
|
+
}
|
|
2432
|
+
),
|
|
2433
|
+
/* @__PURE__ */ jsxRuntime.jsx(NavigateToOption, { nodes })
|
|
2434
|
+
] });
|
|
2435
|
+
}
|
|
2436
|
+
function Colors({
|
|
2437
|
+
nodes: [firstNode, ...nodes],
|
|
2438
|
+
onColorChange
|
|
2439
|
+
}) {
|
|
2440
|
+
let selectedColor = firstNode.data.element.color;
|
|
2441
|
+
takeWhile(nodes, (node) => {
|
|
2442
|
+
if (node.data.element.color !== selectedColor) {
|
|
2443
|
+
selectedColor = null;
|
|
2444
|
+
return false;
|
|
2445
|
+
}
|
|
2446
|
+
return true;
|
|
2447
|
+
});
|
|
2448
|
+
const changeColor = (color) => () => {
|
|
2449
|
+
if (selectedColor === color) {
|
|
2450
|
+
return;
|
|
2451
|
+
}
|
|
2452
|
+
onColorChange(color);
|
|
2453
|
+
};
|
|
2454
|
+
return /* @__PURE__ */ jsxRuntime.jsx(core.Box, { children: /* @__PURE__ */ jsxRuntime.jsxs(core.Tooltip.Group, { openDelay: 400, closeDelay: 300, children: [
|
|
2455
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Divider, { label: "color", labelPosition: "left" }),
|
|
2456
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Flex, { mt: "xs", maw: 150, gap: "xs", justify: "flex-start", align: "flex-start", direction: "row", wrap: "wrap", children: themedColors.map(({ key, value }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2457
|
+
core.Tooltip,
|
|
2458
|
+
{
|
|
2459
|
+
label: key,
|
|
2460
|
+
fz: "xs",
|
|
2461
|
+
color: "dark",
|
|
2462
|
+
offset: 2,
|
|
2463
|
+
transitionProps: { duration: 140, transition: "slide-up" },
|
|
2464
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2465
|
+
core.ColorSwatch,
|
|
2466
|
+
{
|
|
2467
|
+
color: value,
|
|
2468
|
+
size: 20,
|
|
2469
|
+
withShadow: true,
|
|
2470
|
+
onClick: changeColor(key),
|
|
2471
|
+
style: { color: "#fff", cursor: "pointer" },
|
|
2472
|
+
children: selectedColor === key && /* @__PURE__ */ jsxRuntime.jsx(core.CheckIcon, { style: { width: core.rem(12), height: core.rem(12) } })
|
|
2473
|
+
}
|
|
2474
|
+
)
|
|
2475
|
+
},
|
|
2476
|
+
key
|
|
2477
|
+
)) }),
|
|
2478
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Flex, { mt: "sm", maw: 150, gap: "xs", justify: "flex-start", align: "flex-start", direction: "row", wrap: "wrap", children: colors.map(({ key, value }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2479
|
+
core.Tooltip,
|
|
2480
|
+
{
|
|
2481
|
+
label: key,
|
|
2482
|
+
fz: "xs",
|
|
2483
|
+
color: "dark",
|
|
2484
|
+
offset: 2,
|
|
2485
|
+
transitionProps: { duration: 140, transition: "slide-up" },
|
|
2486
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2487
|
+
core.ColorSwatch,
|
|
2488
|
+
{
|
|
2489
|
+
color: value,
|
|
2490
|
+
size: 20,
|
|
2491
|
+
onClick: changeColor(key),
|
|
2492
|
+
style: { color: "#fff", cursor: "pointer" },
|
|
2493
|
+
children: selectedColor === key && /* @__PURE__ */ jsxRuntime.jsx(core.CheckIcon, { style: { width: core.rem(12), height: core.rem(12) } })
|
|
2494
|
+
}
|
|
2495
|
+
)
|
|
2496
|
+
},
|
|
2497
|
+
key
|
|
2498
|
+
)) })
|
|
2499
|
+
] }) });
|
|
2500
|
+
}
|
|
2501
|
+
function ShapeOption({
|
|
2502
|
+
nodes: [firstNode, ...nodes],
|
|
2503
|
+
onShapeChange
|
|
2504
|
+
}) {
|
|
2505
|
+
let selectedShape = firstNode.data.element.shape;
|
|
2506
|
+
takeWhile(nodes, (node) => {
|
|
2507
|
+
if (node.data.element.shape !== selectedShape) {
|
|
2508
|
+
selectedShape = null;
|
|
2509
|
+
return false;
|
|
2510
|
+
}
|
|
2511
|
+
return true;
|
|
2512
|
+
});
|
|
2513
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(core.Box, { children: [
|
|
2514
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Divider, { label: "shape", labelPosition: "left" }),
|
|
2515
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2516
|
+
core.Select,
|
|
2517
|
+
{
|
|
2518
|
+
mt: "xs",
|
|
2519
|
+
size: "xs",
|
|
2520
|
+
variant: "filled",
|
|
2521
|
+
value: selectedShape,
|
|
2522
|
+
placeholder: "[ multiple ]",
|
|
2523
|
+
data: core$1.ElementShapes,
|
|
2524
|
+
allowDeselect: false,
|
|
2525
|
+
checkIconPosition: "right",
|
|
2526
|
+
onChange: (value) => {
|
|
2527
|
+
if (!value || value === selectedShape) {
|
|
2528
|
+
return;
|
|
2529
|
+
}
|
|
2530
|
+
onShapeChange(value);
|
|
2531
|
+
}
|
|
2532
|
+
}
|
|
2533
|
+
)
|
|
2534
|
+
] });
|
|
2535
|
+
}
|
|
2536
|
+
function NavigateToOption({
|
|
2537
|
+
nodes: [node, ...nodes]
|
|
2538
|
+
}) {
|
|
2539
|
+
const isMultiple = nodes.length >= 1;
|
|
2540
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(core.Box, { children: [
|
|
2541
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Divider, { label: "navigate to", labelPosition: "left" }),
|
|
2542
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2543
|
+
core.Select,
|
|
2544
|
+
{
|
|
2545
|
+
mt: "xs",
|
|
2546
|
+
size: "xs",
|
|
2547
|
+
variant: "filled",
|
|
2548
|
+
value: !isMultiple ? node.data.element.navigateTo ?? null : null,
|
|
2549
|
+
disabled: isMultiple,
|
|
2550
|
+
placeholder: isMultiple ? "[ multiple ]" : "select",
|
|
2551
|
+
data: node.data.element.navigateTo ? [{ value: node.data.element.navigateTo, label: node.data.element.navigateTo }] : [],
|
|
2552
|
+
allowDeselect: true,
|
|
2553
|
+
checkIconPosition: "right"
|
|
2554
|
+
}
|
|
2555
|
+
)
|
|
2556
|
+
] });
|
|
2557
|
+
}
|
|
2558
|
+
var panel = "_1lmzt1h0";
|
|
2559
|
+
const OptionsPanelMemo = /* @__PURE__ */ react.memo(function OptionsPanel() {
|
|
2560
|
+
const [selectedNodes, setSelectedNodes] = react.useState([]);
|
|
2561
|
+
react$1.useOnSelectionChange({
|
|
2562
|
+
onChange: ({ nodes, edges }) => {
|
|
2563
|
+
const next = nodes.map((n) => n.id).sort();
|
|
2564
|
+
setSelectedNodes((prev) => {
|
|
2565
|
+
return shallowEqual(prev, next) ? prev : next;
|
|
2566
|
+
});
|
|
2567
|
+
}
|
|
2568
|
+
});
|
|
2569
|
+
return /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "wait", children: selectedNodes.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2570
|
+
framerMotion.motion.div,
|
|
2571
|
+
{
|
|
2572
|
+
initial: { opacity: 0, scale: 0.85 },
|
|
2573
|
+
animate: { opacity: 1, scale: 1 },
|
|
2574
|
+
exit: {
|
|
2575
|
+
opacity: 0,
|
|
2576
|
+
scale: 0.85
|
|
2577
|
+
},
|
|
2578
|
+
transition: { duration: 0.14 },
|
|
2579
|
+
className: clsx("react-flow__panel", panel),
|
|
2580
|
+
style: {
|
|
2581
|
+
transformOrigin: "center right"
|
|
2582
|
+
},
|
|
2583
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(core.Card, { shadow: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(NodeOptions, { selectedNodeIds: selectedNodes }) })
|
|
2584
|
+
}
|
|
2585
|
+
) });
|
|
2586
|
+
});
|
|
2587
|
+
const OptionsPanel2 = OptionsPanelMemo;
|
|
2588
|
+
function deriveEdgePoints(bezierSpline) {
|
|
2589
|
+
let [start, ...bezierPoints] = bezierSpline;
|
|
2590
|
+
core$1.invariant(start, "start should be defined");
|
|
2591
|
+
const handles = [
|
|
2592
|
+
// start
|
|
2593
|
+
];
|
|
2594
|
+
while (hasAtLeast(bezierPoints, 3)) {
|
|
2595
|
+
const [cp1, cp2, end, ...rest] = bezierPoints;
|
|
2596
|
+
const [centerX, centerY] = react$1.getBezierEdgeCenter({
|
|
2597
|
+
sourceX: start[0],
|
|
2598
|
+
sourceY: start[1],
|
|
2599
|
+
targetX: end[0],
|
|
2600
|
+
targetY: end[1],
|
|
2601
|
+
sourceControlX: cp1[0],
|
|
2602
|
+
sourceControlY: cp1[1],
|
|
2603
|
+
targetControlX: cp2[0],
|
|
2604
|
+
targetControlY: cp2[1]
|
|
2605
|
+
});
|
|
2606
|
+
handles.push(
|
|
2607
|
+
[centerX, centerY]
|
|
2608
|
+
);
|
|
2609
|
+
bezierPoints = rest;
|
|
2610
|
+
start = end;
|
|
2611
|
+
}
|
|
2612
|
+
core$1.invariant(bezierPoints.length === 0, "all points should be consumed");
|
|
2613
|
+
return handles;
|
|
2614
|
+
}
|
|
2615
|
+
function nodeZIndex(node) {
|
|
2616
|
+
return node.children.length > 0 ? 0 : node.level + 1;
|
|
2617
|
+
}
|
|
2618
|
+
function diagramViewToXYFlowData(view, dragEnabled = true) {
|
|
2619
|
+
const editor = {
|
|
2620
|
+
nodes: [],
|
|
2621
|
+
edges: []
|
|
2622
|
+
};
|
|
2623
|
+
const ns = "";
|
|
2624
|
+
const nodeById = (id) => core$1.nonNullable(view.nodes.find((n) => n.id === id));
|
|
2625
|
+
const createNode = (node) => {
|
|
2626
|
+
const isCompound = hasAtLeast(node.children, 1);
|
|
2627
|
+
const id = ns + node.id;
|
|
2628
|
+
const position = {
|
|
2629
|
+
x: node.position[0],
|
|
2630
|
+
y: node.position[1]
|
|
2631
|
+
};
|
|
2632
|
+
const parent = node.parent ? nodeById(node.parent) : null;
|
|
2633
|
+
if (parent) {
|
|
2634
|
+
position.x -= parent.position[0];
|
|
2635
|
+
position.y -= parent.position[1];
|
|
2636
|
+
}
|
|
2637
|
+
const zIndex = nodeZIndex(node);
|
|
2638
|
+
editor.nodes.push({
|
|
2639
|
+
id,
|
|
2640
|
+
type: isCompound ? "compound" : "element",
|
|
2641
|
+
data: {
|
|
2642
|
+
id,
|
|
2643
|
+
element: node
|
|
2644
|
+
},
|
|
2645
|
+
draggable: dragEnabled && (!parent || parent.children.length > 1),
|
|
2646
|
+
deletable: false,
|
|
2647
|
+
position,
|
|
2648
|
+
zIndex,
|
|
2649
|
+
width: node.width,
|
|
2650
|
+
height: node.height,
|
|
2651
|
+
// handles: [
|
|
2652
|
+
// ...outEdges.map(out => ({
|
|
2653
|
+
// id: `${out.id}`,
|
|
2654
|
+
// type: 'source' as const,
|
|
2655
|
+
// position: Position.Bottom,
|
|
2656
|
+
// x: out.points[0][0],
|
|
2657
|
+
// y: out.points[0][1],
|
|
2658
|
+
// width: 10,
|
|
2659
|
+
// height: 10
|
|
2660
|
+
// })),
|
|
2661
|
+
// ...inEdges.map(out => ({
|
|
2662
|
+
// id: out.id,
|
|
2663
|
+
// type: 'target' as const,
|
|
2664
|
+
// position: Position.Top,
|
|
2665
|
+
// x: out.points[0][0],
|
|
2666
|
+
// y: out.points[0][1],
|
|
2667
|
+
// width: 10,
|
|
2668
|
+
// height: 10
|
|
2669
|
+
// }))
|
|
2670
|
+
// ],
|
|
2671
|
+
...parent ? {
|
|
2672
|
+
parentNode: ns + parent.id
|
|
2673
|
+
} : {}
|
|
2674
|
+
});
|
|
2675
|
+
};
|
|
2676
|
+
for (const node of view.nodes.toSorted(core$1.compareByFqnHierarchically)) {
|
|
2677
|
+
createNode(node);
|
|
2678
|
+
}
|
|
2679
|
+
const createEdge = (edge) => {
|
|
2680
|
+
const source = edge.source;
|
|
2681
|
+
const target = edge.target;
|
|
2682
|
+
const id = ns + edge.id;
|
|
2683
|
+
const controlPoints = deriveEdgePoints(edge.points);
|
|
2684
|
+
core$1.invariant(hasAtLeast(edge.points, 2), "edge should have at least 2 points");
|
|
2685
|
+
const level = Math.min(nodeById(source).level, nodeById(target).level);
|
|
2686
|
+
editor.edges.push({
|
|
2687
|
+
id,
|
|
2688
|
+
type: "relationship",
|
|
2689
|
+
source: ns + source,
|
|
2690
|
+
target: ns + target,
|
|
2691
|
+
zIndex: level + 1,
|
|
2692
|
+
deletable: false,
|
|
2693
|
+
data: {
|
|
2694
|
+
edge,
|
|
2695
|
+
type: "bezier",
|
|
2696
|
+
controlPoints,
|
|
2697
|
+
headPoint: edge.headArrowPoint ?? null,
|
|
2698
|
+
tailPoint: edge.tailArrowPoint ?? null,
|
|
2699
|
+
label: edge.labelBBox && edge.label ? {
|
|
2700
|
+
bbox: edge.labelBBox,
|
|
2701
|
+
// text: edge.labels ? edge.labels.map(l => l.text).join('\n') : ''
|
|
2702
|
+
text: edge.label
|
|
2703
|
+
} : null
|
|
2704
|
+
},
|
|
2705
|
+
// markerEnd: {
|
|
2706
|
+
// type: MarkerType.ArrowClosed
|
|
2707
|
+
// },
|
|
2708
|
+
interactionWidth: 20
|
|
2709
|
+
});
|
|
2710
|
+
};
|
|
2711
|
+
for (const edge of view.edges) {
|
|
2712
|
+
createEdge(edge);
|
|
2713
|
+
}
|
|
2714
|
+
return editor;
|
|
2715
|
+
}
|
|
2716
|
+
const ZIndexes = {
|
|
2717
|
+
Compound: 1,
|
|
2718
|
+
Edge: 2,
|
|
2719
|
+
Element: 3
|
|
2720
|
+
};
|
|
2721
|
+
const MinZoom = 0.01;
|
|
2722
|
+
function FitViewOnDiagramChange() {
|
|
2723
|
+
const [state, updateState] = useDiagramStateTracked();
|
|
2724
|
+
const xyflow = useXYFlow();
|
|
2725
|
+
const nodeInitialized = react$1.useNodesInitialized({
|
|
2726
|
+
includeHiddenNodes: true
|
|
2727
|
+
});
|
|
2728
|
+
const isReady = nodeInitialized && xyflow.viewportInitialized;
|
|
2729
|
+
const viewLayout = state.viewId + "_" + state.viewLayout + "_" + state.fitViewPadding;
|
|
2730
|
+
const prevViewLayoutRef = react.useRef(viewLayout);
|
|
2731
|
+
useDebouncedEffect(
|
|
2732
|
+
() => {
|
|
2733
|
+
if (!isReady || prevViewLayoutRef.current === viewLayout) {
|
|
2734
|
+
return;
|
|
2735
|
+
}
|
|
2736
|
+
const zoom = xyflow.getZoom();
|
|
2737
|
+
xyflow.setCenter(state.viewWidth / 2, state.viewHeight / 2, {
|
|
2738
|
+
duration: 150,
|
|
2739
|
+
zoom
|
|
2740
|
+
});
|
|
2741
|
+
xyflow.fitView({
|
|
2742
|
+
duration: 350,
|
|
2743
|
+
padding: state.fitViewPadding,
|
|
2744
|
+
minZoom: MinZoom,
|
|
2745
|
+
maxZoom: Math.max(1, zoom)
|
|
2746
|
+
});
|
|
2747
|
+
updateState({ viewportMoved: false });
|
|
2748
|
+
prevViewLayoutRef.current = viewLayout;
|
|
2749
|
+
},
|
|
2750
|
+
[isReady, viewLayout],
|
|
2751
|
+
50
|
|
2752
|
+
);
|
|
2753
|
+
return null;
|
|
2754
|
+
}
|
|
2755
|
+
function UpdateOnDiagramChange({
|
|
2756
|
+
nodesDraggable,
|
|
2757
|
+
view: {
|
|
2758
|
+
nodes,
|
|
2759
|
+
edges
|
|
2760
|
+
}
|
|
2761
|
+
}) {
|
|
2762
|
+
const xyflow = useXYFlow();
|
|
2763
|
+
const initialized = xyflow.viewportInitialized;
|
|
2764
|
+
useUpdateEffect(
|
|
2765
|
+
() => {
|
|
2766
|
+
if (!initialized) {
|
|
2767
|
+
return;
|
|
2768
|
+
}
|
|
2769
|
+
const updates = diagramViewToXYFlowData({
|
|
2770
|
+
nodes,
|
|
2771
|
+
edges
|
|
2772
|
+
}, nodesDraggable);
|
|
2773
|
+
xyflow.setNodes(
|
|
2774
|
+
(prev) => updates.nodes.map((update) => {
|
|
2775
|
+
const existing = prev.find((p) => p.id === update.id);
|
|
2776
|
+
if (existing && existing.type == update.type) {
|
|
2777
|
+
const { data, parentNode, ...rest } = update;
|
|
2778
|
+
if (!deepEqual(existing.data, data)) {
|
|
2779
|
+
existing.data = data;
|
|
2780
|
+
}
|
|
2781
|
+
if (!isNullish(parentNode)) {
|
|
2782
|
+
existing.parentNode = parentNode;
|
|
2783
|
+
} else {
|
|
2784
|
+
delete existing.parentNode;
|
|
2785
|
+
}
|
|
2786
|
+
return Object.assign(existing, rest);
|
|
2787
|
+
}
|
|
2788
|
+
return update;
|
|
2789
|
+
})
|
|
2790
|
+
);
|
|
2791
|
+
xyflow.setEdges(
|
|
2792
|
+
(prev) => updates.edges.map((update) => {
|
|
2793
|
+
const existing = prev.find((e) => e.id === update.id);
|
|
2794
|
+
if (existing) {
|
|
2795
|
+
if (deepEqual(existing.data.edge, update.data.edge)) {
|
|
2796
|
+
return existing;
|
|
2797
|
+
}
|
|
2798
|
+
return {
|
|
2799
|
+
...existing,
|
|
2800
|
+
...update
|
|
2801
|
+
};
|
|
2802
|
+
}
|
|
2803
|
+
return update;
|
|
2804
|
+
})
|
|
2805
|
+
);
|
|
2806
|
+
},
|
|
2807
|
+
[initialized, nodesDraggable, nodes, edges]
|
|
2808
|
+
);
|
|
2809
|
+
return null;
|
|
2810
|
+
}
|
|
2811
|
+
function literalToEnum(value) {
|
|
2812
|
+
switch (value) {
|
|
2813
|
+
case "dots":
|
|
2814
|
+
return react$1.BackgroundVariant.Dots;
|
|
2815
|
+
case "lines":
|
|
2816
|
+
return react$1.BackgroundVariant.Lines;
|
|
2817
|
+
case "cross":
|
|
2818
|
+
return react$1.BackgroundVariant.Cross;
|
|
2819
|
+
default:
|
|
2820
|
+
core$1.nonexhaustive(value);
|
|
2821
|
+
}
|
|
2822
|
+
}
|
|
2823
|
+
const XYFlowBackground = react.memo(({ background }) => {
|
|
2824
|
+
if (typeof background === "string") {
|
|
2825
|
+
return /* @__PURE__ */ jsxRuntime.jsx(react$1.Background, { variant: literalToEnum(background) });
|
|
2826
|
+
}
|
|
2827
|
+
const { variant, ...rest } = background;
|
|
2828
|
+
return /* @__PURE__ */ jsxRuntime.jsx(react$1.Background, { variant: literalToEnum(variant), ...rest });
|
|
2829
|
+
}, deepEqual);
|
|
2830
|
+
var container$1 = "bexn7q0";
|
|
2831
|
+
var edgePathBg = "bexn7q1";
|
|
2832
|
+
var fillStrokeCtx = "bexn7q2";
|
|
2833
|
+
var cssEdgePath = "bexn7q3";
|
|
2834
|
+
var edgeLabel = "bexn7q4";
|
|
2835
|
+
var edgeLabelBody = "bexn7q5";
|
|
2836
|
+
function getNodeIntersection(intersectionNode, targetNode) {
|
|
2837
|
+
var _a, _b, _c, _d, _e, _f;
|
|
2838
|
+
const intersectionNodeWidth = ((_a = intersectionNode.computed) == null ? void 0 : _a.width) ?? intersectionNode.data.element.width;
|
|
2839
|
+
const intersectionNodeHeight = ((_b = intersectionNode.computed) == null ? void 0 : _b.height) ?? intersectionNode.data.element.height;
|
|
2840
|
+
const intersectionNodePosition = ((_c = intersectionNode.computed) == null ? void 0 : _c.positionAbsolute) ?? { x: intersectionNode.data.element.position[0], y: intersectionNode.data.element.position[1] };
|
|
2841
|
+
const targetPosition = ((_d = targetNode.computed) == null ? void 0 : _d.positionAbsolute) ?? { x: targetNode.data.element.position[0], y: targetNode.data.element.position[1] };
|
|
2842
|
+
const w = intersectionNodeWidth / 2;
|
|
2843
|
+
const h = intersectionNodeHeight / 2;
|
|
2844
|
+
const x2 = intersectionNodePosition.x + w;
|
|
2845
|
+
const y2 = intersectionNodePosition.y + h;
|
|
2846
|
+
const x1 = targetPosition.x + (((_e = targetNode.computed) == null ? void 0 : _e.width) ?? targetNode.data.element.width) / 2;
|
|
2847
|
+
const y1 = targetPosition.y + (((_f = targetNode.computed) == null ? void 0 : _f.height) ?? targetNode.data.element.height) / 2;
|
|
2848
|
+
const xx1 = (x1 - x2) / (2 * w) - (y1 - y2) / (2 * h);
|
|
2849
|
+
const yy1 = (x1 - x2) / (2 * w) + (y1 - y2) / (2 * h);
|
|
2850
|
+
const a = 1 / (Math.abs(xx1) + Math.abs(yy1));
|
|
2851
|
+
const xx3 = a * xx1;
|
|
2852
|
+
const yy3 = a * yy1;
|
|
2853
|
+
const x = w * (xx3 + yy3) + x2;
|
|
2854
|
+
const y = h * (-xx3 + yy3) + y2;
|
|
2855
|
+
return { x, y };
|
|
2856
|
+
}
|
|
2857
|
+
function getPointPosition(node, intersectionPoint) {
|
|
2858
|
+
var _a, _b, _c;
|
|
2859
|
+
const n = {
|
|
2860
|
+
x: node.data.element.position[0],
|
|
2861
|
+
y: node.data.element.position[1],
|
|
2862
|
+
...(_a = node.computed) == null ? void 0 : _a.positionAbsolute,
|
|
2863
|
+
width: ((_b = node.computed) == null ? void 0 : _b.width) ?? node.data.element.width,
|
|
2864
|
+
height: ((_c = node.computed) == null ? void 0 : _c.height) ?? node.data.element.height
|
|
2865
|
+
};
|
|
2866
|
+
const nx = Math.round(n.x);
|
|
2867
|
+
const ny = Math.round(n.y);
|
|
2868
|
+
const px = Math.round(intersectionPoint.x);
|
|
2869
|
+
const py = Math.round(intersectionPoint.y);
|
|
2870
|
+
let handlePosition = react$1.Position.Top;
|
|
2871
|
+
if (px <= nx + 1) {
|
|
2872
|
+
handlePosition = react$1.Position.Left;
|
|
2873
|
+
} else if (px >= nx + n.width - 1) {
|
|
2874
|
+
handlePosition = react$1.Position.Right;
|
|
2875
|
+
} else if (py <= ny + 1) {
|
|
2876
|
+
handlePosition = react$1.Position.Top;
|
|
2877
|
+
} else if (py >= n.y + n.height - 1) {
|
|
2878
|
+
handlePosition = react$1.Position.Bottom;
|
|
2879
|
+
}
|
|
2880
|
+
let handleWidth = 8, handleHeight = 8;
|
|
2881
|
+
let offsetX = 0;
|
|
2882
|
+
let offsetY = 0;
|
|
2883
|
+
switch (handlePosition) {
|
|
2884
|
+
case react$1.Position.Left:
|
|
2885
|
+
offsetX = -handleWidth;
|
|
2886
|
+
break;
|
|
2887
|
+
case react$1.Position.Right:
|
|
2888
|
+
offsetX = handleWidth;
|
|
2889
|
+
break;
|
|
2890
|
+
case react$1.Position.Top:
|
|
2891
|
+
offsetY = -handleHeight;
|
|
2892
|
+
break;
|
|
2893
|
+
case react$1.Position.Bottom:
|
|
2894
|
+
offsetY = handleHeight;
|
|
2895
|
+
break;
|
|
2896
|
+
}
|
|
2897
|
+
return [
|
|
2898
|
+
intersectionPoint.x + offsetX,
|
|
2899
|
+
intersectionPoint.y + offsetY,
|
|
2900
|
+
handlePosition
|
|
2901
|
+
];
|
|
2902
|
+
}
|
|
2903
|
+
function getEdgeParams(source, target) {
|
|
2904
|
+
const sourceIntersectionPoint = getNodeIntersection(source, target);
|
|
2905
|
+
const targetIntersectionPoint = getNodeIntersection(target, source);
|
|
2906
|
+
const [sx, sy, sourcePos] = getPointPosition(source, sourceIntersectionPoint);
|
|
2907
|
+
const [tx, ty, targetPos] = getPointPosition(target, targetIntersectionPoint);
|
|
2908
|
+
return {
|
|
2909
|
+
sx,
|
|
2910
|
+
sy,
|
|
2911
|
+
tx,
|
|
2912
|
+
ty,
|
|
2913
|
+
sourcePos,
|
|
2914
|
+
targetPos
|
|
2915
|
+
};
|
|
2916
|
+
}
|
|
2917
|
+
function bezierPath(bezierSpline) {
|
|
2918
|
+
let [start, ...points] = bezierSpline;
|
|
2919
|
+
core$1.invariant(start, "start should be defined");
|
|
2920
|
+
let path = `M ${start[0]},${start[1]}`;
|
|
2921
|
+
while (hasAtLeast(points, 3)) {
|
|
2922
|
+
const [cp1, cp2, end, ...rest] = points;
|
|
2923
|
+
path = path + ` C ${cp1[0]},${cp1[1]} ${cp2[0]},${cp2[1]} ${end[0]},${end[1]}`;
|
|
2924
|
+
points = rest;
|
|
2925
|
+
}
|
|
2926
|
+
core$1.invariant(points.length === 0, "all points should be consumed");
|
|
2927
|
+
return path;
|
|
2928
|
+
}
|
|
2929
|
+
const isEqualProps$2 = (prev, next) => prev.id === next.id && prev.source === next.source && prev.target === next.target && prev.sourceX === next.sourceX && prev.sourceY === next.sourceY && prev.targetX === next.targetX && prev.targetY === next.targetY && deepEqual(prev.data, next.data);
|
|
2930
|
+
const RelationshipEdge = /* @__PURE__ */ react.memo(function RelationshipEdgeR({
|
|
2931
|
+
id,
|
|
2932
|
+
data,
|
|
2933
|
+
selected,
|
|
2934
|
+
markerEnd,
|
|
2935
|
+
style,
|
|
2936
|
+
source,
|
|
2937
|
+
target,
|
|
2938
|
+
interactionWidth
|
|
2939
|
+
}) {
|
|
2940
|
+
var _a, _b;
|
|
2941
|
+
const xyflow = useXYFlow();
|
|
2942
|
+
const isModified = react$1.useStore(
|
|
2943
|
+
react.useCallback((s) => {
|
|
2944
|
+
var _a2, _b2;
|
|
2945
|
+
const sourceNode = s.nodeLookup.get(source);
|
|
2946
|
+
const targetNode = s.nodeLookup.get(target);
|
|
2947
|
+
core$1.invariant(XYFlowNode.is(sourceNode));
|
|
2948
|
+
core$1.invariant(XYFlowNode.is(targetNode));
|
|
2949
|
+
const isSourceModified = !!((_a2 = sourceNode.computed) == null ? void 0 : _a2.positionAbsolute) && !shallowEqual(sourceNode.computed.positionAbsolute, {
|
|
2950
|
+
x: sourceNode.data.element.position[0],
|
|
2951
|
+
y: sourceNode.data.element.position[1]
|
|
2952
|
+
});
|
|
2953
|
+
if (isSourceModified) {
|
|
2954
|
+
return true;
|
|
2955
|
+
}
|
|
2956
|
+
return !!((_b2 = targetNode.computed) == null ? void 0 : _b2.positionAbsolute) && !shallowEqual(targetNode.computed.positionAbsolute, {
|
|
2957
|
+
x: targetNode.data.element.position[0],
|
|
2958
|
+
y: targetNode.data.element.position[1]
|
|
2959
|
+
});
|
|
2960
|
+
}, [source, target]),
|
|
2961
|
+
deepEqual
|
|
2962
|
+
);
|
|
2963
|
+
core$1.invariant(data, "data isd required");
|
|
2964
|
+
const {
|
|
2965
|
+
edge,
|
|
2966
|
+
controlPoints
|
|
2967
|
+
} = data;
|
|
2968
|
+
const color = edge.color ?? "gray";
|
|
2969
|
+
const isHovered = useDiagramStateSelector((state) => state.hoveredEdgeId === id);
|
|
2970
|
+
const line = edge.line ?? "dashed";
|
|
2971
|
+
const isDotted = line === "dotted";
|
|
2972
|
+
const isDashed = isDotted || line === "dashed";
|
|
2973
|
+
let strokeDasharray;
|
|
2974
|
+
if (isDotted) {
|
|
2975
|
+
strokeDasharray = "1,8";
|
|
2976
|
+
} else if (isDashed) {
|
|
2977
|
+
strokeDasharray = "8,10";
|
|
2978
|
+
}
|
|
2979
|
+
const marker = `url(#arrow-${id})`;
|
|
2980
|
+
let edgePath, labelX, labelY;
|
|
2981
|
+
if (isModified) {
|
|
2982
|
+
const sourceNode = xyflow.getNode(source);
|
|
2983
|
+
const targetNode = xyflow.getNode(target);
|
|
2984
|
+
const { sx, sy, tx, ty, sourcePos, targetPos } = getEdgeParams(sourceNode, targetNode);
|
|
2985
|
+
const [_edgePath, _labelX, _labelY] = react$1.getBezierPath({
|
|
2986
|
+
sourceX: sx,
|
|
2987
|
+
sourceY: sy,
|
|
2988
|
+
sourcePosition: sourcePos,
|
|
2989
|
+
targetPosition: targetPos,
|
|
2990
|
+
targetX: tx,
|
|
2991
|
+
targetY: ty
|
|
2992
|
+
});
|
|
2993
|
+
edgePath = _edgePath;
|
|
2994
|
+
labelX = _labelX;
|
|
2995
|
+
labelY = _labelY;
|
|
2996
|
+
} else {
|
|
2997
|
+
edgePath = bezierPath(edge.points);
|
|
2998
|
+
labelX = ((_a = data.label) == null ? void 0 : _a.bbox.x) ?? 0;
|
|
2999
|
+
labelY = ((_b = data.label) == null ? void 0 : _b.bbox.y) ?? 0;
|
|
3000
|
+
}
|
|
3001
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("g", { className: clsx(container$1), "data-likec4-color": color, "data-edge-hovered": isHovered, children: [
|
|
3002
|
+
/* @__PURE__ */ jsxRuntime.jsx("g", { className: clsx(fillStrokeCtx), children: /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3003
|
+
"marker",
|
|
3004
|
+
{
|
|
3005
|
+
id: `arrow-${id}`,
|
|
3006
|
+
viewBox: "0 0 10 8",
|
|
3007
|
+
refX: "0",
|
|
3008
|
+
refY: "4",
|
|
3009
|
+
markerWidth: "5",
|
|
3010
|
+
markerHeight: "5",
|
|
3011
|
+
markerUnits: "strokeWidth",
|
|
3012
|
+
preserveAspectRatio: "xMaxYMid meet",
|
|
3013
|
+
orient: "auto-start-reverse",
|
|
3014
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M 0 0 L 10 4 L 0 8 z", stroke: "context-stroke", fill: "context-fill" })
|
|
3015
|
+
}
|
|
3016
|
+
) }) }),
|
|
3017
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3018
|
+
"path",
|
|
3019
|
+
{
|
|
3020
|
+
className: clsx("react-flow__edge-path", edgePathBg),
|
|
3021
|
+
d: edgePath,
|
|
3022
|
+
style,
|
|
3023
|
+
strokeLinecap: "round"
|
|
3024
|
+
}
|
|
3025
|
+
),
|
|
3026
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3027
|
+
"path",
|
|
3028
|
+
{
|
|
3029
|
+
className: clsx("react-flow__edge-path", cssEdgePath),
|
|
3030
|
+
d: edgePath,
|
|
3031
|
+
style,
|
|
3032
|
+
strokeLinecap: "round",
|
|
3033
|
+
// strokeLinecap={isDotted ? 'butt' : 'round'}
|
|
3034
|
+
// strokeMiterlimit={10}
|
|
3035
|
+
// strokeLinejoin="bevel"
|
|
3036
|
+
...strokeDasharray ? { strokeDasharray } : {},
|
|
3037
|
+
...edge.headArrow ? { markerEnd: marker } : {},
|
|
3038
|
+
...edge.tailArrow ? { markerStart: marker } : {}
|
|
3039
|
+
}
|
|
3040
|
+
),
|
|
3041
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3042
|
+
"path",
|
|
3043
|
+
{
|
|
3044
|
+
className: clsx("react-flow__edge-interaction"),
|
|
3045
|
+
d: edgePath,
|
|
3046
|
+
fill: "none",
|
|
3047
|
+
strokeOpacity: 0,
|
|
3048
|
+
strokeWidth: interactionWidth ?? 10
|
|
3049
|
+
}
|
|
3050
|
+
),
|
|
3051
|
+
data.label && /* @__PURE__ */ jsxRuntime.jsx(react$1.EdgeLabelRenderer, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3052
|
+
core.Box,
|
|
3053
|
+
{
|
|
3054
|
+
className: clsx(container$1, edgeLabel),
|
|
3055
|
+
"data-likec4-color": color,
|
|
3056
|
+
style: {
|
|
3057
|
+
top: labelY,
|
|
3058
|
+
left: labelX,
|
|
3059
|
+
maxWidth: data.label.bbox.width + 10,
|
|
3060
|
+
zIndex: ZIndexes.Edge
|
|
3061
|
+
},
|
|
3062
|
+
mod: {
|
|
3063
|
+
"data-edge-hovered": isHovered
|
|
3064
|
+
},
|
|
3065
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(core.Box, { className: edgeLabelBody, children: data.label.text })
|
|
3066
|
+
}
|
|
3067
|
+
) })
|
|
3068
|
+
] });
|
|
3069
|
+
}, isEqualProps$2);
|
|
3070
|
+
function getVarName(variable) {
|
|
3071
|
+
var matches = variable.match(/^var\((.*)\)$/);
|
|
3072
|
+
if (matches) {
|
|
3073
|
+
return matches[1];
|
|
3074
|
+
}
|
|
3075
|
+
return variable;
|
|
3076
|
+
}
|
|
3077
|
+
function get(obj, path) {
|
|
3078
|
+
var result = obj;
|
|
3079
|
+
for (var key of path) {
|
|
3080
|
+
if (!(key in result)) {
|
|
3081
|
+
throw new Error("Path ".concat(path.join(" -> "), " does not exist in object"));
|
|
3082
|
+
}
|
|
3083
|
+
result = result[key];
|
|
3084
|
+
}
|
|
3085
|
+
return result;
|
|
3086
|
+
}
|
|
3087
|
+
function walkObject(obj, fn) {
|
|
3088
|
+
var path = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : [];
|
|
3089
|
+
var clone = {};
|
|
3090
|
+
for (var key in obj) {
|
|
3091
|
+
var _value = obj[key];
|
|
3092
|
+
var currentPath = [...path, key];
|
|
3093
|
+
if (typeof _value === "string" || typeof _value === "number" || _value == null) {
|
|
3094
|
+
clone[key] = fn(_value, currentPath);
|
|
3095
|
+
} else if (typeof _value === "object" && !Array.isArray(_value)) {
|
|
3096
|
+
clone[key] = walkObject(_value, fn, currentPath);
|
|
3097
|
+
} else {
|
|
3098
|
+
console.warn('Skipping invalid key "'.concat(currentPath.join("."), '". Should be a string, number, null or object. Received: "').concat(Array.isArray(_value) ? "Array" : typeof _value, '"'));
|
|
3099
|
+
}
|
|
3100
|
+
}
|
|
3101
|
+
return clone;
|
|
3102
|
+
}
|
|
3103
|
+
function assignInlineVars(varsOrContract, tokens) {
|
|
3104
|
+
var styles = {};
|
|
3105
|
+
if (typeof tokens === "object") {
|
|
3106
|
+
var _contract = varsOrContract;
|
|
3107
|
+
walkObject(tokens, (value2, path) => {
|
|
3108
|
+
if (value2 == null) {
|
|
3109
|
+
return;
|
|
3110
|
+
}
|
|
3111
|
+
var varName2 = get(_contract, path);
|
|
3112
|
+
styles[getVarName(varName2)] = String(value2);
|
|
3113
|
+
});
|
|
3114
|
+
} else {
|
|
3115
|
+
var _vars = varsOrContract;
|
|
3116
|
+
for (var varName in _vars) {
|
|
3117
|
+
var value = _vars[varName];
|
|
3118
|
+
if (value == null) {
|
|
3119
|
+
continue;
|
|
3120
|
+
}
|
|
3121
|
+
styles[getVarName(varName)] = value;
|
|
3122
|
+
}
|
|
3123
|
+
}
|
|
3124
|
+
Object.defineProperty(styles, "toString", {
|
|
3125
|
+
value: function value2() {
|
|
3126
|
+
return Object.keys(this).map((key) => "".concat(key, ":").concat(this[key])).join(";");
|
|
3127
|
+
},
|
|
3128
|
+
writable: false
|
|
3129
|
+
});
|
|
3130
|
+
return styles;
|
|
3131
|
+
}
|
|
3132
|
+
const Channel = {
|
|
3133
|
+
/* CLAMP */
|
|
3134
|
+
min: {
|
|
3135
|
+
r: 0,
|
|
3136
|
+
g: 0,
|
|
3137
|
+
b: 0,
|
|
3138
|
+
s: 0,
|
|
3139
|
+
l: 0,
|
|
3140
|
+
a: 0
|
|
3141
|
+
},
|
|
3142
|
+
max: {
|
|
3143
|
+
r: 255,
|
|
3144
|
+
g: 255,
|
|
3145
|
+
b: 255,
|
|
3146
|
+
h: 360,
|
|
3147
|
+
s: 100,
|
|
3148
|
+
l: 100,
|
|
3149
|
+
a: 1
|
|
3150
|
+
},
|
|
3151
|
+
clamp: {
|
|
3152
|
+
r: (r) => r >= 255 ? 255 : r < 0 ? 0 : r,
|
|
3153
|
+
g: (g) => g >= 255 ? 255 : g < 0 ? 0 : g,
|
|
3154
|
+
b: (b) => b >= 255 ? 255 : b < 0 ? 0 : b,
|
|
3155
|
+
h: (h) => h % 360,
|
|
3156
|
+
s: (s) => s >= 100 ? 100 : s < 0 ? 0 : s,
|
|
3157
|
+
l: (l) => l >= 100 ? 100 : l < 0 ? 0 : l,
|
|
3158
|
+
a: (a) => a >= 1 ? 1 : a < 0 ? 0 : a
|
|
3159
|
+
},
|
|
3160
|
+
/* CONVERSION */
|
|
3161
|
+
//SOURCE: https://planetcalc.com/7779
|
|
3162
|
+
toLinear: (c) => {
|
|
3163
|
+
const n = c / 255;
|
|
3164
|
+
return c > 0.03928 ? Math.pow((n + 0.055) / 1.055, 2.4) : n / 12.92;
|
|
3165
|
+
},
|
|
3166
|
+
//SOURCE: https://gist.github.com/mjackson/5311256
|
|
3167
|
+
hue2rgb: (p, q, t) => {
|
|
3168
|
+
if (t < 0)
|
|
3169
|
+
t += 1;
|
|
3170
|
+
if (t > 1)
|
|
3171
|
+
t -= 1;
|
|
3172
|
+
if (t < 1 / 6)
|
|
3173
|
+
return p + (q - p) * 6 * t;
|
|
3174
|
+
if (t < 1 / 2)
|
|
3175
|
+
return q;
|
|
3176
|
+
if (t < 2 / 3)
|
|
3177
|
+
return p + (q - p) * (2 / 3 - t) * 6;
|
|
3178
|
+
return p;
|
|
3179
|
+
},
|
|
3180
|
+
hsl2rgb: ({ h, s, l }, channel) => {
|
|
3181
|
+
if (!s)
|
|
3182
|
+
return l * 2.55;
|
|
3183
|
+
h /= 360;
|
|
3184
|
+
s /= 100;
|
|
3185
|
+
l /= 100;
|
|
3186
|
+
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
3187
|
+
const p = 2 * l - q;
|
|
3188
|
+
switch (channel) {
|
|
3189
|
+
case "r":
|
|
3190
|
+
return Channel.hue2rgb(p, q, h + 1 / 3) * 255;
|
|
3191
|
+
case "g":
|
|
3192
|
+
return Channel.hue2rgb(p, q, h) * 255;
|
|
3193
|
+
case "b":
|
|
3194
|
+
return Channel.hue2rgb(p, q, h - 1 / 3) * 255;
|
|
3195
|
+
}
|
|
3196
|
+
},
|
|
3197
|
+
rgb2hsl: ({ r, g, b }, channel) => {
|
|
3198
|
+
r /= 255;
|
|
3199
|
+
g /= 255;
|
|
3200
|
+
b /= 255;
|
|
3201
|
+
const max = Math.max(r, g, b);
|
|
3202
|
+
const min = Math.min(r, g, b);
|
|
3203
|
+
const l = (max + min) / 2;
|
|
3204
|
+
if (channel === "l")
|
|
3205
|
+
return l * 100;
|
|
3206
|
+
if (max === min)
|
|
3207
|
+
return 0;
|
|
3208
|
+
const d = max - min;
|
|
3209
|
+
const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
3210
|
+
if (channel === "s")
|
|
3211
|
+
return s * 100;
|
|
3212
|
+
switch (max) {
|
|
3213
|
+
case r:
|
|
3214
|
+
return ((g - b) / d + (g < b ? 6 : 0)) * 60;
|
|
3215
|
+
case g:
|
|
3216
|
+
return ((b - r) / d + 2) * 60;
|
|
3217
|
+
case b:
|
|
3218
|
+
return ((r - g) / d + 4) * 60;
|
|
3219
|
+
default:
|
|
3220
|
+
return -1;
|
|
3221
|
+
}
|
|
3222
|
+
}
|
|
3223
|
+
};
|
|
3224
|
+
const Lang = {
|
|
3225
|
+
/* API */
|
|
3226
|
+
clamp: (number, lower, upper) => {
|
|
3227
|
+
if (lower > upper)
|
|
3228
|
+
return Math.min(lower, Math.max(upper, number));
|
|
3229
|
+
return Math.min(upper, Math.max(lower, number));
|
|
3230
|
+
},
|
|
3231
|
+
round: (number) => {
|
|
3232
|
+
return Math.round(number * 1e10) / 1e10;
|
|
3233
|
+
}
|
|
3234
|
+
};
|
|
3235
|
+
const lang = Lang;
|
|
3236
|
+
const Unit = {
|
|
3237
|
+
/* API */
|
|
3238
|
+
dec2hex: (dec) => {
|
|
3239
|
+
const hex = Math.round(dec).toString(16);
|
|
3240
|
+
return hex.length > 1 ? hex : `0${hex}`;
|
|
3241
|
+
}
|
|
3242
|
+
};
|
|
3243
|
+
const unit = Unit;
|
|
3244
|
+
const Utils = {
|
|
3245
|
+
channel: Channel,
|
|
3246
|
+
lang,
|
|
3247
|
+
unit
|
|
3248
|
+
};
|
|
3249
|
+
const DEC2HEX = {};
|
|
3250
|
+
for (let i = 0; i <= 255; i++)
|
|
3251
|
+
DEC2HEX[i] = Utils.unit.dec2hex(i);
|
|
3252
|
+
const TYPE = {
|
|
3253
|
+
ALL: 0,
|
|
3254
|
+
RGB: 1,
|
|
3255
|
+
HSL: 2
|
|
3256
|
+
};
|
|
3257
|
+
class Type {
|
|
3258
|
+
constructor() {
|
|
3259
|
+
this.type = TYPE.ALL;
|
|
3260
|
+
}
|
|
3261
|
+
/* API */
|
|
3262
|
+
get() {
|
|
3263
|
+
return this.type;
|
|
3264
|
+
}
|
|
3265
|
+
set(type) {
|
|
3266
|
+
if (this.type && this.type !== type)
|
|
3267
|
+
throw new Error("Cannot change both RGB and HSL channels at the same time");
|
|
3268
|
+
this.type = type;
|
|
3269
|
+
}
|
|
3270
|
+
reset() {
|
|
3271
|
+
this.type = TYPE.ALL;
|
|
3272
|
+
}
|
|
3273
|
+
is(type) {
|
|
3274
|
+
return this.type === type;
|
|
3275
|
+
}
|
|
3276
|
+
}
|
|
3277
|
+
class Channels {
|
|
3278
|
+
/* CONSTRUCTOR */
|
|
3279
|
+
constructor(data, color) {
|
|
3280
|
+
this.color = color;
|
|
3281
|
+
this.changed = false;
|
|
3282
|
+
this.data = data;
|
|
3283
|
+
this.type = new Type();
|
|
3284
|
+
}
|
|
3285
|
+
/* API */
|
|
3286
|
+
set(data, color) {
|
|
3287
|
+
this.color = color;
|
|
3288
|
+
this.changed = false;
|
|
3289
|
+
this.data = data;
|
|
3290
|
+
this.type.type = TYPE.ALL;
|
|
3291
|
+
return this;
|
|
3292
|
+
}
|
|
3293
|
+
/* HELPERS */
|
|
3294
|
+
_ensureHSL() {
|
|
3295
|
+
const data = this.data;
|
|
3296
|
+
const { h, s, l } = data;
|
|
3297
|
+
if (h === void 0)
|
|
3298
|
+
data.h = Utils.channel.rgb2hsl(data, "h");
|
|
3299
|
+
if (s === void 0)
|
|
3300
|
+
data.s = Utils.channel.rgb2hsl(data, "s");
|
|
3301
|
+
if (l === void 0)
|
|
3302
|
+
data.l = Utils.channel.rgb2hsl(data, "l");
|
|
3303
|
+
}
|
|
3304
|
+
_ensureRGB() {
|
|
3305
|
+
const data = this.data;
|
|
3306
|
+
const { r, g, b } = data;
|
|
3307
|
+
if (r === void 0)
|
|
3308
|
+
data.r = Utils.channel.hsl2rgb(data, "r");
|
|
3309
|
+
if (g === void 0)
|
|
3310
|
+
data.g = Utils.channel.hsl2rgb(data, "g");
|
|
3311
|
+
if (b === void 0)
|
|
3312
|
+
data.b = Utils.channel.hsl2rgb(data, "b");
|
|
3313
|
+
}
|
|
3314
|
+
/* GETTERS */
|
|
3315
|
+
get r() {
|
|
3316
|
+
const data = this.data;
|
|
3317
|
+
const r = data.r;
|
|
3318
|
+
if (!this.type.is(TYPE.HSL) && r !== void 0)
|
|
3319
|
+
return r;
|
|
3320
|
+
this._ensureHSL();
|
|
3321
|
+
return Utils.channel.hsl2rgb(data, "r");
|
|
3322
|
+
}
|
|
3323
|
+
get g() {
|
|
3324
|
+
const data = this.data;
|
|
3325
|
+
const g = data.g;
|
|
3326
|
+
if (!this.type.is(TYPE.HSL) && g !== void 0)
|
|
3327
|
+
return g;
|
|
3328
|
+
this._ensureHSL();
|
|
3329
|
+
return Utils.channel.hsl2rgb(data, "g");
|
|
3330
|
+
}
|
|
3331
|
+
get b() {
|
|
3332
|
+
const data = this.data;
|
|
3333
|
+
const b = data.b;
|
|
3334
|
+
if (!this.type.is(TYPE.HSL) && b !== void 0)
|
|
3335
|
+
return b;
|
|
3336
|
+
this._ensureHSL();
|
|
3337
|
+
return Utils.channel.hsl2rgb(data, "b");
|
|
3338
|
+
}
|
|
3339
|
+
get h() {
|
|
3340
|
+
const data = this.data;
|
|
3341
|
+
const h = data.h;
|
|
3342
|
+
if (!this.type.is(TYPE.RGB) && h !== void 0)
|
|
3343
|
+
return h;
|
|
3344
|
+
this._ensureRGB();
|
|
3345
|
+
return Utils.channel.rgb2hsl(data, "h");
|
|
3346
|
+
}
|
|
3347
|
+
get s() {
|
|
3348
|
+
const data = this.data;
|
|
3349
|
+
const s = data.s;
|
|
3350
|
+
if (!this.type.is(TYPE.RGB) && s !== void 0)
|
|
3351
|
+
return s;
|
|
3352
|
+
this._ensureRGB();
|
|
3353
|
+
return Utils.channel.rgb2hsl(data, "s");
|
|
3354
|
+
}
|
|
3355
|
+
get l() {
|
|
3356
|
+
const data = this.data;
|
|
3357
|
+
const l = data.l;
|
|
3358
|
+
if (!this.type.is(TYPE.RGB) && l !== void 0)
|
|
3359
|
+
return l;
|
|
3360
|
+
this._ensureRGB();
|
|
3361
|
+
return Utils.channel.rgb2hsl(data, "l");
|
|
3362
|
+
}
|
|
3363
|
+
get a() {
|
|
3364
|
+
return this.data.a;
|
|
3365
|
+
}
|
|
3366
|
+
/* SETTERS */
|
|
3367
|
+
set r(r) {
|
|
3368
|
+
this.type.set(TYPE.RGB);
|
|
3369
|
+
this.changed = true;
|
|
3370
|
+
this.data.r = r;
|
|
3371
|
+
}
|
|
3372
|
+
set g(g) {
|
|
3373
|
+
this.type.set(TYPE.RGB);
|
|
3374
|
+
this.changed = true;
|
|
3375
|
+
this.data.g = g;
|
|
3376
|
+
}
|
|
3377
|
+
set b(b) {
|
|
3378
|
+
this.type.set(TYPE.RGB);
|
|
3379
|
+
this.changed = true;
|
|
3380
|
+
this.data.b = b;
|
|
3381
|
+
}
|
|
3382
|
+
set h(h) {
|
|
3383
|
+
this.type.set(TYPE.HSL);
|
|
3384
|
+
this.changed = true;
|
|
3385
|
+
this.data.h = h;
|
|
3386
|
+
}
|
|
3387
|
+
set s(s) {
|
|
3388
|
+
this.type.set(TYPE.HSL);
|
|
3389
|
+
this.changed = true;
|
|
3390
|
+
this.data.s = s;
|
|
3391
|
+
}
|
|
3392
|
+
set l(l) {
|
|
3393
|
+
this.type.set(TYPE.HSL);
|
|
3394
|
+
this.changed = true;
|
|
3395
|
+
this.data.l = l;
|
|
3396
|
+
}
|
|
3397
|
+
set a(a) {
|
|
3398
|
+
this.changed = true;
|
|
3399
|
+
this.data.a = a;
|
|
3400
|
+
}
|
|
3401
|
+
}
|
|
3402
|
+
const Channels$1 = Channels;
|
|
3403
|
+
const channels = new Channels$1({ r: 0, g: 0, b: 0, a: 0 }, "transparent");
|
|
3404
|
+
const Hex = {
|
|
3405
|
+
/* VARIABLES */
|
|
3406
|
+
re: /^#((?:[a-f0-9]{2}){2,4}|[a-f0-9]{3})$/i,
|
|
3407
|
+
/* API */
|
|
3408
|
+
parse: (color) => {
|
|
3409
|
+
if (color.charCodeAt(0) !== 35)
|
|
3410
|
+
return;
|
|
3411
|
+
const match = color.match(Hex.re);
|
|
3412
|
+
if (!match)
|
|
3413
|
+
return;
|
|
3414
|
+
const hex = match[1];
|
|
3415
|
+
const dec = parseInt(hex, 16);
|
|
3416
|
+
const length = hex.length;
|
|
3417
|
+
const hasAlpha = length % 4 === 0;
|
|
3418
|
+
const isFullLength = length > 4;
|
|
3419
|
+
const multiplier = isFullLength ? 1 : 17;
|
|
3420
|
+
const bits = isFullLength ? 8 : 4;
|
|
3421
|
+
const bitsOffset = hasAlpha ? 0 : -1;
|
|
3422
|
+
const mask = isFullLength ? 255 : 15;
|
|
3423
|
+
return channels.set({
|
|
3424
|
+
r: (dec >> bits * (bitsOffset + 3) & mask) * multiplier,
|
|
3425
|
+
g: (dec >> bits * (bitsOffset + 2) & mask) * multiplier,
|
|
3426
|
+
b: (dec >> bits * (bitsOffset + 1) & mask) * multiplier,
|
|
3427
|
+
a: hasAlpha ? (dec & mask) * multiplier / 255 : 1
|
|
3428
|
+
}, color);
|
|
3429
|
+
},
|
|
3430
|
+
stringify: (channels2) => {
|
|
3431
|
+
const { r, g, b, a } = channels2;
|
|
3432
|
+
if (a < 1) {
|
|
3433
|
+
return `#${DEC2HEX[Math.round(r)]}${DEC2HEX[Math.round(g)]}${DEC2HEX[Math.round(b)]}${DEC2HEX[Math.round(a * 255)]}`;
|
|
3434
|
+
} else {
|
|
3435
|
+
return `#${DEC2HEX[Math.round(r)]}${DEC2HEX[Math.round(g)]}${DEC2HEX[Math.round(b)]}`;
|
|
3436
|
+
}
|
|
3437
|
+
}
|
|
3438
|
+
};
|
|
3439
|
+
const HSL = {
|
|
3440
|
+
/* VARIABLES */
|
|
3441
|
+
re: /^hsla?\(\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?(?:deg|grad|rad|turn)?)\s*?(?:,|\s)\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?%)\s*?(?:,|\s)\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?%)(?:\s*?(?:,|\/)\s*?\+?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?(%)?))?\s*?\)$/i,
|
|
3442
|
+
hueRe: /^(.+?)(deg|grad|rad|turn)$/i,
|
|
3443
|
+
/* HELPERS */
|
|
3444
|
+
_hue2deg: (hue) => {
|
|
3445
|
+
const match = hue.match(HSL.hueRe);
|
|
3446
|
+
if (match) {
|
|
3447
|
+
const [, number, unit2] = match;
|
|
3448
|
+
switch (unit2) {
|
|
3449
|
+
case "grad":
|
|
3450
|
+
return Utils.channel.clamp.h(parseFloat(number) * 0.9);
|
|
3451
|
+
case "rad":
|
|
3452
|
+
return Utils.channel.clamp.h(parseFloat(number) * 180 / Math.PI);
|
|
3453
|
+
case "turn":
|
|
3454
|
+
return Utils.channel.clamp.h(parseFloat(number) * 360);
|
|
3455
|
+
}
|
|
3456
|
+
}
|
|
3457
|
+
return Utils.channel.clamp.h(parseFloat(hue));
|
|
3458
|
+
},
|
|
3459
|
+
/* API */
|
|
3460
|
+
parse: (color) => {
|
|
3461
|
+
const charCode = color.charCodeAt(0);
|
|
3462
|
+
if (charCode !== 104 && charCode !== 72)
|
|
3463
|
+
return;
|
|
3464
|
+
const match = color.match(HSL.re);
|
|
3465
|
+
if (!match)
|
|
3466
|
+
return;
|
|
3467
|
+
const [, h, s, l, a, isAlphaPercentage] = match;
|
|
3468
|
+
return channels.set({
|
|
3469
|
+
h: HSL._hue2deg(h),
|
|
3470
|
+
s: Utils.channel.clamp.s(parseFloat(s)),
|
|
3471
|
+
l: Utils.channel.clamp.l(parseFloat(l)),
|
|
3472
|
+
a: a ? Utils.channel.clamp.a(isAlphaPercentage ? parseFloat(a) / 100 : parseFloat(a)) : 1
|
|
3473
|
+
}, color);
|
|
3474
|
+
},
|
|
3475
|
+
stringify: (channels2) => {
|
|
3476
|
+
const { h, s, l, a } = channels2;
|
|
3477
|
+
if (a < 1) {
|
|
3478
|
+
return `hsla(${Utils.lang.round(h)}, ${Utils.lang.round(s)}%, ${Utils.lang.round(l)}%, ${a})`;
|
|
3479
|
+
} else {
|
|
3480
|
+
return `hsl(${Utils.lang.round(h)}, ${Utils.lang.round(s)}%, ${Utils.lang.round(l)}%)`;
|
|
3481
|
+
}
|
|
3482
|
+
}
|
|
3483
|
+
};
|
|
3484
|
+
const Keyword = {
|
|
3485
|
+
/* VARIABLES */
|
|
3486
|
+
colors: {
|
|
3487
|
+
aliceblue: "#f0f8ff",
|
|
3488
|
+
antiquewhite: "#faebd7",
|
|
3489
|
+
aqua: "#00ffff",
|
|
3490
|
+
aquamarine: "#7fffd4",
|
|
3491
|
+
azure: "#f0ffff",
|
|
3492
|
+
beige: "#f5f5dc",
|
|
3493
|
+
bisque: "#ffe4c4",
|
|
3494
|
+
black: "#000000",
|
|
3495
|
+
blanchedalmond: "#ffebcd",
|
|
3496
|
+
blue: "#0000ff",
|
|
3497
|
+
blueviolet: "#8a2be2",
|
|
3498
|
+
brown: "#a52a2a",
|
|
3499
|
+
burlywood: "#deb887",
|
|
3500
|
+
cadetblue: "#5f9ea0",
|
|
3501
|
+
chartreuse: "#7fff00",
|
|
3502
|
+
chocolate: "#d2691e",
|
|
3503
|
+
coral: "#ff7f50",
|
|
3504
|
+
cornflowerblue: "#6495ed",
|
|
3505
|
+
cornsilk: "#fff8dc",
|
|
3506
|
+
crimson: "#dc143c",
|
|
3507
|
+
cyanaqua: "#00ffff",
|
|
3508
|
+
darkblue: "#00008b",
|
|
3509
|
+
darkcyan: "#008b8b",
|
|
3510
|
+
darkgoldenrod: "#b8860b",
|
|
3511
|
+
darkgray: "#a9a9a9",
|
|
3512
|
+
darkgreen: "#006400",
|
|
3513
|
+
darkgrey: "#a9a9a9",
|
|
3514
|
+
darkkhaki: "#bdb76b",
|
|
3515
|
+
darkmagenta: "#8b008b",
|
|
3516
|
+
darkolivegreen: "#556b2f",
|
|
3517
|
+
darkorange: "#ff8c00",
|
|
3518
|
+
darkorchid: "#9932cc",
|
|
3519
|
+
darkred: "#8b0000",
|
|
3520
|
+
darksalmon: "#e9967a",
|
|
3521
|
+
darkseagreen: "#8fbc8f",
|
|
3522
|
+
darkslateblue: "#483d8b",
|
|
3523
|
+
darkslategray: "#2f4f4f",
|
|
3524
|
+
darkslategrey: "#2f4f4f",
|
|
3525
|
+
darkturquoise: "#00ced1",
|
|
3526
|
+
darkviolet: "#9400d3",
|
|
3527
|
+
deeppink: "#ff1493",
|
|
3528
|
+
deepskyblue: "#00bfff",
|
|
3529
|
+
dimgray: "#696969",
|
|
3530
|
+
dimgrey: "#696969",
|
|
3531
|
+
dodgerblue: "#1e90ff",
|
|
3532
|
+
firebrick: "#b22222",
|
|
3533
|
+
floralwhite: "#fffaf0",
|
|
3534
|
+
forestgreen: "#228b22",
|
|
3535
|
+
fuchsia: "#ff00ff",
|
|
3536
|
+
gainsboro: "#dcdcdc",
|
|
3537
|
+
ghostwhite: "#f8f8ff",
|
|
3538
|
+
gold: "#ffd700",
|
|
3539
|
+
goldenrod: "#daa520",
|
|
3540
|
+
gray: "#808080",
|
|
3541
|
+
green: "#008000",
|
|
3542
|
+
greenyellow: "#adff2f",
|
|
3543
|
+
grey: "#808080",
|
|
3544
|
+
honeydew: "#f0fff0",
|
|
3545
|
+
hotpink: "#ff69b4",
|
|
3546
|
+
indianred: "#cd5c5c",
|
|
3547
|
+
indigo: "#4b0082",
|
|
3548
|
+
ivory: "#fffff0",
|
|
3549
|
+
khaki: "#f0e68c",
|
|
3550
|
+
lavender: "#e6e6fa",
|
|
3551
|
+
lavenderblush: "#fff0f5",
|
|
3552
|
+
lawngreen: "#7cfc00",
|
|
3553
|
+
lemonchiffon: "#fffacd",
|
|
3554
|
+
lightblue: "#add8e6",
|
|
3555
|
+
lightcoral: "#f08080",
|
|
3556
|
+
lightcyan: "#e0ffff",
|
|
3557
|
+
lightgoldenrodyellow: "#fafad2",
|
|
3558
|
+
lightgray: "#d3d3d3",
|
|
3559
|
+
lightgreen: "#90ee90",
|
|
3560
|
+
lightgrey: "#d3d3d3",
|
|
3561
|
+
lightpink: "#ffb6c1",
|
|
3562
|
+
lightsalmon: "#ffa07a",
|
|
3563
|
+
lightseagreen: "#20b2aa",
|
|
3564
|
+
lightskyblue: "#87cefa",
|
|
3565
|
+
lightslategray: "#778899",
|
|
3566
|
+
lightslategrey: "#778899",
|
|
3567
|
+
lightsteelblue: "#b0c4de",
|
|
3568
|
+
lightyellow: "#ffffe0",
|
|
3569
|
+
lime: "#00ff00",
|
|
3570
|
+
limegreen: "#32cd32",
|
|
3571
|
+
linen: "#faf0e6",
|
|
3572
|
+
magenta: "#ff00ff",
|
|
3573
|
+
maroon: "#800000",
|
|
3574
|
+
mediumaquamarine: "#66cdaa",
|
|
3575
|
+
mediumblue: "#0000cd",
|
|
3576
|
+
mediumorchid: "#ba55d3",
|
|
3577
|
+
mediumpurple: "#9370db",
|
|
3578
|
+
mediumseagreen: "#3cb371",
|
|
3579
|
+
mediumslateblue: "#7b68ee",
|
|
3580
|
+
mediumspringgreen: "#00fa9a",
|
|
3581
|
+
mediumturquoise: "#48d1cc",
|
|
3582
|
+
mediumvioletred: "#c71585",
|
|
3583
|
+
midnightblue: "#191970",
|
|
3584
|
+
mintcream: "#f5fffa",
|
|
3585
|
+
mistyrose: "#ffe4e1",
|
|
3586
|
+
moccasin: "#ffe4b5",
|
|
3587
|
+
navajowhite: "#ffdead",
|
|
3588
|
+
navy: "#000080",
|
|
3589
|
+
oldlace: "#fdf5e6",
|
|
3590
|
+
olive: "#808000",
|
|
3591
|
+
olivedrab: "#6b8e23",
|
|
3592
|
+
orange: "#ffa500",
|
|
3593
|
+
orangered: "#ff4500",
|
|
3594
|
+
orchid: "#da70d6",
|
|
3595
|
+
palegoldenrod: "#eee8aa",
|
|
3596
|
+
palegreen: "#98fb98",
|
|
3597
|
+
paleturquoise: "#afeeee",
|
|
3598
|
+
palevioletred: "#db7093",
|
|
3599
|
+
papayawhip: "#ffefd5",
|
|
3600
|
+
peachpuff: "#ffdab9",
|
|
3601
|
+
peru: "#cd853f",
|
|
3602
|
+
pink: "#ffc0cb",
|
|
3603
|
+
plum: "#dda0dd",
|
|
3604
|
+
powderblue: "#b0e0e6",
|
|
3605
|
+
purple: "#800080",
|
|
3606
|
+
rebeccapurple: "#663399",
|
|
3607
|
+
red: "#ff0000",
|
|
3608
|
+
rosybrown: "#bc8f8f",
|
|
3609
|
+
royalblue: "#4169e1",
|
|
3610
|
+
saddlebrown: "#8b4513",
|
|
3611
|
+
salmon: "#fa8072",
|
|
3612
|
+
sandybrown: "#f4a460",
|
|
3613
|
+
seagreen: "#2e8b57",
|
|
3614
|
+
seashell: "#fff5ee",
|
|
3615
|
+
sienna: "#a0522d",
|
|
3616
|
+
silver: "#c0c0c0",
|
|
3617
|
+
skyblue: "#87ceeb",
|
|
3618
|
+
slateblue: "#6a5acd",
|
|
3619
|
+
slategray: "#708090",
|
|
3620
|
+
slategrey: "#708090",
|
|
3621
|
+
snow: "#fffafa",
|
|
3622
|
+
springgreen: "#00ff7f",
|
|
3623
|
+
tan: "#d2b48c",
|
|
3624
|
+
teal: "#008080",
|
|
3625
|
+
thistle: "#d8bfd8",
|
|
3626
|
+
transparent: "#00000000",
|
|
3627
|
+
turquoise: "#40e0d0",
|
|
3628
|
+
violet: "#ee82ee",
|
|
3629
|
+
wheat: "#f5deb3",
|
|
3630
|
+
white: "#ffffff",
|
|
3631
|
+
whitesmoke: "#f5f5f5",
|
|
3632
|
+
yellow: "#ffff00",
|
|
3633
|
+
yellowgreen: "#9acd32"
|
|
3634
|
+
},
|
|
3635
|
+
/* API */
|
|
3636
|
+
parse: (color) => {
|
|
3637
|
+
color = color.toLowerCase();
|
|
3638
|
+
const hex = Keyword.colors[color];
|
|
3639
|
+
if (!hex)
|
|
3640
|
+
return;
|
|
3641
|
+
return Hex.parse(hex);
|
|
3642
|
+
},
|
|
3643
|
+
stringify: (channels2) => {
|
|
3644
|
+
const hex = Hex.stringify(channels2);
|
|
3645
|
+
for (const name in Keyword.colors) {
|
|
3646
|
+
if (Keyword.colors[name] === hex)
|
|
3647
|
+
return name;
|
|
3648
|
+
}
|
|
3649
|
+
return;
|
|
3650
|
+
}
|
|
3651
|
+
};
|
|
3652
|
+
const RGB = {
|
|
3653
|
+
/* VARIABLES */
|
|
3654
|
+
re: /^rgba?\(\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e\d+)?(%?))\s*?(?:,|\s)\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e\d+)?(%?))\s*?(?:,|\s)\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e\d+)?(%?))(?:\s*?(?:,|\/)\s*?\+?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e\d+)?(%?)))?\s*?\)$/i,
|
|
3655
|
+
/* API */
|
|
3656
|
+
parse: (color) => {
|
|
3657
|
+
const charCode = color.charCodeAt(0);
|
|
3658
|
+
if (charCode !== 114 && charCode !== 82)
|
|
3659
|
+
return;
|
|
3660
|
+
const match = color.match(RGB.re);
|
|
3661
|
+
if (!match)
|
|
3662
|
+
return;
|
|
3663
|
+
const [, r, isRedPercentage, g, isGreenPercentage, b, isBluePercentage, a, isAlphaPercentage] = match;
|
|
3664
|
+
return channels.set({
|
|
3665
|
+
r: Utils.channel.clamp.r(isRedPercentage ? parseFloat(r) * 2.55 : parseFloat(r)),
|
|
3666
|
+
g: Utils.channel.clamp.g(isGreenPercentage ? parseFloat(g) * 2.55 : parseFloat(g)),
|
|
3667
|
+
b: Utils.channel.clamp.b(isBluePercentage ? parseFloat(b) * 2.55 : parseFloat(b)),
|
|
3668
|
+
a: a ? Utils.channel.clamp.a(isAlphaPercentage ? parseFloat(a) / 100 : parseFloat(a)) : 1
|
|
3669
|
+
}, color);
|
|
3670
|
+
},
|
|
3671
|
+
stringify: (channels2) => {
|
|
3672
|
+
const { r, g, b, a } = channels2;
|
|
3673
|
+
if (a < 1) {
|
|
3674
|
+
return `rgba(${Utils.lang.round(r)}, ${Utils.lang.round(g)}, ${Utils.lang.round(b)}, ${Utils.lang.round(a)})`;
|
|
3675
|
+
} else {
|
|
3676
|
+
return `rgb(${Utils.lang.round(r)}, ${Utils.lang.round(g)}, ${Utils.lang.round(b)})`;
|
|
3677
|
+
}
|
|
3678
|
+
}
|
|
3679
|
+
};
|
|
3680
|
+
const Color = {
|
|
3681
|
+
/* VARIABLES */
|
|
3682
|
+
format: {
|
|
3683
|
+
keyword: Keyword,
|
|
3684
|
+
hex: Hex,
|
|
3685
|
+
rgb: RGB,
|
|
3686
|
+
rgba: RGB,
|
|
3687
|
+
hsl: HSL,
|
|
3688
|
+
hsla: HSL
|
|
3689
|
+
},
|
|
3690
|
+
/* API */
|
|
3691
|
+
parse: (color) => {
|
|
3692
|
+
if (typeof color !== "string")
|
|
3693
|
+
return color;
|
|
3694
|
+
const channels2 = Hex.parse(color) || RGB.parse(color) || HSL.parse(color) || Keyword.parse(color);
|
|
3695
|
+
if (channels2)
|
|
3696
|
+
return channels2;
|
|
3697
|
+
throw new Error(`Unsupported color format: "${color}"`);
|
|
3698
|
+
},
|
|
3699
|
+
stringify: (channels2) => {
|
|
3700
|
+
if (!channels2.changed && channels2.color)
|
|
3701
|
+
return channels2.color;
|
|
3702
|
+
if (channels2.type.is(TYPE.HSL) || channels2.data.r === void 0) {
|
|
3703
|
+
return HSL.stringify(channels2);
|
|
3704
|
+
} else if (channels2.a < 1 || !Number.isInteger(channels2.r) || !Number.isInteger(channels2.g) || !Number.isInteger(channels2.b)) {
|
|
3705
|
+
return RGB.stringify(channels2);
|
|
3706
|
+
} else {
|
|
3707
|
+
return Hex.stringify(channels2);
|
|
3708
|
+
}
|
|
3709
|
+
}
|
|
3710
|
+
};
|
|
3711
|
+
const change = (color, channels2) => {
|
|
3712
|
+
const ch = Color.parse(color);
|
|
3713
|
+
for (const c in channels2) {
|
|
3714
|
+
ch[c] = Utils.channel.clamp[c](channels2[c]);
|
|
3715
|
+
}
|
|
3716
|
+
return Color.stringify(ch);
|
|
3717
|
+
};
|
|
3718
|
+
const toHex = (color) => {
|
|
3719
|
+
return Color.format.hex.stringify(Color.parse(color));
|
|
3720
|
+
};
|
|
3721
|
+
const adjust = (color, channels2) => {
|
|
3722
|
+
const ch = Color.parse(color);
|
|
3723
|
+
const changes = {};
|
|
3724
|
+
for (const c in channels2) {
|
|
3725
|
+
if (!channels2[c])
|
|
3726
|
+
continue;
|
|
3727
|
+
changes[c] = ch[c] + channels2[c];
|
|
3728
|
+
}
|
|
3729
|
+
return change(color, changes);
|
|
3730
|
+
};
|
|
3731
|
+
const scale = (color, channels2) => {
|
|
3732
|
+
const ch = Color.parse(color);
|
|
3733
|
+
const adjustments = {};
|
|
3734
|
+
const delta = (amount, weight, max) => weight > 0 ? (max - amount) * weight / 100 : amount * weight / 100;
|
|
3735
|
+
for (const c in channels2) {
|
|
3736
|
+
adjustments[c] = delta(ch[c], channels2[c], Utils.channel.max[c]);
|
|
3737
|
+
}
|
|
3738
|
+
return adjust(color, adjustments);
|
|
3739
|
+
};
|
|
3740
|
+
var vars = { likec4: { font: "var(--likec4-font-family)", backgroundColor: "var(--likec4-background-color)" }, compound: { font: "var(--likec4-compound-font-family)", titleColor: "var(--likec4-compound-title-color)" }, element: { font: "var(--likec4-element-font-family)", fill: "var(--likec4-element-fill)", stroke: "var(--likec4-element-stroke)", hiContrast: "var(--likec4-element-hiContrast)", loContrast: "var(--likec4-element-loContrast)" }, relation: { lineColor: "var(--likec4-relation-lineColor)", labelColor: "var(--likec4-relation-labelColor)", labelBgColor: "var(--likec4-relation-labelBg)" } };
|
|
3741
|
+
function toDomPrecision(v) {
|
|
3742
|
+
if (v === null) {
|
|
3743
|
+
return 0.01;
|
|
3744
|
+
}
|
|
3745
|
+
return Math.round(v * 100) / 100;
|
|
3746
|
+
}
|
|
3747
|
+
const Link = react.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3748
|
+
"svg",
|
|
3749
|
+
{
|
|
3750
|
+
ref,
|
|
3751
|
+
className: clsx("icon icon-tabler", className),
|
|
3752
|
+
stroke: "currentColor",
|
|
3753
|
+
fill: "currentColor",
|
|
3754
|
+
strokeWidth: "0",
|
|
3755
|
+
viewBox: "0 0 20 20",
|
|
3756
|
+
height: "20",
|
|
3757
|
+
width: "20",
|
|
3758
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
3759
|
+
...props,
|
|
3760
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3761
|
+
"path",
|
|
3762
|
+
{
|
|
3763
|
+
fillRule: "evenodd",
|
|
3764
|
+
d: "M12.586 4.586a2 2 0 112.828 2.828l-3 3a2 2 0 01-2.828 0 1 1 0 00-1.414 1.414 4 4 0 005.656 0l3-3a4 4 0 00-5.656-5.656l-1.5 1.5a1 1 0 101.414 1.414l1.5-1.5zm-5 5a2 2 0 012.828 0 1 1 0 101.414-1.414 4 4 0 00-5.656 0l-3 3a4 4 0 105.656 5.656l1.5-1.5a1 1 0 10-1.414-1.414l-1.5 1.5a2 2 0 11-2.828-2.828l3-3z",
|
|
3765
|
+
clipRule: "evenodd"
|
|
3766
|
+
}
|
|
3767
|
+
)
|
|
3768
|
+
}
|
|
3769
|
+
));
|
|
3770
|
+
const ZoomIn = react.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3771
|
+
"svg",
|
|
3772
|
+
{
|
|
3773
|
+
ref,
|
|
3774
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
3775
|
+
className: clsx("icon icon-tabler icon-tabler-zoom-in", className),
|
|
3776
|
+
width: "24",
|
|
3777
|
+
height: "24",
|
|
3778
|
+
viewBox: "0 0 24 24",
|
|
3779
|
+
strokeWidth: "1.5",
|
|
3780
|
+
stroke: "currentColor",
|
|
3781
|
+
fill: "none",
|
|
3782
|
+
strokeLinecap: "round",
|
|
3783
|
+
strokeLinejoin: "round",
|
|
3784
|
+
...props,
|
|
3785
|
+
children: [
|
|
3786
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { stroke: "none", d: "M0 0h24v24H0z", fill: "none" }),
|
|
3787
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 10m-7 0a7 7 0 1 0 14 0a7 7 0 1 0 -14 0" }),
|
|
3788
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 10l6 0" }),
|
|
3789
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 7l0 6" }),
|
|
3790
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 21l-6 -6" })
|
|
3791
|
+
]
|
|
3792
|
+
}
|
|
3793
|
+
));
|
|
3794
|
+
function NavigateToBtn({ xynodeId, className }) {
|
|
3795
|
+
const { onNavigateTo } = useXYFlowEvents();
|
|
3796
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3797
|
+
core.ActionIcon,
|
|
3798
|
+
{
|
|
3799
|
+
className: clsx("nodrag nopan", className),
|
|
3800
|
+
radius: "xl",
|
|
3801
|
+
autoFocus: false,
|
|
3802
|
+
onClick: (event) => {
|
|
3803
|
+
event.stopPropagation();
|
|
3804
|
+
event.preventDefault();
|
|
3805
|
+
onNavigateTo(xynodeId, event);
|
|
3806
|
+
},
|
|
3807
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ZoomIn, {})
|
|
3808
|
+
}
|
|
3809
|
+
);
|
|
3810
|
+
}
|
|
3811
|
+
var cssContainer = "lbtzdo0";
|
|
3812
|
+
var cssCompound = "lbtzdo2";
|
|
3813
|
+
var cssTitle = "lbtzdo4";
|
|
3814
|
+
var cssIndicator = "lbtzdo6";
|
|
3815
|
+
var cssNavigateBtn$1 = "lbtzdo7";
|
|
3816
|
+
const isEqualProps$1 = (prev, next) => prev.id === next.id && prev.selected === next.selected && prev.width === next.width && prev.height === next.height && deepEqual(prev.data, next.data);
|
|
3817
|
+
const compoundColor = (color, depth) => toHex(
|
|
3818
|
+
scale(color, {
|
|
3819
|
+
l: -35 - 5 * depth,
|
|
3820
|
+
s: -15 - 5 * depth
|
|
3821
|
+
})
|
|
3822
|
+
);
|
|
3823
|
+
const CompoundNodeMemo = /* @__PURE__ */ react.memo(function CompoundNode({
|
|
3824
|
+
id,
|
|
3825
|
+
data: {
|
|
3826
|
+
element
|
|
3827
|
+
},
|
|
3828
|
+
width,
|
|
3829
|
+
height
|
|
3830
|
+
}) {
|
|
3831
|
+
const { color, depth = 0, ...compound } = element;
|
|
3832
|
+
const colors2 = react.useMemo(() => {
|
|
3833
|
+
const colors22 = core$1.defaultTheme.elements[color];
|
|
3834
|
+
return {
|
|
3835
|
+
...colors22,
|
|
3836
|
+
fill: compoundColor(colors22.fill, depth),
|
|
3837
|
+
stroke: compoundColor(colors22.stroke, depth)
|
|
3838
|
+
};
|
|
3839
|
+
}, [color, depth]);
|
|
3840
|
+
const w = toDomPrecision(width ?? compound.width);
|
|
3841
|
+
const h = toDomPrecision(height ?? compound.height);
|
|
3842
|
+
const diagramState = useDiagramState();
|
|
3843
|
+
const isnavigable = diagramState.hasOnNavigateTo && !!compound.navigateTo;
|
|
3844
|
+
const isHovered = useDiagramStateSelector((state) => state.hoveredNodeId === id);
|
|
3845
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3846
|
+
core.Box,
|
|
3847
|
+
{
|
|
3848
|
+
className: clsx(cssContainer, "likec4-compound-node"),
|
|
3849
|
+
style: assignInlineVars({ fill: vars.element.fill, stroke: vars.element.stroke }, {
|
|
3850
|
+
fill: colors2.fill,
|
|
3851
|
+
stroke: colors2.stroke
|
|
3852
|
+
}),
|
|
3853
|
+
mod: {
|
|
3854
|
+
"likec4-color": color,
|
|
3855
|
+
"likec4-shape": compound.shape,
|
|
3856
|
+
"likec4-navigable": isnavigable,
|
|
3857
|
+
hovered: isHovered
|
|
3858
|
+
},
|
|
3859
|
+
children: [
|
|
3860
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3861
|
+
react$1.Handle,
|
|
3862
|
+
{
|
|
3863
|
+
type: "target",
|
|
3864
|
+
position: react$1.Position.Top,
|
|
3865
|
+
style: { visibility: "hidden" }
|
|
3866
|
+
}
|
|
3867
|
+
),
|
|
3868
|
+
/* @__PURE__ */ jsxRuntime.jsx("svg", { className: cssIndicator, viewBox: `0 0 ${w} ${h}`, width: w, height: h, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3869
|
+
"rect",
|
|
3870
|
+
{
|
|
3871
|
+
x: -1,
|
|
3872
|
+
y: -1,
|
|
3873
|
+
width: w + 2,
|
|
3874
|
+
height: h + 2,
|
|
3875
|
+
rx: 6
|
|
3876
|
+
}
|
|
3877
|
+
) }),
|
|
3878
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx(cssCompound, "likec4-compound"), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3879
|
+
core.Text,
|
|
3880
|
+
{
|
|
3881
|
+
component: "div",
|
|
3882
|
+
className: clsx(cssTitle, "likec4-compound-title"),
|
|
3883
|
+
children: compound.title
|
|
3884
|
+
}
|
|
3885
|
+
) }),
|
|
3886
|
+
isnavigable && /* @__PURE__ */ jsxRuntime.jsx(NavigateToBtn, { xynodeId: id, className: cssNavigateBtn$1 }),
|
|
3887
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3888
|
+
react$1.Handle,
|
|
3889
|
+
{
|
|
3890
|
+
type: "source",
|
|
3891
|
+
position: react$1.Position.Bottom,
|
|
3892
|
+
style: { visibility: "hidden" }
|
|
3893
|
+
}
|
|
3894
|
+
)
|
|
3895
|
+
]
|
|
3896
|
+
}
|
|
3897
|
+
);
|
|
3898
|
+
}, isEqualProps$1);
|
|
3899
|
+
var container = "_1b6tkn2";
|
|
3900
|
+
var indicator = "_1b6tkn4";
|
|
3901
|
+
var fillElementFill = "_1b6tkn5";
|
|
3902
|
+
var fillMixStroke = "_1b6tkn7";
|
|
3903
|
+
var title = "_1b6tkn8";
|
|
3904
|
+
var description = "_1b6tkn9";
|
|
3905
|
+
var technology = "_1b6tkna";
|
|
3906
|
+
var cssElement = "_1b6tknb";
|
|
3907
|
+
var iconMaxH = "var(--_1b6tknc)";
|
|
3908
|
+
var elementIcon = "_1b6tknd";
|
|
3909
|
+
var cssShapeSvg = "_1b6tkng";
|
|
3910
|
+
var cssNavigateBtn = "_1b6tknh";
|
|
3911
|
+
function ElementIcon({
|
|
3912
|
+
node,
|
|
3913
|
+
maxWidth,
|
|
3914
|
+
paddingX = 32,
|
|
3915
|
+
paddingY = 32
|
|
3916
|
+
}) {
|
|
3917
|
+
if (!node.icon) {
|
|
3918
|
+
return null;
|
|
3919
|
+
}
|
|
3920
|
+
const firstLabel = node.labels[0];
|
|
3921
|
+
if (!firstLabel) {
|
|
3922
|
+
return null;
|
|
3923
|
+
}
|
|
3924
|
+
const firstLabelY = Math.floor(firstLabel.pt[1] - firstLabel.fontSize * 1.25);
|
|
3925
|
+
const maxIconHeight = Math.floor(firstLabelY - paddingY - 16);
|
|
3926
|
+
maxWidth ?? node.width - paddingX * 2;
|
|
3927
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3928
|
+
"div",
|
|
3929
|
+
{
|
|
3930
|
+
className: clsx(elementIcon, "likec4-element-icon"),
|
|
3931
|
+
style: assignInlineVars({ iconMaxH }, {
|
|
3932
|
+
iconMaxH: maxIconHeight + "px"
|
|
3933
|
+
}),
|
|
3934
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3935
|
+
"img",
|
|
3936
|
+
{
|
|
3937
|
+
src: node.icon,
|
|
3938
|
+
alt: node.title
|
|
3939
|
+
}
|
|
3940
|
+
)
|
|
3941
|
+
}
|
|
3942
|
+
);
|
|
3943
|
+
}
|
|
3944
|
+
var elementLink = "_4ysv0o0";
|
|
3945
|
+
var trigger = "_4ysv0o1";
|
|
3946
|
+
function ElementLink({
|
|
3947
|
+
element
|
|
3948
|
+
}) {
|
|
3949
|
+
if (!element.links) {
|
|
3950
|
+
return null;
|
|
3951
|
+
}
|
|
3952
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3953
|
+
framerMotion.motion.div,
|
|
3954
|
+
{
|
|
3955
|
+
className: elementLink,
|
|
3956
|
+
whileHover: {
|
|
3957
|
+
scale: 1.07
|
|
3958
|
+
},
|
|
3959
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3960
|
+
core.HoverCard,
|
|
3961
|
+
{
|
|
3962
|
+
position: "bottom-start",
|
|
3963
|
+
shadow: "lg",
|
|
3964
|
+
radius: "sm",
|
|
3965
|
+
transitionProps: {
|
|
3966
|
+
transition: "pop"
|
|
3967
|
+
},
|
|
3968
|
+
withinPortal: false,
|
|
3969
|
+
floatingStrategy: "fixed",
|
|
3970
|
+
openDelay: 350,
|
|
3971
|
+
closeDelay: 600,
|
|
3972
|
+
offset: {
|
|
3973
|
+
mainAxis: 5,
|
|
3974
|
+
crossAxis: -10
|
|
3975
|
+
},
|
|
3976
|
+
children: [
|
|
3977
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.HoverCard.Target, { children: /* @__PURE__ */ jsxRuntime.jsxs(core.UnstyledButton, { className: clsx("nodrag nopan", trigger), children: [
|
|
3978
|
+
/* @__PURE__ */ jsxRuntime.jsx(Link, {}),
|
|
3979
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "links" })
|
|
3980
|
+
] }) }),
|
|
3981
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.HoverCard.Dropdown, { p: "xs", children: /* @__PURE__ */ jsxRuntime.jsx(core.Stack, { onClick: (e) => e.stopPropagation(), gap: "xs", children: element.links.map((link, i) => /* @__PURE__ */ jsxRuntime.jsxs(core.Group, { wrap: "nowrap", gap: "sm", children: [
|
|
3982
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Box, { flex: "1", style: { overflow: "clip", maxWidth: 240 }, children: /* @__PURE__ */ jsxRuntime.jsx(core.Anchor, { href: link, target: "_blank", fz: "13", truncate: "end", children: link }) }),
|
|
3983
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.CopyButton, { value: link, children: ({ copied, copy }) => /* @__PURE__ */ jsxRuntime.jsx(core.Button, { size: "compact-xs", fz: "12", onClick: copy, color: copied ? "teal" : "gray", children: copied ? "Copied" : "Copy" }) })
|
|
3984
|
+
] }, link)) }) })
|
|
3985
|
+
]
|
|
3986
|
+
}
|
|
3987
|
+
)
|
|
3988
|
+
}
|
|
3989
|
+
);
|
|
3990
|
+
}
|
|
3991
|
+
function cylinderSVGPath(diameter, height, tilt = 0.0725) {
|
|
3992
|
+
const radius = Math.round(diameter / 2);
|
|
3993
|
+
const rx = radius;
|
|
3994
|
+
const ry = Math.round(tilt * radius);
|
|
3995
|
+
const tiltAdjustedHeight = height - 2 * ry;
|
|
3996
|
+
const path = ` M ${diameter},${ry}
|
|
3997
|
+
a ${rx},${ry} 0,0,0 ${-diameter} 0
|
|
3998
|
+
l 0,${tiltAdjustedHeight}
|
|
3999
|
+
a ${rx},${ry} 0,0,0 ${diameter} 0
|
|
4000
|
+
l 0,${-tiltAdjustedHeight}
|
|
4001
|
+
z
|
|
4002
|
+
`.replace(/\s+/g, " ").trim();
|
|
4003
|
+
return {
|
|
4004
|
+
path,
|
|
4005
|
+
ry,
|
|
4006
|
+
rx
|
|
4007
|
+
};
|
|
4008
|
+
}
|
|
4009
|
+
function queueSVGPath(width, height, tilt = 0.2) {
|
|
4010
|
+
const diameter = height;
|
|
4011
|
+
const radius = Math.round(diameter / 2);
|
|
4012
|
+
const ry = radius;
|
|
4013
|
+
const rx = Math.round(diameter / 2 * tilt);
|
|
4014
|
+
const tiltAdjustedWidth = width - 2 * rx;
|
|
4015
|
+
const path = `
|
|
4016
|
+
M ${rx},0
|
|
4017
|
+
a ${rx},${ry} 0,0,0 0 ${diameter}
|
|
4018
|
+
l ${tiltAdjustedWidth},0
|
|
4019
|
+
a ${rx},${ry} 0,0,0 0 ${-diameter}
|
|
4020
|
+
z`.replace(/\s+/g, " ").trim();
|
|
4021
|
+
return {
|
|
4022
|
+
path,
|
|
4023
|
+
ry,
|
|
4024
|
+
rx
|
|
4025
|
+
};
|
|
4026
|
+
}
|
|
4027
|
+
const PersonIcon = {
|
|
4028
|
+
width: 115,
|
|
4029
|
+
height: 120,
|
|
4030
|
+
path: `M57.9197 0C10.9124 0 33.5766 54.75 33.5766 54.75C38.6131 62.25 45.3285 60.75 45.3285 66C45.3285 70.5 39.4526 72 33.5766 72.75C24.3431 72.75 15.9489 71.25 7.55474 84.75C2.51825 93 0 120 0 120H115C115 120 112.482 93 108.285 84.75C99.8905 70.5 91.4963 72.75 82.2628 72C76.3869 71.25 70.5109 69.75 70.5109 65.25C70.5109 60.75 77.2263 62.25 82.2628 54C82.2628 54.75 104.927 0 57.9197 0V0Z`
|
|
4031
|
+
};
|
|
4032
|
+
const ElementShapeSvg = /* @__PURE__ */ react.memo(({
|
|
4033
|
+
shape,
|
|
4034
|
+
w,
|
|
4035
|
+
h
|
|
4036
|
+
}) => {
|
|
4037
|
+
switch (shape) {
|
|
4038
|
+
case "mobile": {
|
|
4039
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4040
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4041
|
+
"rect",
|
|
4042
|
+
{
|
|
4043
|
+
width: w,
|
|
4044
|
+
height: h,
|
|
4045
|
+
rx: 6,
|
|
4046
|
+
className: fillMixStroke,
|
|
4047
|
+
strokeWidth: 0
|
|
4048
|
+
}
|
|
4049
|
+
),
|
|
4050
|
+
/* @__PURE__ */ jsxRuntime.jsxs("g", { className: fillElementFill, strokeWidth: 0, children: [
|
|
4051
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: 17, cy: h / 2, r: 12 }),
|
|
4052
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: 33, y: 12, width: w - 44, height: h - 24, rx: 5 })
|
|
4053
|
+
] })
|
|
4054
|
+
] });
|
|
4055
|
+
}
|
|
4056
|
+
case "browser": {
|
|
4057
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4058
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4059
|
+
"rect",
|
|
4060
|
+
{
|
|
4061
|
+
width: w,
|
|
4062
|
+
height: h,
|
|
4063
|
+
rx: 6,
|
|
4064
|
+
className: fillMixStroke,
|
|
4065
|
+
strokeWidth: 0
|
|
4066
|
+
}
|
|
4067
|
+
),
|
|
4068
|
+
/* @__PURE__ */ jsxRuntime.jsxs("g", { className: fillElementFill, strokeWidth: 0, children: [
|
|
4069
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: 16, cy: 17, r: 7 }),
|
|
4070
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: 36, cy: 17, r: 7 }),
|
|
4071
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: 56, cy: 17, r: 7 }),
|
|
4072
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: 70, y: 8, width: w - 80, height: 17, rx: 4 }),
|
|
4073
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: 10, y: 32, width: w - 20, height: h - 42, rx: 4 })
|
|
4074
|
+
] })
|
|
4075
|
+
] });
|
|
4076
|
+
}
|
|
4077
|
+
case "person": {
|
|
4078
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4079
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4080
|
+
"rect",
|
|
4081
|
+
{
|
|
4082
|
+
width: w,
|
|
4083
|
+
height: h,
|
|
4084
|
+
rx: 6,
|
|
4085
|
+
strokeWidth: 0
|
|
4086
|
+
}
|
|
4087
|
+
),
|
|
4088
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4089
|
+
"svg",
|
|
4090
|
+
{
|
|
4091
|
+
x: w - PersonIcon.width - 6,
|
|
4092
|
+
y: h - PersonIcon.height,
|
|
4093
|
+
width: PersonIcon.width,
|
|
4094
|
+
height: PersonIcon.height,
|
|
4095
|
+
viewBox: `0 0 ${PersonIcon.width} ${PersonIcon.height}`,
|
|
4096
|
+
className: fillMixStroke,
|
|
4097
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4098
|
+
"path",
|
|
4099
|
+
{
|
|
4100
|
+
strokeWidth: 0,
|
|
4101
|
+
d: "M57.9197 0C10.9124 0 33.5766 54.75 33.5766 54.75C38.6131 62.25 45.3285 60.75 45.3285 66C45.3285 70.5 39.4526 72 33.5766 72.75C24.3431 72.75 15.9489 71.25 7.55474 84.75C2.51825 93 0 120 0 120H115C115 120 112.482 93 108.285 84.75C99.8905 70.5 91.4963 72.75 82.2628 72C76.3869 71.25 70.5109 69.75 70.5109 65.25C70.5109 60.75 77.2263 62.25 82.2628 54C82.2628 54.75 104.927 0 57.9197 0V0Z"
|
|
4102
|
+
}
|
|
4103
|
+
)
|
|
4104
|
+
}
|
|
4105
|
+
)
|
|
4106
|
+
] });
|
|
4107
|
+
}
|
|
4108
|
+
case "queue": {
|
|
4109
|
+
const { path, rx, ry } = queueSVGPath(w, h);
|
|
4110
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4111
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: path, strokeWidth: 2 }),
|
|
4112
|
+
/* @__PURE__ */ jsxRuntime.jsx("ellipse", { cx: rx, cy: ry, ry: ry - 0.75, rx, className: fillMixStroke, strokeWidth: 2 })
|
|
4113
|
+
] });
|
|
4114
|
+
}
|
|
4115
|
+
case "storage":
|
|
4116
|
+
case "cylinder": {
|
|
4117
|
+
const { path, rx, ry } = cylinderSVGPath(w, h);
|
|
4118
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4119
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: path, strokeWidth: 2 }),
|
|
4120
|
+
/* @__PURE__ */ jsxRuntime.jsx("ellipse", { cx: rx, cy: ry, ry, rx: rx - 0.75, className: fillMixStroke, strokeWidth: 2 })
|
|
4121
|
+
] });
|
|
4122
|
+
}
|
|
4123
|
+
case "rectangle": {
|
|
4124
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4125
|
+
"rect",
|
|
4126
|
+
{
|
|
4127
|
+
width: w,
|
|
4128
|
+
height: h,
|
|
4129
|
+
rx: 6,
|
|
4130
|
+
strokeWidth: 0
|
|
4131
|
+
}
|
|
4132
|
+
);
|
|
4133
|
+
}
|
|
4134
|
+
default: {
|
|
4135
|
+
return core$1.nonexhaustive(shape);
|
|
4136
|
+
}
|
|
4137
|
+
}
|
|
4138
|
+
}, deepEqual);
|
|
4139
|
+
const SelectedIndicator = /* @__PURE__ */ react.memo(({
|
|
4140
|
+
shape,
|
|
4141
|
+
w,
|
|
4142
|
+
h
|
|
4143
|
+
}) => {
|
|
4144
|
+
switch (shape) {
|
|
4145
|
+
case "queue":
|
|
4146
|
+
case "storage":
|
|
4147
|
+
case "cylinder": {
|
|
4148
|
+
const { path } = shape === "queue" ? queueSVGPath(w, h) : cylinderSVGPath(w, h);
|
|
4149
|
+
return /* @__PURE__ */ jsxRuntime.jsx("path", { d: path });
|
|
4150
|
+
}
|
|
4151
|
+
default: {
|
|
4152
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4153
|
+
"rect",
|
|
4154
|
+
{
|
|
4155
|
+
x: -1,
|
|
4156
|
+
y: -1,
|
|
4157
|
+
width: w + 2,
|
|
4158
|
+
height: h + 2,
|
|
4159
|
+
rx: 6
|
|
4160
|
+
}
|
|
4161
|
+
);
|
|
4162
|
+
}
|
|
4163
|
+
}
|
|
4164
|
+
}, deepEqual);
|
|
4165
|
+
const isEqualProps = (prev, next) => prev.id === next.id && prev.width === next.width && prev.height === next.height && prev.selected === next.selected && deepEqual(prev.data, next.data);
|
|
4166
|
+
const variants = {
|
|
4167
|
+
idle: {
|
|
4168
|
+
transformOrigin: "50% 50%"
|
|
4169
|
+
},
|
|
4170
|
+
selected: {
|
|
4171
|
+
scale: 1.015
|
|
4172
|
+
},
|
|
4173
|
+
hover: {
|
|
4174
|
+
scale: 1.08,
|
|
4175
|
+
transition: {
|
|
4176
|
+
delay: 0.175
|
|
4177
|
+
// duration: 0.3
|
|
4178
|
+
}
|
|
4179
|
+
},
|
|
4180
|
+
tap: {
|
|
4181
|
+
scale: 0.97,
|
|
4182
|
+
transition: {
|
|
4183
|
+
type: "spring"
|
|
4184
|
+
}
|
|
4185
|
+
}
|
|
4186
|
+
};
|
|
4187
|
+
function ElementNode({
|
|
4188
|
+
id,
|
|
4189
|
+
data: {
|
|
4190
|
+
element
|
|
4191
|
+
},
|
|
4192
|
+
selected = false,
|
|
4193
|
+
width,
|
|
4194
|
+
height
|
|
4195
|
+
}) {
|
|
4196
|
+
const diagramState = useDiagramState();
|
|
4197
|
+
const isNodeInteractive = diagramState.isNodeInteractive;
|
|
4198
|
+
const isHovercards = diagramState.disableHovercards !== true;
|
|
4199
|
+
const isNavigable = diagramState.hasOnNavigateTo && !!element.navigateTo;
|
|
4200
|
+
const isHovered = useDiagramStateSelector((state) => state.hoveredNodeId === id);
|
|
4201
|
+
const w = toDomPrecision(width ?? element.width);
|
|
4202
|
+
const h = toDomPrecision(height ?? element.height);
|
|
4203
|
+
let animate = "idle";
|
|
4204
|
+
if (selected) {
|
|
4205
|
+
animate = "selected";
|
|
4206
|
+
}
|
|
4207
|
+
if (isHovered) {
|
|
4208
|
+
animate = "hover";
|
|
4209
|
+
}
|
|
4210
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4211
|
+
framerMotion.motion.div,
|
|
4212
|
+
{
|
|
4213
|
+
id,
|
|
4214
|
+
className: clsx(container, "likec4-element-node"),
|
|
4215
|
+
"data-likec4-color": element.color,
|
|
4216
|
+
"data-likec4-shape": element.shape,
|
|
4217
|
+
variants,
|
|
4218
|
+
initial: "idle",
|
|
4219
|
+
...isNodeInteractive && {
|
|
4220
|
+
whileTap: "tap",
|
|
4221
|
+
animate,
|
|
4222
|
+
["data-likec4-interactive"]: true
|
|
4223
|
+
},
|
|
4224
|
+
children: [
|
|
4225
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4226
|
+
react$1.Handle,
|
|
4227
|
+
{
|
|
4228
|
+
type: "target",
|
|
4229
|
+
position: react$1.Position.Top,
|
|
4230
|
+
style: { visibility: "hidden" }
|
|
4231
|
+
}
|
|
4232
|
+
),
|
|
4233
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4234
|
+
"svg",
|
|
4235
|
+
{
|
|
4236
|
+
className: cssShapeSvg,
|
|
4237
|
+
viewBox: `0 0 ${w} ${h}`,
|
|
4238
|
+
width: w,
|
|
4239
|
+
height: h,
|
|
4240
|
+
children: [
|
|
4241
|
+
/* @__PURE__ */ jsxRuntime.jsx("g", { className: indicator, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4242
|
+
SelectedIndicator,
|
|
4243
|
+
{
|
|
4244
|
+
shape: element.shape,
|
|
4245
|
+
w,
|
|
4246
|
+
h
|
|
4247
|
+
}
|
|
4248
|
+
) }),
|
|
4249
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4250
|
+
ElementShapeSvg,
|
|
4251
|
+
{
|
|
4252
|
+
shape: element.shape,
|
|
4253
|
+
w,
|
|
4254
|
+
h
|
|
4255
|
+
}
|
|
4256
|
+
)
|
|
4257
|
+
]
|
|
4258
|
+
}
|
|
4259
|
+
),
|
|
4260
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx(cssElement, "likec4-element"), children: [
|
|
4261
|
+
element.icon && /* @__PURE__ */ jsxRuntime.jsx(ElementIcon, { node: element }),
|
|
4262
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4263
|
+
core.Text,
|
|
4264
|
+
{
|
|
4265
|
+
component: "div",
|
|
4266
|
+
className: clsx(title, "likec4-element-title"),
|
|
4267
|
+
children: element.title
|
|
4268
|
+
}
|
|
4269
|
+
),
|
|
4270
|
+
element.technology && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4271
|
+
core.Text,
|
|
4272
|
+
{
|
|
4273
|
+
component: "div",
|
|
4274
|
+
className: clsx(technology, "likec4-element-technology"),
|
|
4275
|
+
children: element.technology
|
|
4276
|
+
}
|
|
4277
|
+
),
|
|
4278
|
+
element.description && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4279
|
+
core.Text,
|
|
4280
|
+
{
|
|
4281
|
+
component: "div",
|
|
4282
|
+
className: clsx(description, "likec4-element-description"),
|
|
4283
|
+
children: element.description
|
|
4284
|
+
}
|
|
4285
|
+
)
|
|
4286
|
+
] }),
|
|
4287
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4288
|
+
react$1.Handle,
|
|
4289
|
+
{
|
|
4290
|
+
type: "source",
|
|
4291
|
+
position: react$1.Position.Bottom,
|
|
4292
|
+
style: { visibility: "hidden" }
|
|
4293
|
+
}
|
|
4294
|
+
),
|
|
4295
|
+
isHovercards && /* @__PURE__ */ jsxRuntime.jsx(ElementLink, { element }),
|
|
4296
|
+
isNavigable && /* @__PURE__ */ jsxRuntime.jsx(NavigateToBtn, { xynodeId: id, className: cssNavigateBtn })
|
|
4297
|
+
]
|
|
4298
|
+
}
|
|
4299
|
+
);
|
|
4300
|
+
}
|
|
4301
|
+
const ElementNodeMemo = react.memo(ElementNode, isEqualProps);
|
|
4302
|
+
const nodeTypes = {
|
|
4303
|
+
element: ElementNodeMemo,
|
|
4304
|
+
compound: CompoundNodeMemo
|
|
4305
|
+
};
|
|
4306
|
+
const edgeTypes = {
|
|
4307
|
+
relationship: RelationshipEdge
|
|
4308
|
+
};
|
|
4309
|
+
function XYFlowWrapper({
|
|
4310
|
+
className,
|
|
4311
|
+
children,
|
|
4312
|
+
defaultNodes,
|
|
4313
|
+
defaultEdges,
|
|
4314
|
+
fitView = true,
|
|
4315
|
+
colorMode: colorModeProp,
|
|
4316
|
+
readonly = false,
|
|
4317
|
+
pannable = true,
|
|
4318
|
+
zoomable = true,
|
|
4319
|
+
nodesSelectable = !readonly,
|
|
4320
|
+
nodesDraggable = !readonly,
|
|
4321
|
+
fitViewPadding = 0,
|
|
4322
|
+
style
|
|
4323
|
+
}) {
|
|
4324
|
+
const xyflowRef = react.useRef();
|
|
4325
|
+
const [editor, updateState] = useDiagramStateTracked();
|
|
4326
|
+
const layoutConstraints = useLayoutConstraints(xyflowRef);
|
|
4327
|
+
const handlers = useXYFlowEvents();
|
|
4328
|
+
const { colorScheme } = core.useMantineColorScheme();
|
|
4329
|
+
let colorMode = colorModeProp ?? (colorScheme !== "auto" ? colorScheme : void 0);
|
|
4330
|
+
return (
|
|
4331
|
+
// @ts-expect-error
|
|
4332
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4333
|
+
react$1.ReactFlow,
|
|
4334
|
+
{
|
|
4335
|
+
className,
|
|
4336
|
+
style,
|
|
4337
|
+
...colorMode && { colorMode },
|
|
4338
|
+
defaultNodes,
|
|
4339
|
+
defaultEdges,
|
|
4340
|
+
nodeTypes,
|
|
4341
|
+
edgeTypes,
|
|
4342
|
+
zoomOnPinch: zoomable,
|
|
4343
|
+
zoomOnScroll: !pannable && zoomable,
|
|
4344
|
+
...!zoomable && {
|
|
4345
|
+
zoomActivationKeyCode: null
|
|
4346
|
+
},
|
|
4347
|
+
maxZoom: zoomable ? 1.9 : 1,
|
|
4348
|
+
minZoom: zoomable ? MinZoom : 1,
|
|
4349
|
+
fitView,
|
|
4350
|
+
fitViewOptions: {
|
|
4351
|
+
minZoom: MinZoom,
|
|
4352
|
+
maxZoom: 1,
|
|
4353
|
+
padding: fitViewPadding
|
|
4354
|
+
},
|
|
4355
|
+
defaultMarkerColor: "var(--xy-edge-stroke)",
|
|
4356
|
+
noDragClassName: "nodrag",
|
|
4357
|
+
noPanClassName: "nopan",
|
|
4358
|
+
panOnScroll: pannable,
|
|
4359
|
+
panOnDrag: pannable,
|
|
4360
|
+
elementsSelectable: nodesSelectable,
|
|
4361
|
+
...!nodesSelectable && {
|
|
4362
|
+
selectionKeyCode: null
|
|
4363
|
+
},
|
|
4364
|
+
nodesDraggable,
|
|
4365
|
+
...nodesDraggable && layoutConstraints,
|
|
4366
|
+
zoomOnDoubleClick: false,
|
|
4367
|
+
elevateNodesOnSelect: false,
|
|
4368
|
+
selectNodesOnDrag: false,
|
|
4369
|
+
onInit: react.useCallback((instance) => {
|
|
4370
|
+
xyflowRef.current = instance;
|
|
4371
|
+
updateState({ viewportInitialized: true });
|
|
4372
|
+
}, []),
|
|
4373
|
+
onEdgeMouseEnter: react.useCallback((event, edge) => {
|
|
4374
|
+
updateState({ hoveredEdgeId: edge.id });
|
|
4375
|
+
}, []),
|
|
4376
|
+
onEdgeMouseLeave: react.useCallback(() => {
|
|
4377
|
+
updateState({ hoveredEdgeId: null });
|
|
4378
|
+
}, []),
|
|
4379
|
+
...editor.isNodeInteractive && {
|
|
4380
|
+
onNodeMouseEnter: (event, node) => {
|
|
4381
|
+
updateState({ hoveredNodeId: node.id });
|
|
4382
|
+
},
|
|
4383
|
+
onNodeMouseLeave: () => {
|
|
4384
|
+
updateState({ hoveredNodeId: null });
|
|
4385
|
+
}
|
|
4386
|
+
},
|
|
4387
|
+
...editor.hasOnContextMenu && {
|
|
4388
|
+
onNodeContextMenu: handlers.onNodeContextMenu,
|
|
4389
|
+
onPaneContextMenu: handlers.onPaneContextMenu,
|
|
4390
|
+
onEdgeContextMenu: handlers.onEdgeContextMenu
|
|
4391
|
+
},
|
|
4392
|
+
...editor.hasOnCanvasClick && {
|
|
4393
|
+
onPaneClick: handlers.onPanelClick
|
|
4394
|
+
},
|
|
4395
|
+
...editor.hasOnNodeClick && {
|
|
4396
|
+
onNodeClick: handlers.onNodeClick
|
|
4397
|
+
},
|
|
4398
|
+
...editor.hasOnEdgeClick && {
|
|
4399
|
+
onEdgeClick: handlers.onEdgeClick
|
|
4400
|
+
},
|
|
4401
|
+
children
|
|
4402
|
+
}
|
|
4403
|
+
)
|
|
4404
|
+
);
|
|
4405
|
+
}
|
|
4406
|
+
const isEquals = ({ children: _childrenA, ...a }, { children: _childrenB, ...b }) => deepEqual(a, b);
|
|
4407
|
+
const XYFlow = react.memo(XYFlowWrapper, isEquals);
|
|
4408
|
+
function LikeC4Diagram({
|
|
4409
|
+
view,
|
|
4410
|
+
className,
|
|
4411
|
+
fitView = true,
|
|
4412
|
+
fitViewPadding = 0,
|
|
4413
|
+
colorMode,
|
|
4414
|
+
readonly = true,
|
|
4415
|
+
pannable = true,
|
|
4416
|
+
zoomable = true,
|
|
4417
|
+
nodesSelectable = true,
|
|
4418
|
+
nodesDraggable = !readonly,
|
|
4419
|
+
background = "dots",
|
|
4420
|
+
controls = false,
|
|
4421
|
+
disableHovercards = false,
|
|
4422
|
+
initialWidth,
|
|
4423
|
+
initialHeight,
|
|
4424
|
+
keepAspectRatio = false,
|
|
4425
|
+
...eventHandlers
|
|
4426
|
+
}) {
|
|
4427
|
+
const initialRef = react.useRef();
|
|
4428
|
+
if (!initialRef.current) {
|
|
4429
|
+
const initial = diagramViewToXYFlowData(view);
|
|
4430
|
+
initialRef.current = {
|
|
4431
|
+
defaultNodes: initial.nodes,
|
|
4432
|
+
defaultEdges: initial.edges,
|
|
4433
|
+
initialWidth: initialWidth ?? view.width,
|
|
4434
|
+
initialHeight: initialHeight ?? view.height
|
|
4435
|
+
};
|
|
4436
|
+
}
|
|
4437
|
+
const isBgWithPattern = background !== "transparent" && background !== "solid";
|
|
4438
|
+
const isNodeInteractive = nodesDraggable || nodesSelectable || !!eventHandlers.onNavigateTo || !!eventHandlers.onNavigateTo;
|
|
4439
|
+
return /* @__PURE__ */ jsxRuntime.jsx(EnsureMantine, { colorMode, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4440
|
+
react$1.ReactFlowProvider,
|
|
4441
|
+
{
|
|
4442
|
+
fitView,
|
|
4443
|
+
...initialRef.current,
|
|
4444
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4445
|
+
DiagramStateProvider,
|
|
4446
|
+
{
|
|
4447
|
+
isNodeInteractive,
|
|
4448
|
+
view,
|
|
4449
|
+
fitViewPadding,
|
|
4450
|
+
readonly,
|
|
4451
|
+
disableHovercards,
|
|
4452
|
+
eventHandlers,
|
|
4453
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(XYFlowEventHandlers, { eventHandlers, children: [
|
|
4454
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4455
|
+
KeepAspectRatio,
|
|
4456
|
+
{
|
|
4457
|
+
enabled: keepAspectRatio,
|
|
4458
|
+
width: view.width,
|
|
4459
|
+
height: view.height,
|
|
4460
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4461
|
+
XYFlow,
|
|
4462
|
+
{
|
|
4463
|
+
className: clsx(
|
|
4464
|
+
className,
|
|
4465
|
+
scope,
|
|
4466
|
+
cssReactFlow,
|
|
4467
|
+
controls === false && cssNoControls,
|
|
4468
|
+
pannable !== true && cssDisablePan,
|
|
4469
|
+
background === "transparent" && cssTransparentBg
|
|
4470
|
+
),
|
|
4471
|
+
defaultNodes: initialRef.current.defaultNodes,
|
|
4472
|
+
defaultEdges: initialRef.current.defaultEdges,
|
|
4473
|
+
readonly,
|
|
4474
|
+
nodesDraggable,
|
|
4475
|
+
nodesSelectable,
|
|
4476
|
+
pannable,
|
|
4477
|
+
zoomable,
|
|
4478
|
+
fitView,
|
|
4479
|
+
colorMode,
|
|
4480
|
+
fitViewPadding,
|
|
4481
|
+
children: [
|
|
4482
|
+
isBgWithPattern && /* @__PURE__ */ jsxRuntime.jsx(XYFlowBackground, { background }),
|
|
4483
|
+
controls && /* @__PURE__ */ jsxRuntime.jsx(react$1.Controls, {}),
|
|
4484
|
+
readonly !== true && /* @__PURE__ */ jsxRuntime.jsx(OptionsPanel2, {}),
|
|
4485
|
+
fitView && /* @__PURE__ */ jsxRuntime.jsx(FitViewOnDiagramChange, {})
|
|
4486
|
+
]
|
|
4487
|
+
}
|
|
4488
|
+
)
|
|
4489
|
+
}
|
|
4490
|
+
),
|
|
4491
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4492
|
+
UpdateOnDiagramChange,
|
|
4493
|
+
{
|
|
4494
|
+
view,
|
|
4495
|
+
nodesDraggable
|
|
4496
|
+
}
|
|
4497
|
+
)
|
|
4498
|
+
] })
|
|
4499
|
+
}
|
|
4500
|
+
)
|
|
4501
|
+
}
|
|
4502
|
+
) });
|
|
4503
|
+
}
|
|
4504
|
+
function StaticLikeC4Diagram({
|
|
4505
|
+
view,
|
|
4506
|
+
fitView = true,
|
|
4507
|
+
fitViewPadding = 0,
|
|
4508
|
+
background = "transparent",
|
|
4509
|
+
...rest
|
|
4510
|
+
}) {
|
|
4511
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4512
|
+
LikeC4Diagram,
|
|
4513
|
+
{
|
|
4514
|
+
view,
|
|
4515
|
+
readonly: true,
|
|
4516
|
+
fitView,
|
|
4517
|
+
fitViewPadding,
|
|
4518
|
+
pannable: false,
|
|
4519
|
+
zoomable: false,
|
|
4520
|
+
controls: false,
|
|
4521
|
+
background,
|
|
4522
|
+
disableHovercards: true,
|
|
4523
|
+
nodesSelectable: false,
|
|
4524
|
+
nodesDraggable: false,
|
|
4525
|
+
...rest
|
|
4526
|
+
}
|
|
4527
|
+
);
|
|
4528
|
+
}
|
|
4529
|
+
function EmbeddedLikeC4DiagramCmp({
|
|
4530
|
+
viewId,
|
|
4531
|
+
views,
|
|
4532
|
+
colorMode
|
|
4533
|
+
}) {
|
|
4534
|
+
const [isOpened, toggleOpened] = useToggle(false);
|
|
4535
|
+
const [browserViewId, setBrowserViewId] = react.useState(viewId);
|
|
4536
|
+
const view = views[viewId];
|
|
4537
|
+
core$1.invariant(view, `View with id ${viewId} not found`);
|
|
4538
|
+
const browserView = views[browserViewId];
|
|
4539
|
+
core$1.invariant(browserView, `View with id ${browserViewId} not found`);
|
|
4540
|
+
const closeBrowser = () => {
|
|
4541
|
+
toggleOpened(false);
|
|
4542
|
+
setBrowserViewId(viewId);
|
|
4543
|
+
};
|
|
4544
|
+
useUpdateEffect(closeBrowser, [viewId]);
|
|
4545
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(EnsureMantine, { colorMode, children: [
|
|
4546
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4547
|
+
KeepAspectRatio,
|
|
4548
|
+
{
|
|
4549
|
+
enabled: true,
|
|
4550
|
+
height: view.height,
|
|
4551
|
+
width: view.width,
|
|
4552
|
+
onClick: (e) => {
|
|
4553
|
+
e.stopPropagation();
|
|
4554
|
+
toggleOpened(true);
|
|
4555
|
+
},
|
|
4556
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4557
|
+
StaticLikeC4Diagram,
|
|
4558
|
+
{
|
|
4559
|
+
colorMode,
|
|
4560
|
+
view,
|
|
4561
|
+
fitView: true,
|
|
4562
|
+
fitViewPadding: 0.01,
|
|
4563
|
+
background: "transparent",
|
|
4564
|
+
keepAspectRatio: false
|
|
4565
|
+
}
|
|
4566
|
+
)
|
|
4567
|
+
}
|
|
4568
|
+
),
|
|
4569
|
+
/* @__PURE__ */ jsxRuntime.jsxs(core.Modal.Root, { opened: isOpened, onClose: closeBrowser, fullScreen: true, children: [
|
|
4570
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Modal.Overlay, { blur: 16 }),
|
|
4571
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Modal.Content, { className: modalContent, children: /* @__PURE__ */ jsxRuntime.jsxs(core.Modal.Body, { className: modalBody, children: [
|
|
4572
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Box, { className: modalHeader, children: /* @__PURE__ */ jsxRuntime.jsx(core.Title, { order: 4, children: browserView.title || browserView.id }) }),
|
|
4573
|
+
isOpened && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4574
|
+
LikeC4Diagram,
|
|
4575
|
+
{
|
|
4576
|
+
readonly: true,
|
|
4577
|
+
view: browserView,
|
|
4578
|
+
colorMode,
|
|
4579
|
+
background: "transparent",
|
|
4580
|
+
fitViewPadding: 0.09,
|
|
4581
|
+
onCanvasDblClick: closeBrowser,
|
|
4582
|
+
onNavigateTo: ({ event, element }) => {
|
|
4583
|
+
event.stopPropagation();
|
|
4584
|
+
setBrowserViewId(element.navigateTo);
|
|
4585
|
+
}
|
|
4586
|
+
}
|
|
4587
|
+
),
|
|
4588
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Box, { className: modalCloseButtonBox, children: /* @__PURE__ */ jsxRuntime.jsx(core.CloseButton, { className: modalCloseButton, onClick: closeBrowser }) })
|
|
4589
|
+
] }) })
|
|
4590
|
+
] })
|
|
4591
|
+
] });
|
|
4592
|
+
}
|
|
4593
|
+
const EmbeddedLikeC4Diagram = react.memo(EmbeddedLikeC4DiagramCmp, shallowEqual);
|
|
4594
|
+
exports.EmbeddedLikeC4Diagram = EmbeddedLikeC4Diagram;
|
|
4595
|
+
exports.LikeC4Diagram = LikeC4Diagram;
|
|
4596
|
+
exports.StaticLikeC4Diagram = StaticLikeC4Diagram;
|