@markdy/renderer-dom 0.7.10 → 0.7.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.
Files changed (2) hide show
  1. package/dist/index.js +204 -2
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -367,6 +367,66 @@ function createActorEl(name, def, assetDefs, assetOverrides) {
367
367
  el = createFigureEl(def);
368
368
  break;
369
369
  }
370
+ case "service":
371
+ case "client":
372
+ case "db":
373
+ case "queue": {
374
+ const card = document.createElement("div");
375
+ const label = document.createElement("div");
376
+ label.textContent = def.args[0] ?? "";
377
+ Object.assign(label.style, {
378
+ fontFamily: "system-ui, -apple-system, sans-serif",
379
+ fontSize: `${def.size ?? 16}px`,
380
+ fontWeight: "600",
381
+ color: "#e2e8f0",
382
+ textAlign: "center",
383
+ lineHeight: "1.2",
384
+ pointerEvents: "none",
385
+ whiteSpace: "nowrap",
386
+ overflow: "hidden",
387
+ textOverflow: "ellipsis",
388
+ maxWidth: "100%"
389
+ });
390
+ Object.assign(card.style, {
391
+ width: "180px",
392
+ height: "84px",
393
+ boxSizing: "border-box",
394
+ border: "1px solid #475569",
395
+ background: "#0f172a",
396
+ display: "grid",
397
+ placeItems: "center",
398
+ padding: "10px 12px"
399
+ });
400
+ if (def.type === "service") {
401
+ card.style.borderRadius = "12px";
402
+ card.style.background = "linear-gradient(180deg, #1e293b 0%, #0f172a 100%)";
403
+ } else if (def.type === "client") {
404
+ const bar = document.createElement("div");
405
+ Object.assign(bar.style, {
406
+ position: "absolute",
407
+ top: "8px",
408
+ left: "8px",
409
+ right: "8px",
410
+ height: "8px",
411
+ borderRadius: "6px",
412
+ background: "#334155"
413
+ });
414
+ card.style.position = "relative";
415
+ card.style.borderRadius = "10px";
416
+ card.style.paddingTop = "20px";
417
+ card.appendChild(bar);
418
+ } else if (def.type === "db") {
419
+ card.style.borderRadius = "50% / 14%";
420
+ card.style.background = "linear-gradient(180deg, #334155 0%, #0f172a 70%)";
421
+ card.style.boxShadow = "inset 0 10px 0 rgba(226, 232, 240, 0.12)";
422
+ } else if (def.type === "queue") {
423
+ card.style.borderRadius = "8px";
424
+ card.style.boxShadow = "-6px -6px 0 rgba(30, 41, 59, 0.9), -12px -12px 0 rgba(15, 23, 42, 0.9)";
425
+ }
426
+ card.appendChild(label);
427
+ el = card;
428
+ break;
429
+ }
370
430
  default: {
371
431
  const div = document.createElement("div");
372
432
  div.style.width = "100px";
@@ -437,7 +497,22 @@ function buildAnimations(ast, actorEls, scene, assetOverrides, faceSwaps) {
437
497
  const el = actorEls.get(ev.actor);
438
498
  const s = states.get(ev.actor);
439
499
  if (!el || !s) continue;
440
- buildAction(ev, el, s, baseOpts, delayMs, durMs, ast, states, scene, assetOverrides, faceSwaps, anims, txFor(ev.actor));
500
+ buildAction(
501
+ ev,
502
+ el,
503
+ s,
504
+ baseOpts,
505
+ delayMs,
506
+ durMs,
507
+ ast,
508
+ states,
509
+ actorEls,
510
+ scene,
511
+ assetOverrides,
512
+ faceSwaps,
513
+ anims,
514
+ txFor(ev.actor)
515
+ );
441
516
  }
442
517
  return anims;
443
518
  }
@@ -541,8 +616,135 @@ function buildCameraAction(ev, scene, ast, baseOpts, anims, cameraState) {
541
616
  break;
542
617
  }
543
618
  }
