nimbus-docs 0.1.7 → 0.1.8
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/README.md +1 -1
- package/dist/cli/index.js +16 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/content.d.ts +62 -6
- package/dist/content.d.ts.map +1 -1
- package/dist/content.js +11 -5
- package/dist/content.js.map +1 -1
- package/dist/{diagnostic-C6OaBe_o.d.ts → diagnostic-ewiZxpSO.d.ts} +4 -1
- package/dist/diagnostic-ewiZxpSO.d.ts.map +1 -0
- package/dist/index.d.ts +52 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +349 -159
- package/dist/index.js.map +1 -1
- package/dist/react.d.ts +164 -19
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +290 -50
- package/dist/react.js.map +1 -1
- package/dist/{rules-DnAP-j89.js → rules-B7o0k3TA.js} +249 -2
- package/dist/rules-B7o0k3TA.js.map +1 -0
- package/dist/schemas.d.ts +85 -2
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +32 -6
- package/dist/schemas.js.map +1 -1
- package/dist/strict-keys-fbKKxxKL.js +141 -0
- package/dist/strict-keys-fbKKxxKL.js.map +1 -0
- package/dist/types.d.ts +49 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +12 -11
- package/CHANGELOG.md +0 -19
- package/dist/diagnostic-C6OaBe_o.d.ts.map +0 -1
- package/dist/rules-DnAP-j89.js.map +0 -1
- package/dist/strict-keys-BiXiT3pq.js +0 -35
- package/dist/strict-keys-BiXiT3pq.js.map +0 -1
package/dist/react.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Component, createContext, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useReducer, useRef, useState } from "react";
|
|
1
|
+
import { Component, createContext, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useReducer, useRef, useState, useSyncExternalStore } from "react";
|
|
2
2
|
import { clsx } from "clsx";
|
|
3
3
|
import { twMerge } from "tailwind-merge";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -30,8 +30,14 @@ var DiagramRegistry = class {
|
|
|
30
30
|
this.notify();
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Pause everything when at least one diagram is unpaused; resume
|
|
35
|
+
* everything otherwise. A naive per-entry toggle would *invert* mixed
|
|
36
|
+
* states — resuming the diagrams a reader had deliberately paused.
|
|
37
|
+
*/
|
|
33
38
|
toggleAll() {
|
|
34
|
-
|
|
39
|
+
const anyUnpaused = [...this.entries.values()].some((e) => !e.userPaused());
|
|
40
|
+
for (const entry of this.entries.values()) entry.setPaused(anyUnpaused);
|
|
35
41
|
}
|
|
36
42
|
count = () => this.entries.size;
|
|
37
43
|
getVersion = () => this.version;
|
|
@@ -71,6 +77,10 @@ function reducer(state, event) {
|
|
|
71
77
|
...state,
|
|
72
78
|
userPaused: !state.userPaused
|
|
73
79
|
};
|
|
80
|
+
case "SET_PAUSED": return state.userPaused === event.paused ? state : {
|
|
81
|
+
...state,
|
|
82
|
+
userPaused: event.paused
|
|
83
|
+
};
|
|
74
84
|
}
|
|
75
85
|
}
|
|
76
86
|
function derivePhase(state, reducedMotionMode, pauseWhenOffscreen) {
|
|
@@ -260,7 +270,13 @@ function DiagramRoot(props) {
|
|
|
260
270
|
};
|
|
261
271
|
}, []);
|
|
262
272
|
const toggle = useCallback(() => dispatch({ type: "TOGGLE" }), []);
|
|
263
|
-
const reset = useCallback(() =>
|
|
273
|
+
const reset = useCallback(() => {
|
|
274
|
+
setResetKey((k) => k + 1);
|
|
275
|
+
dispatch({
|
|
276
|
+
type: "SET_PAUSED",
|
|
277
|
+
paused: false
|
|
278
|
+
});
|
|
279
|
+
}, []);
|
|
264
280
|
const handleKeyDown = useCallback((event) => {
|
|
265
281
|
if (!keyboard) return;
|
|
266
282
|
if (isInteractiveTarget(event.target)) return;
|
|
@@ -276,12 +292,18 @@ function DiagramRoot(props) {
|
|
|
276
292
|
toggle,
|
|
277
293
|
reset
|
|
278
294
|
]);
|
|
295
|
+
const userPausedRef = useRef(state.userPaused);
|
|
296
|
+
userPausedRef.current = state.userPaused;
|
|
279
297
|
useEffect(() => {
|
|
280
298
|
return diagramRegistry.register({
|
|
281
299
|
id,
|
|
282
|
-
|
|
300
|
+
setPaused: (paused) => dispatch({
|
|
301
|
+
type: "SET_PAUSED",
|
|
302
|
+
paused
|
|
303
|
+
}),
|
|
304
|
+
userPaused: () => userPausedRef.current
|
|
283
305
|
});
|
|
284
|
-
}, [id
|
|
306
|
+
}, [id]);
|
|
285
307
|
const phase = derivePhase(state, reducedMotionMode, pauseWhenOffscreen);
|
|
286
308
|
const playing = phase === "playing";
|
|
287
309
|
const reducedMotionEffective = reducedMotionMode === "respect" ? state.reducedMotion : false;
|
|
@@ -324,7 +346,8 @@ function DiagramRoot(props) {
|
|
|
324
346
|
"data-tab-visible": String(state.tabVisible),
|
|
325
347
|
"data-reduced-motion": String(reducedMotionEffective),
|
|
326
348
|
"aria-label": label,
|
|
327
|
-
role: "region",
|
|
349
|
+
role: label ? "region" : void 0,
|
|
350
|
+
tabIndex: keyboard ? 0 : void 0,
|
|
328
351
|
onKeyDown: handleKeyDown,
|
|
329
352
|
className: cn("flex flex-col", className),
|
|
330
353
|
children: [/* @__PURE__ */ jsx("span", {
|
|
@@ -349,14 +372,27 @@ const Diagram = DiagramRoot;
|
|
|
349
372
|
* automatically when any gate fails.
|
|
350
373
|
*
|
|
351
374
|
* Steps may carry a `when(ctx)` predicate that filters them out for a
|
|
352
|
-
* given cycle
|
|
353
|
-
*
|
|
354
|
-
* `context`.
|
|
375
|
+
* given cycle, and a `data` payload surfaced while the step holds. Mode
|
|
376
|
+
* toggles, branches, alternating loops — anything cycle-dependent —
|
|
377
|
+
* composes via the predicate plus user-supplied `context`.
|
|
378
|
+
*
|
|
379
|
+
* Two run modes:
|
|
380
|
+
* - `autoplay: true` (default) — ambient looping animation. Freezes under
|
|
381
|
+
* reduced motion (`data` reads `null`).
|
|
382
|
+
* - `autoplay: false` — idle until `start()`. Started runs are
|
|
383
|
+
* user-initiated *function*, not decoration: they keep advancing under
|
|
384
|
+
* reduced motion (gate your CSS transition durations card-side), and a
|
|
385
|
+
* `start()` while the page is paused arms as soon as play resumes.
|
|
386
|
+
*
|
|
387
|
+
* The scheduler depends on the current step's *values* (id, hold), not
|
|
388
|
+
* on `steps` / `context` identity — inline literals are safe and won't
|
|
389
|
+
* re-arm the hold timer under frequent re-renders.
|
|
355
390
|
*/
|
|
356
|
-
function usePhase({ steps, context, loop = true }) {
|
|
391
|
+
function usePhase({ steps, context, loop = true, autoplay = true }) {
|
|
357
392
|
const ctx = useDiagramOrDefault("usePhase");
|
|
358
393
|
const [cycle, setCycle] = useState(0);
|
|
359
394
|
const [index, setIndex] = useState(0);
|
|
395
|
+
const [running, setRunning] = useState(autoplay);
|
|
360
396
|
const sequence = useMemo(() => {
|
|
361
397
|
const seq = [];
|
|
362
398
|
let prev = "";
|
|
@@ -379,53 +415,77 @@ function usePhase({ steps, context, loop = true }) {
|
|
|
379
415
|
steps
|
|
380
416
|
]);
|
|
381
417
|
const currentStep = sequence[index] ?? sequence[sequence.length - 1] ?? null;
|
|
382
|
-
const currentId = currentStep?.id ?? "";
|
|
418
|
+
const currentId = running ? currentStep?.id ?? "" : "";
|
|
419
|
+
const currentHold = currentStep?.hold ?? null;
|
|
420
|
+
const advanceRef = useRef(() => {});
|
|
421
|
+
const sequenceRef = useRef(sequence);
|
|
422
|
+
const runningRef = useRef(running);
|
|
383
423
|
useEffect(() => {
|
|
384
|
-
|
|
385
|
-
if (ctx.reducedMotion) return;
|
|
386
|
-
if (!currentStep || sequence.length === 0) return;
|
|
387
|
-
const t = setTimeout(() => {
|
|
424
|
+
advanceRef.current = () => {
|
|
388
425
|
if (index + 1 >= sequence.length) {
|
|
389
426
|
if (loop) {
|
|
390
427
|
setCycle((c) => c + 1);
|
|
391
428
|
setIndex(0);
|
|
429
|
+
} else if (!autoplay) {
|
|
430
|
+
setCycle((c) => c + 1);
|
|
431
|
+
setIndex(0);
|
|
432
|
+
setRunning(false);
|
|
392
433
|
}
|
|
393
434
|
} else setIndex((i) => i + 1);
|
|
394
|
-
}
|
|
435
|
+
};
|
|
436
|
+
sequenceRef.current = sequence;
|
|
437
|
+
runningRef.current = running;
|
|
438
|
+
});
|
|
439
|
+
const hasSteps = steps.length > 0;
|
|
440
|
+
useEffect(() => {
|
|
441
|
+
if (!running) return;
|
|
442
|
+
if (!ctx.playing) return;
|
|
443
|
+
if (ctx.reducedMotion && autoplay) return;
|
|
444
|
+
if (currentHold === null) {
|
|
445
|
+
if (!hasSteps) return;
|
|
446
|
+
const t = setTimeout(() => advanceRef.current(), 0);
|
|
447
|
+
return () => clearTimeout(t);
|
|
448
|
+
}
|
|
449
|
+
const t = setTimeout(() => advanceRef.current(), currentHold);
|
|
395
450
|
return () => clearTimeout(t);
|
|
396
451
|
}, [
|
|
397
452
|
index,
|
|
398
453
|
cycle,
|
|
454
|
+
running,
|
|
455
|
+
autoplay,
|
|
399
456
|
ctx.playing,
|
|
400
457
|
ctx.reducedMotion,
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
458
|
+
currentId,
|
|
459
|
+
currentHold,
|
|
460
|
+
hasSteps
|
|
404
461
|
]);
|
|
462
|
+
const start = useCallback(() => {
|
|
463
|
+
if (runningRef.current) return;
|
|
464
|
+
setIndex(0);
|
|
465
|
+
setRunning(true);
|
|
466
|
+
}, []);
|
|
467
|
+
const advance = useCallback(() => advanceRef.current(), []);
|
|
468
|
+
const goto = useCallback((id) => {
|
|
469
|
+
const i = sequenceRef.current.findIndex((s) => s.id === id);
|
|
470
|
+
if (i < 0) return;
|
|
471
|
+
setIndex(i);
|
|
472
|
+
setRunning(true);
|
|
473
|
+
}, []);
|
|
474
|
+
const reset = useCallback(() => {
|
|
475
|
+
setCycle(0);
|
|
476
|
+
setIndex(0);
|
|
477
|
+
setRunning(autoplay);
|
|
478
|
+
}, [autoplay]);
|
|
405
479
|
return {
|
|
406
480
|
current: currentId,
|
|
407
481
|
index,
|
|
408
482
|
cycle,
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
} else setIndex((i) => i + 1);
|
|
416
|
-
}, [
|
|
417
|
-
index,
|
|
418
|
-
sequence.length,
|
|
419
|
-
loop
|
|
420
|
-
]),
|
|
421
|
-
goto: useCallback((id) => {
|
|
422
|
-
const i = sequence.findIndex((s) => s.id === id);
|
|
423
|
-
if (i >= 0) setIndex(i);
|
|
424
|
-
}, [sequence]),
|
|
425
|
-
reset: useCallback(() => {
|
|
426
|
-
setCycle(0);
|
|
427
|
-
setIndex(0);
|
|
428
|
-
}, [])
|
|
483
|
+
data: running && currentStep && !(ctx.reducedMotion && autoplay) ? currentStep.data ?? null : null,
|
|
484
|
+
running,
|
|
485
|
+
start,
|
|
486
|
+
advance,
|
|
487
|
+
goto,
|
|
488
|
+
reset
|
|
429
489
|
};
|
|
430
490
|
}
|
|
431
491
|
|
|
@@ -434,8 +494,7 @@ function usePhase({ steps, context, loop = true }) {
|
|
|
434
494
|
/**
|
|
435
495
|
* DOM rect + optional selector callback. The selector receives the
|
|
436
496
|
* observed element and its rect, and returns whatever derived geometry
|
|
437
|
-
* the author needs (NodeRect, EdgeData, etc.).
|
|
438
|
-
* `useWeldedMeasure` pattern.
|
|
497
|
+
* the author needs (NodeRect, EdgeData, etc.).
|
|
439
498
|
*
|
|
440
499
|
* For multi-element measurements (e.g. measuring a container plus 5
|
|
441
500
|
* child nodes), pass the container ref and read the other refs from
|
|
@@ -452,9 +511,9 @@ function useMeasure(ref, selector, options = {}) {
|
|
|
452
511
|
const selectorRef = useRef(selector);
|
|
453
512
|
selectorRef.current = selector;
|
|
454
513
|
const sampleRef = useRef(() => {});
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
514
|
+
const boundElRef = useRef(null);
|
|
515
|
+
const unbindRef = useRef(null);
|
|
516
|
+
const bind = (el) => {
|
|
458
517
|
const sample = (r) => {
|
|
459
518
|
setRect(r);
|
|
460
519
|
const s = selectorRef.current;
|
|
@@ -463,18 +522,39 @@ function useMeasure(ref, selector, options = {}) {
|
|
|
463
522
|
sampleRef.current = () => {
|
|
464
523
|
sample(el.getBoundingClientRect());
|
|
465
524
|
};
|
|
525
|
+
let cancelled = false;
|
|
526
|
+
el.ownerDocument.fonts?.ready.then(() => {
|
|
527
|
+
if (!cancelled) sampleRef.current();
|
|
528
|
+
});
|
|
466
529
|
const win = el.ownerDocument.defaultView ?? window;
|
|
467
530
|
if (typeof win.ResizeObserver === "undefined") {
|
|
468
531
|
sampleRef.current();
|
|
469
|
-
return
|
|
532
|
+
return () => {
|
|
533
|
+
cancelled = true;
|
|
534
|
+
};
|
|
470
535
|
}
|
|
471
|
-
const ro = new win.ResizeObserver((
|
|
472
|
-
|
|
536
|
+
const ro = new win.ResizeObserver(() => {
|
|
537
|
+
sample(el.getBoundingClientRect());
|
|
473
538
|
});
|
|
474
539
|
ro.observe(el);
|
|
475
540
|
sampleRef.current();
|
|
476
|
-
return () =>
|
|
477
|
-
|
|
541
|
+
return () => {
|
|
542
|
+
cancelled = true;
|
|
543
|
+
ro.disconnect();
|
|
544
|
+
};
|
|
545
|
+
};
|
|
546
|
+
useLayoutEffect(() => {
|
|
547
|
+
const el = ref.current;
|
|
548
|
+
if (el === boundElRef.current) return;
|
|
549
|
+
unbindRef.current?.();
|
|
550
|
+
boundElRef.current = el;
|
|
551
|
+
unbindRef.current = el ? bind(el) : null;
|
|
552
|
+
});
|
|
553
|
+
useLayoutEffect(() => () => {
|
|
554
|
+
unbindRef.current?.();
|
|
555
|
+
unbindRef.current = null;
|
|
556
|
+
boundElRef.current = null;
|
|
557
|
+
}, []);
|
|
478
558
|
useLayoutEffect(() => {
|
|
479
559
|
sampleRef.current();
|
|
480
560
|
}, deps);
|
|
@@ -538,5 +618,165 @@ function useTabIndicator(containerRef, getTab, activeId) {
|
|
|
538
618
|
}
|
|
539
619
|
|
|
540
620
|
//#endregion
|
|
541
|
-
|
|
621
|
+
//#region src/react/hooks/use-ref-setters.ts
|
|
622
|
+
/**
|
|
623
|
+
* Stable per-id ref callbacks for a refs map — the ergonomic half of the
|
|
624
|
+
* "refs map + setter factory" pattern. Instead of N individual `useRef`s
|
|
625
|
+
* and N inline `ref={(el) => …}` arrows (which churn refs every render),
|
|
626
|
+
* keep one map and hand each element a cached callback:
|
|
627
|
+
*
|
|
628
|
+
* ```tsx
|
|
629
|
+
* const nodeRefs = useRef<Partial<Record<NodeId, HTMLDivElement | null>>>({});
|
|
630
|
+
* const setNode = useRefSetters(nodeRefs);
|
|
631
|
+
*
|
|
632
|
+
* <div ref={setNode("prompt")}>Prompt</div>
|
|
633
|
+
* <div ref={setNode("model")}>Model</div>
|
|
634
|
+
* ```
|
|
635
|
+
*
|
|
636
|
+
* Measurement stays caller-side (read `refs.current` inside a `useMeasure`
|
|
637
|
+
* selector) — this hook owns only the ref plumbing.
|
|
638
|
+
*/
|
|
639
|
+
function useRefSetters(refs) {
|
|
640
|
+
const cache = useRef(/* @__PURE__ */ new Map());
|
|
641
|
+
return (id) => {
|
|
642
|
+
let cb = cache.current.get(id);
|
|
643
|
+
if (!cb) {
|
|
644
|
+
cb = (el) => {
|
|
645
|
+
refs.current[id] = el;
|
|
646
|
+
};
|
|
647
|
+
cache.current.set(id, cb);
|
|
648
|
+
}
|
|
649
|
+
return cb;
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
//#endregion
|
|
654
|
+
//#region src/react/hooks/use-media-query.ts
|
|
655
|
+
/**
|
|
656
|
+
* Reactive `window.matchMedia` subscription, SSR-safe.
|
|
657
|
+
*
|
|
658
|
+
* The server snapshot returns `defaultValue` (default `false`), so static
|
|
659
|
+
* builds render the no-match branch and hydrate without mismatch warnings;
|
|
660
|
+
* the first client render corrects it if the query matches.
|
|
661
|
+
*
|
|
662
|
+
* ```ts
|
|
663
|
+
* const isMobile = useMediaQuery("(max-width: 640px)");
|
|
664
|
+
* ```
|
|
665
|
+
*/
|
|
666
|
+
function useMediaQuery(query, defaultValue = false) {
|
|
667
|
+
return useSyncExternalStore(useCallback((onChange) => {
|
|
668
|
+
const mq = window.matchMedia(query);
|
|
669
|
+
mq.addEventListener("change", onChange);
|
|
670
|
+
return () => mq.removeEventListener("change", onChange);
|
|
671
|
+
}, [query]), () => window.matchMedia(query).matches, () => defaultValue);
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
//#endregion
|
|
675
|
+
//#region src/react/geometry.ts
|
|
676
|
+
/** Anchor point on a rect edge. `frac` runs 0→1 from top/left. */
|
|
677
|
+
function edgePoint(rect, side, frac = .5) {
|
|
678
|
+
if (side === "top") return {
|
|
679
|
+
x: rect.l + rect.w * frac,
|
|
680
|
+
y: rect.t
|
|
681
|
+
};
|
|
682
|
+
if (side === "bottom") return {
|
|
683
|
+
x: rect.l + rect.w * frac,
|
|
684
|
+
y: rect.t + rect.h
|
|
685
|
+
};
|
|
686
|
+
if (side === "left") return {
|
|
687
|
+
x: rect.l,
|
|
688
|
+
y: rect.t + rect.h * frac
|
|
689
|
+
};
|
|
690
|
+
return {
|
|
691
|
+
x: rect.l + rect.w,
|
|
692
|
+
y: rect.t + rect.h * frac
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
function straightPath(from, to, arrowOffset) {
|
|
696
|
+
const dx = Math.abs(to.x - from.x);
|
|
697
|
+
if (Math.abs(to.y - from.y) < 2) {
|
|
698
|
+
const dir = to.x > from.x ? 1 : -1;
|
|
699
|
+
return `M ${from.x},${from.y} L ${to.x - dir * arrowOffset},${to.y}`;
|
|
700
|
+
}
|
|
701
|
+
if (dx < 2) {
|
|
702
|
+
const dir = to.y > from.y ? 1 : -1;
|
|
703
|
+
return `M ${from.x},${from.y} L ${to.x},${to.y - dir * arrowOffset}`;
|
|
704
|
+
}
|
|
705
|
+
return `M ${from.x},${from.y} L ${to.x},${to.y}`;
|
|
706
|
+
}
|
|
707
|
+
function elbowPath(from, to, r, arrowOffset) {
|
|
708
|
+
const dx = to.x - from.x;
|
|
709
|
+
const dy = to.y - from.y;
|
|
710
|
+
const corner = Math.abs(dx) > Math.abs(dy) ? {
|
|
711
|
+
x: to.x,
|
|
712
|
+
y: from.y
|
|
713
|
+
} : {
|
|
714
|
+
x: from.x,
|
|
715
|
+
y: to.y
|
|
716
|
+
};
|
|
717
|
+
const dx1 = Math.sign(corner.x - from.x);
|
|
718
|
+
const dy1 = Math.sign(corner.y - from.y);
|
|
719
|
+
const dx2 = Math.sign(to.x - corner.x);
|
|
720
|
+
const dy2 = Math.sign(to.y - corner.y);
|
|
721
|
+
const seg1Len = Math.abs(corner.x - from.x) + Math.abs(corner.y - from.y);
|
|
722
|
+
const seg2Len = Math.abs(to.x - corner.x) + Math.abs(to.y - corner.y);
|
|
723
|
+
const rr = Math.max(2, Math.min(r, seg1Len / 2, seg2Len / 2));
|
|
724
|
+
const preX = corner.x - dx1 * rr;
|
|
725
|
+
const preY = corner.y - dy1 * rr;
|
|
726
|
+
const postX = corner.x + dx2 * rr;
|
|
727
|
+
const postY = corner.y + dy2 * rr;
|
|
728
|
+
const endX = to.x - dx2 * arrowOffset;
|
|
729
|
+
const endY = to.y - dy2 * arrowOffset;
|
|
730
|
+
return `M ${from.x},${from.y} L ${preX},${preY} Q ${corner.x},${corner.y} ${postX},${postY} L ${endX},${endY}`;
|
|
731
|
+
}
|
|
732
|
+
function vSplitPath(from, to, r) {
|
|
733
|
+
if (Math.abs(from.x - to.x) < 1) return `M ${from.x},${from.y} L ${to.x},${to.y}`;
|
|
734
|
+
const midY = (from.y + to.y) / 2;
|
|
735
|
+
const sx = Math.sign(to.x - from.x);
|
|
736
|
+
const sy1 = Math.sign(midY - from.y);
|
|
737
|
+
const sy2 = Math.sign(to.y - midY);
|
|
738
|
+
const rr = Math.min(r, Math.abs(midY - from.y), Math.abs(to.x - from.x) / 2, Math.abs(to.y - midY));
|
|
739
|
+
return [
|
|
740
|
+
`M ${from.x},${from.y}`,
|
|
741
|
+
`L ${from.x},${midY - rr * sy1}`,
|
|
742
|
+
`Q ${from.x},${midY} ${from.x + rr * sx},${midY}`,
|
|
743
|
+
`L ${to.x - rr * sx},${midY}`,
|
|
744
|
+
`Q ${to.x},${midY} ${to.x},${midY + rr * sy2}`,
|
|
745
|
+
`L ${to.x},${to.y}`
|
|
746
|
+
].join(" ");
|
|
747
|
+
}
|
|
748
|
+
/** Build an SVG path string between two points using the given route. */
|
|
749
|
+
function routeEdge(from, to, route = "auto", options = {}) {
|
|
750
|
+
const arrowOffset = options.arrowOffset ?? 6;
|
|
751
|
+
if (route === "vSplit") return vSplitPath(from, to, options.radius ?? 6);
|
|
752
|
+
if (route === "straight") return straightPath(from, to, arrowOffset);
|
|
753
|
+
if (route === "elbow") return elbowPath(from, to, options.radius ?? 10, arrowOffset);
|
|
754
|
+
return Math.abs(from.x - to.x) < 2 || Math.abs(from.y - to.y) < 2 ? straightPath(from, to, arrowOffset) : elbowPath(from, to, options.radius ?? 10, arrowOffset);
|
|
755
|
+
}
|
|
756
|
+
/**
|
|
757
|
+
* Resolve declarative edge specs against a map of measured rects.
|
|
758
|
+
* Specs whose endpoints aren't in `rects` yet (unmounted nodes,
|
|
759
|
+
* first-paint gaps) are skipped rather than rendered degenerate.
|
|
760
|
+
*/
|
|
761
|
+
function resolveEdges(specs, rects, options = {}) {
|
|
762
|
+
const out = [];
|
|
763
|
+
for (const spec of specs) {
|
|
764
|
+
const fromRect = rects[spec.from[0]];
|
|
765
|
+
const toRect = rects[spec.to[0]];
|
|
766
|
+
if (!fromRect || !toRect) continue;
|
|
767
|
+
const from = edgePoint(fromRect, spec.from[1], spec.from[2] ?? .5);
|
|
768
|
+
const to = edgePoint(toRect, spec.to[1], spec.to[2] ?? .5);
|
|
769
|
+
out.push({
|
|
770
|
+
id: spec.id,
|
|
771
|
+
from,
|
|
772
|
+
to,
|
|
773
|
+
d: routeEdge(from, to, spec.route ?? "auto", options),
|
|
774
|
+
ghost: spec.ghost
|
|
775
|
+
});
|
|
776
|
+
}
|
|
777
|
+
return out;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
//#endregion
|
|
781
|
+
export { Diagram, cn, diagramRegistry, edgePoint, resolveEdges, routeEdge, useDiagram, useDiagramOrDefault, useMeasure, useMediaQuery, usePhase, useRefSetters, useTabIndicator };
|
|
542
782
|
//# sourceMappingURL=react.js.map
|