544
- function buildAction(ev, el, s, baseOpts, delayMs, durMs, ast, states, scene, assetOverrides, faceSwaps, anims, txFn) {
619
+ var FLOW_STROKE_BY_ACTION = {
620
+ request: "#38bdf8",
621
+ response: "#a78bfa",
622
+ emit: "#f59e0b"
623
+ };
624
+ function actorSizeByType(type) {
625
+ switch (type) {
626
+ case "service":
627
+ case "client":
628
+ case "db":
629
+ case "queue":
630
+ return { width: 180, height: 84 };
631
+ case "box":
632
+ return { width: 100, height: 100 };
633
+ case "caption":
634
+ return { width: 260, height: 56 };
635
+ case "figure":
636
+ return { width: 120, height: 170 };
637
+ default:
638
+ return { width: 140, height: 42 };
639
+ }
640
+ }
641
+ function actorCenter(state, actorType) {
642
+ const { width, height } = actorSizeByType(actorType);
643
+ return {
644
+ x: state.x + width / 2,
645
+ y: state.y + height / 2
646
+ };
647
+ }
648
+ function ensureEdgeLayer(scene) {
649
+ const existing = scene.querySelector("svg[data-markdy-edge-layer='1']");
650
+ if (existing) return existing;
651
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
652
+ svg.setAttribute("data-markdy-edge-layer", "1");
653
+ Object.assign(svg.style, {
654
+ position: "absolute",
655
+ inset: "0",
656
+ width: "100%",
657
+ height: "100%",
658
+ overflow: "visible",
659
+ pointerEvents: "none",
660
+ zIndex: "95"
661
+ });
662
+ scene.appendChild(svg);
663
+ return svg;
664
+ }
665
+ function renderFlowEdge(ev, sourceState, targetState, sourceType, targetType, scene, baseOpts, anims) {
666
+ const styleToken = String(ev.params.style ?? "");
667
+ const isDashed = styleToken === "dashed" || styleToken === "fire_and_forget" || ev.action === "response";
668
+ const stroke = FLOW_STROKE_BY_ACTION[ev.action] ?? "#38bdf8";
669
+ const source = actorCenter(sourceState, sourceType);
670
+ const target = actorCenter(targetState, targetType);
671
+ const dx = target.x - source.x;
672
+ const dy = target.y - source.y;
673
+ const length = Math.max(1, Math.hypot(dx, dy));
674
+ const mx = source.x + dx / 2;
675
+ const my = source.y + dy / 2;
676
+ const pathD = `M ${source.x} ${source.y} L ${target.x} ${target.y}`;
677
+ const svg = ensureEdgeLayer(scene);
678
+ const group = document.createElementNS("http://www.w3.org/2000/svg", "g");
679
+ group.setAttribute("data-markdy-flow-edge", "1");
680
+ const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
681
+ path.setAttribute("d", pathD);
682
+ path.setAttribute("fill", "none");
683
+ path.setAttribute("stroke", stroke);
684
+ path.setAttribute("stroke-width", "2.5");
685
+ path.style.strokeDasharray = isDashed ? "8 6" : `${length}`;
686
+ path.style.strokeDashoffset = `${length}`;
687
+ group.appendChild(path);
688
+ const marker = document.createElementNS("http://www.w3.org/2000/svg", "circle");
689
+ marker.setAttribute("r", "3");
690
+ marker.setAttribute("fill", stroke);
691
+ marker.style.offsetPath = `path('${pathD}')`;
692
+ marker.style.offsetDistance = "0%";
693
+ marker.style.opacity = "0";
694
+ group.appendChild(marker);
695
+ const labelRaw = String(ev.params.label ?? "");
696
+ if (labelRaw) {
697
+ const label = labelRaw.length > 28 ? `${labelRaw.slice(0, 27)}\u2026` : labelRaw;
698
+ const labelEl = document.createElementNS("http://www.w3.org/2000/svg", "text");
699
+ labelEl.setAttribute("x", `${mx}`);
700
+ labelEl.setAttribute("y", `${my - 8}`);
701
+ labelEl.setAttribute("text-anchor", "middle");
702
+ labelEl.setAttribute("font-size", "12");
703
+ labelEl.setAttribute("fill", "#cbd5e1");
704
+ labelEl.textContent = label;
705
+ labelEl.setAttribute("data-full-label", labelRaw);
706
+ group.appendChild(labelEl);
707
+ }
708
+ svg.appendChild(group);
709
+ anims.push(path.animate([{ strokeDashoffset: length }, { strokeDashoffset: 0 }], baseOpts));
710
+ anims.push(
711
+ marker.animate(
712
+ [{ offsetDistance: "0%", opacity: 1 }, { offsetDistance: "100%", opacity: 1 }],
713
+ baseOpts
714
+ )
715
+ );
716
+ const fadeOutDelay = Number(baseOpts.delay ?? 0) + Number(baseOpts.duration ?? 0);
717
+ anims.push(
718
+ group.animate([{ opacity: 1 }, { opacity: 0 }], {
719
+ delay: fadeOutDelay,
720
+ duration: 140,
721
+ fill: "forwards"
722
+ })
723
+ );
724
+ }
725
+ function buildAction(ev, el, s, baseOpts, delayMs, durMs, ast, states, actorEls, scene, assetOverrides, faceSwaps, anims, txFn) {
545
726
  switch (ev.action) {
727
+ case "request":
728
+ case "response":
729
+ case "emit": {
730
+ const targetActorName = String(ev.params.to ?? "");
731
+ if (!targetActorName) break;
732
+ const targetState = states.get(targetActorName);
733
+ if (!targetState) break;
734
+ const sourceType = ast.actors[ev.actor]?.type ?? "box";
735
+ const targetType = ast.actors[targetActorName]?.type ?? "box";
736
+ renderFlowEdge(
737
+ ev,
738
+ s,
739
+ targetState,
740
+ sourceType,
741
+ targetType,
742
+ scene,
743
+ baseOpts,
744
+ anims
745
+ );
746
+ break;
747
+ }
546
748
  // ── move ────────────────────────────────────────────────────────────────
547
749
  case "move": {
548
750
  const toArr = ev.params.to;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markdy/renderer-dom",
3
- "version": "0.7.10",
3
+ "version": "0.7.11",
4
4
  "description": "Web Animations API renderer for MarkdyScript scenes.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -43,7 +43,7 @@
43
43
  "access": "public"
44
44
  },
45
45
  "dependencies": {
46
- "@markdy/core": "0.7.10"
46
+ "@markdy/core": "0.7.11"
47
47
  },
48
48
  "devDependencies": {
49
49
  "jsdom": "^29.1.1",