@typeonce/effect-machine-devtools 0.31.0 → 0.31.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ :root{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;color:#e8eaed;font-synthesis:none;text-rendering:optimizelegibility;--surface:#0f1114;--surface-raised:#14171b;--line:#292d34;--line-soft:#20242a;--muted:#8e949e;--accent:#75a7ff;--accent-bg:#4b7dff2e;--orange:#f0a35b;--danger:#d8757b;--danger-strong:#efafb3;--danger-background:#241416;--danger-border:#945057;--chart-surface:#171c23;--chart-surface-raised:#1a2028;--chart-border:#3a4551;--chart-border-soft:#303944;--chart-text:#d5dbe3;--chart-text-muted:#a2acb8;--chart-completion:#82b4c8;--chart-failure:var(--danger);--chart-source:#d18f68;--chart-target:#78a9c9;background:#0b0c0e;font-family:Inter,ui-sans-serif,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}*{box-sizing:border-box}html,body,#app{min-width:320px;height:100%;margin:0}body{background:#0b0c0e}.devtools-shell{flex-direction:column;width:100vw;height:100vh;display:flex;overflow:hidden}.machine-index{border-bottom:1px solid var(--line);scrollbar-width:thin;background:#0d0f12;flex:none;width:100%;min-width:0;min-height:48px;padding:0;display:flex;overflow:auto hidden}.machine-row{border:0;border-right:1px solid var(--line-soft);color:#c9cdd2;text-align:left;cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;flex:none;align-items:center;gap:8px;width:auto;min-width:148px;max-width:280px;min-height:48px;padding:0 16px;display:flex;position:relative}.machine-row:hover,.machine-row:focus-visible{color:#fff;background:#171a1f;outline:none}.machine-row.is-selected{color:#fff;background:#4b7dff1f}.machine-row.is-selected:after{background:var(--accent);content:"";height:2px;position:absolute;bottom:0;left:0;right:0}.machine-row-status{background:#646b75;border-radius:50%;flex:none;width:6px;height:6px}.machine-row-status.status-ready{background:#67a9cf}.machine-row-status.status-partial{background:var(--orange)}.machine-row-status.status-error{background:var(--danger)}.machine-row-label,.machine-row-file{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.machine-row-label{font:600 12px/1.3 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.machine-row-file{display:none}.machine-index-empty{color:#646b75;padding:16px;font:11px/1.4 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.machine-view{flex:1;min-width:0;min-height:0;overflow:hidden}.registry-empty,.connection-failure{color:#7f8690;align-content:start;gap:7px;min-height:100vh;padding:28px;font:12px/1.6 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;display:grid}.registry-empty strong{color:#d4d7dc;font-size:13px}.connection-failure{color:var(--danger-strong)}button{font:inherit}.app-shell,.workspace{width:100%;height:100%;min-height:0}.workspace{position:relative}.chart-panel{flex-direction:column;width:100%;min-width:0;height:100%;display:flex;position:relative;overflow:hidden}.diagnostics{border-bottom:1px solid var(--line);background:#121418}.diagnostic{color:#aeb4bd;flex-wrap:wrap;align-items:center;gap:8px;min-height:36px;padding:8px 16px;font-size:11px;display:flex}.diagnostic+.diagnostic{border-top:1px solid var(--line-soft)}.badge-warning{color:#e9c89f;background:#f0a35b21}.badge-error{color:var(--danger-strong);background:#be485226}.toolbar{border-bottom:1px solid var(--line);justify-content:space-between;align-items:center;gap:2px;min-height:46px;padding:7px 16px;display:flex}.toolbar-actions,.zoom-controls,.runtime-summary{align-items:center;display:flex}.toolbar-actions{gap:2px}.zoom-controls{z-index:5;border:1px solid var(--line-soft);background:#0d0f12f0;border-radius:4px;flex:none;gap:1px;padding:2px;position:absolute;bottom:14px;left:14px;box-shadow:0 8px 28px #00000052}.chart-panel.has-walkthrough .zoom-controls{bottom:88px}.zoom-button{min-width:28px;padding-inline:7px}.zoom-value{color:#aeb4bd;min-width:46px;font:10px/1 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.runtime-summary{color:#7f8690;gap:7px;font:11px/1 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.runtime-dot{background:#555c65;border-radius:50%;width:6px;height:6px}.runtime-dot.has-snapshot{background:var(--accent)}.toolbar-button{color:var(--muted);cursor:pointer;background:0 0;border:0;border-radius:4px;padding:6px 9px;font-size:12px}.toolbar-button:not(:disabled):hover,.toolbar-button:not(:disabled):focus-visible{color:#fff;background:#1b1e23;outline:none}.toolbar-button:disabled{color:#50545c;cursor:default}.toolbar-button[aria-pressed=true]{color:#dce8ff;background:#4167a547}.analysis-button{align-items:center;gap:6px;display:inline-flex}.analysis-button[hidden]{display:none}.analysis-button-count{color:#9da6b3;text-align:center;background:#20242a;border-radius:8px;min-width:17px;padding:2px 5px;font:10px/1 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.topology-chart{flex-direction:column;flex:1;min-height:0;font:13px/1.5 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;display:flex}.topology-empty{color:#7f8690;gap:7px;max-width:420px;margin:26px 8px;font:12px/1.6 Inter,ui-sans-serif,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;display:grid}.topology-empty strong{color:#d4d7dc;font:600 13px/1.4 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.chart-host,.chart-viewport{width:100%;height:100%}.chart-host{flex:1;min-height:0;position:relative}.chart-viewport{overscroll-behavior:contain;cursor:grab;touch-action:pan-x pan-y;overflow:auto}.chart-viewport.is-panning,.chart-viewport.is-panning .chart-state,.chart-viewport.is-panning .chart-edge-hit,.chart-viewport.is-panning .chart-edge-label{cursor:grabbing;-webkit-user-select:none;user-select:none}.chart-stage{min-width:100%;min-height:100%;position:relative}.chart-canvas{transform-origin:0 0;position:absolute;top:0;left:0}.chart-regions,.chart-edges,.chart-nodes,.chart-labels{position:absolute;inset:0}.chart-regions{z-index:0;pointer-events:none}.chart-edges{z-index:1;pointer-events:none;overflow:visible}.chart-nodes{z-index:2;pointer-events:none}.chart-labels{z-index:3;pointer-events:none}.chart-compound{border:1px solid var(--chart-border-soft);background:#151a20c7;border-radius:5px;position:absolute}.chart-compound-parallel{border-color:var(--chart-border);background:#181e26cc}.chart-unconnected-region{background:#0e101394;border:1px dashed #353b44;border-radius:5px;position:absolute}.chart-unconnected-region-label{color:#727984;letter-spacing:.05em;text-transform:uppercase;font:9px/1 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;position:absolute;top:17px;left:24px}.chart-state{border:1px solid var(--chart-border);color:var(--chart-text);background:var(--chart-surface);text-align:left;cursor:pointer;pointer-events:auto;-webkit-user-select:none;user-select:none;border-radius:4px;flex-direction:column;justify-content:center;padding:12px;display:flex;position:absolute;overflow:hidden;box-shadow:0 4px 14px #0000002e}.chart-state-compound,.chart-state-parallel{background:var(--chart-surface-raised);border-color:#465362}.chart-state-final{border-color:#445066}.chart-state-history,.chart-state-choice{background:#1c1a21}.chart-state:not(:disabled):hover,.chart-state:focus-visible{color:#fff;border-color:#596475;outline:none}.chart-state-heading,.chart-state-identity,.chart-activity-row{align-items:center;min-width:0;display:flex}.chart-state-heading{justify-content:space-between;gap:12px}.chart-state-identity{gap:8px}.chart-state-status{border:1px solid #686f78;border-radius:50%;flex:none;width:7px;height:7px}.chart-state-status.is-active{border-color:var(--accent);background:var(--accent);box-shadow:0 0 0 3px #75a7ff1a}.chart-state-name,.chart-activity-name{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.chart-state-name{font-size:12px}.chart-activity-kind,.chart-more{color:var(--chart-text-muted);font-size:9px;line-height:1.3}.chart-activity-kind{text-transform:uppercase}.chart-state-section{border-top:1px solid #333d48;width:min(300px,100%);margin-top:8px;padding-top:7px}.chart-activity-row{grid-template-columns:auto minmax(0,1fr);gap:10px;min-height:20px;display:grid}.chart-activity-name{color:#d1d7df;font-size:10px}.chart-activity-kind{text-overflow:clip;white-space:nowrap;min-width:max-content;color:var(--chart-activity-color,#82a9cb);flex:0 auto;overflow:visible}.chart-activity-process,.chart-edge-activity-process,.badge-activity-process{--chart-activity-color:#c99a82;--chart-activity-border:#624d42;--chart-activity-background:#1d1714}.chart-activity-effect,.chart-edge-activity-effect,.badge-activity-effect{--chart-activity-color:#82a9cb;--chart-activity-border:#435c71;--chart-activity-background:#121a22}.chart-activity-timer,.chart-edge-activity-timer,.badge-activity-timer{--chart-activity-color:#c1ad73;--chart-activity-border:#625842;--chart-activity-background:#1c1a13}.chart-activity-stream,.chart-edge-activity-stream,.badge-activity-stream{--chart-activity-color:#75a9ad;--chart-activity-border:#3f5c5f;--chart-activity-background:#111a1b}.chart-activity-machine,.chart-edge-activity-machine,.badge-activity-machine{--chart-activity-color:#a99cbd;--chart-activity-border:#574e67;--chart-activity-background:#1a1720}.chart-more{min-height:16px;padding-top:2px}.chart-initial{pointer-events:none;background:#b0965d;border-radius:50%;position:absolute;box-shadow:0 0 0 2px #b0965d1a}.chart-runtime-target{color:#858d98;letter-spacing:.04em;text-transform:uppercase;pointer-events:none;-webkit-user-select:none;user-select:none;background:#111419;border:1px dashed #555d68;border-radius:3px;place-items:center;font:9px/1 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;display:grid;position:absolute}.chart-edge-casing,.chart-edge-line,.chart-edge-direction,.chart-edge-hit{fill:none}.chart-edge-parent-origin{fill:#101318;stroke:#89929e;stroke-width:1.8px;vector-effect:non-scaling-stroke}.chart-edge-casing{stroke:#0b0c0e;stroke-width:5.5px;vector-effect:non-scaling-stroke}.chart-edge-line,.chart-edge-direction{stroke:#626b77;stroke-width:1.4px;vector-effect:non-scaling-stroke}.chart-edge-direction{pointer-events:none}.chart-edge-initial .chart-edge-line{stroke:#9f8a5c;stroke-width:1.2px}.chart-edge-hit{stroke:#0000;stroke-width:14px;cursor:pointer;pointer-events:stroke}#chart-arrow path,#chart-direction path,#chart-initial-arrow path{fill:context-stroke}.chart-edge-label{--chart-edge-label-background:#151a20;--chart-edge-label-border:#3a4551;--chart-edge-label-shadow:none;color:#d1d7df;white-space:nowrap;cursor:pointer;pointer-events:auto;-webkit-user-select:none;user-select:none;background:0 0;border:0;justify-content:center;align-items:center;padding:4px 7px;font:10px/1 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;display:flex;position:absolute;overflow:visible}.chart-edge-label:before{border:1px solid var(--chart-edge-label-border);background:var(--chart-edge-label-background);box-shadow:var(--chart-edge-label-shadow);content:"";border-radius:3px;position:absolute;inset:0}.chart-edge-label-corner-badge{padding:8px 11px 4px 7px}.chart-edge-label-corner-badge:before{top:4px;right:4px}.chart-edge-label-text{z-index:1;text-align:center;text-overflow:ellipsis;white-space:nowrap;min-width:0;position:relative;overflow:hidden}.chart-edge-badges{z-index:2;flex:none;align-items:center;gap:3px;min-width:0;display:flex;position:absolute;top:0;right:0}.chart-edge-label-icon-only{justify-content:center;align-items:center;padding:0;display:flex}.chart-edge-label-icon-only:before{display:none}.chart-edge-label-icon-only .chart-edge-badges{position:static}.chart-edge-badge{background:#161b22;border:1px solid;border-radius:50%;flex:none;justify-content:center;align-items:center;width:11px;height:11px;display:inline-flex}.chart-edge-badge-icon{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.8px;width:8px;height:8px;overflow:visible}.chart-edge-badge-icon-fill{fill:currentColor;stroke:none}.chart-edge-badge-completion{color:var(--chart-completion)}.chart-edge-badge-failure{color:var(--chart-failure)}.chart-edge-badge-element{color:#7fadb7}.chart-edge-badge-snapshot{color:#aaa0bd}.chart-edge-badge-always{color:#b8a66f}.chart-edge-badge-choice{color:#aa9abd}.chart-edge-badge-branches{color:#a3acb8;border-radius:6px;gap:1px;width:auto;min-width:21px;padding:0 2px}.chart-edge-badge-branches .chart-edge-badge-icon{width:7px;height:7px}.chart-edge-badge-count{font-size:6px;font-weight:700;line-height:1}.chart-edge-group.chart-edge-parent-child .chart-edge-line,.chart-edge-group.chart-edge-parent-child .chart-edge-direction,.chart-edge-group.chart-edge-parent-child .chart-edge-parent-origin{stroke:#9187a7}.chart-edge-group.chart-edge-parent-child .chart-edge-parent-origin{fill:#1b1820}.chart-edge-label-parent-child{--chart-edge-label-background:#17151b;--chart-edge-label-border:#4d465a;--chart-edge-label-shadow:inset 2px 0 #6f6681;color:#aea5c1}.chart-edge-label:not(:disabled):hover,.chart-edge-label:focus-visible,.chart-edge-group.is-hovered+.chart-edge-label{--chart-edge-label-border:#53657e;color:#fff;outline:none}.chart-edge-label-always,.chart-edge-label-choice,.chart-edge-label-done{color:#d4b4e9}.chart-edge-group.is-hovered .chart-edge-line,.chart-edge-group.is-hovered .chart-edge-direction,.chart-edge-group.is-hovered .chart-edge-parent-origin{stroke:#7c9ed2;stroke-width:1.8px}.chart-edge-group.is-walkthrough-unavailable .chart-edge-line{stroke:#6e675b;stroke-dasharray:5 5}.chart-edge-group.chart-transition-runtime .chart-edge-line{stroke-dasharray:5 5}.chart-edge-group.chart-edge-trigger-always .chart-edge-line,.chart-edge-group.chart-edge-trigger-choice .chart-edge-line,.chart-edge-group.chart-edge-trigger-done .chart-edge-line,.chart-edge-group.chart-edge-trigger-invoke .chart-edge-line{stroke-dasharray:7 5}.chart-edge-group.chart-edge-activity-process .chart-edge-line,.chart-edge-group.chart-edge-activity-effect .chart-edge-line,.chart-edge-group.chart-edge-activity-timer .chart-edge-line,.chart-edge-group.chart-edge-activity-stream .chart-edge-line,.chart-edge-group.chart-edge-activity-machine .chart-edge-line,.chart-edge-group.chart-edge-activity-process .chart-edge-direction,.chart-edge-group.chart-edge-activity-effect .chart-edge-direction,.chart-edge-group.chart-edge-activity-timer .chart-edge-direction,.chart-edge-group.chart-edge-activity-stream .chart-edge-direction,.chart-edge-group.chart-edge-activity-machine .chart-edge-direction,.chart-edge-group.chart-edge-activity-process .chart-edge-parent-origin,.chart-edge-group.chart-edge-activity-effect .chart-edge-parent-origin,.chart-edge-group.chart-edge-activity-timer .chart-edge-parent-origin,.chart-edge-group.chart-edge-activity-stream .chart-edge-parent-origin,.chart-edge-group.chart-edge-activity-machine .chart-edge-parent-origin{stroke:var(--chart-activity-color)}.chart-edge-label.chart-edge-activity-process,.chart-edge-label.chart-edge-activity-effect,.chart-edge-label.chart-edge-activity-timer,.chart-edge-label.chart-edge-activity-stream,.chart-edge-label.chart-edge-activity-machine{--chart-edge-label-background:var(--chart-activity-background);--chart-edge-label-border:var(--chart-activity-border);color:var(--chart-activity-color)}.chart-edge-group.chart-edge-failure .chart-edge-line,.chart-edge-group.chart-edge-failure .chart-edge-direction,.chart-edge-group.chart-edge-failure .chart-edge-parent-origin{stroke:var(--chart-failure)}.chart-edge-label.chart-edge-label-failure{--chart-edge-label-background:var(--danger-background);--chart-edge-label-border:var(--danger-border);color:var(--danger-strong)}.chart-edge-group.is-incoming .chart-edge-line,.chart-edge-group.is-incoming .chart-edge-direction,.chart-edge-group.is-incoming .chart-edge-parent-origin{stroke:var(--chart-source);stroke-width:2px}.chart-edge-group.is-outgoing .chart-edge-line,.chart-edge-group.is-outgoing .chart-edge-direction,.chart-edge-group.is-outgoing .chart-edge-parent-origin{stroke:var(--chart-target);stroke-width:2px}.chart-edge-group.is-selected .chart-edge-line,.chart-edge-group.is-selected .chart-edge-direction,.chart-edge-group.is-selected .chart-edge-parent-origin{stroke:#8ab5ff;stroke-width:2.5px}.chart-edge-group.is-walkthrough-available .chart-edge-line,.chart-edge-group.is-walkthrough-available .chart-edge-direction{stroke:#d5aa57;stroke-width:2px}.chart-edge-label.is-hovered{--chart-edge-label-border:#526783;color:#dbe8ff}.chart-edge-label.is-walkthrough-unavailable{--chart-edge-label-background:#151412;--chart-edge-label-border:#4e4a43;color:#8d8679}.chart-edge-label.is-incoming{--chart-edge-label-background:#241914;--chart-edge-label-border:#8e5f43;color:#f0b590}.chart-edge-label.is-outgoing{--chart-edge-label-background:#111c24;--chart-edge-label-border:#4d7188;color:#a9d3e7}.chart-edge-label.is-selected{--chart-edge-label-background:#18253a;--chart-edge-label-border:#719ce0;color:#fff}.chart-edge-label.is-walkthrough-available{--chart-edge-label-background:#211b12;--chart-edge-label-border:#8d713c;color:#f0d39a}.chart-state.is-selected,.chart-compound.is-selected{background:#2c4b7a6b;border-color:#5f88ca}.chart-state.is-related-to,.chart-compound.is-related-to,.chart-state.is-hover-target,.chart-compound.is-hover-target{background:#36708f4d;border-color:#5e8aa3}.chart-state.is-related-from,.chart-compound.is-related-from,.chart-state.is-hover-source,.chart-compound.is-hover-source{background:#9554304d;border-color:#9b684c}.chart-state.is-related-from.is-related-to,.chart-compound.is-related-from.is-related-to{background:linear-gradient(135deg,#9554304d 0 50%,#36708f4d 50% 100%);border-color:#777a91}.chart-viewport.is-simulating .chart-state:disabled,.chart-viewport.is-simulating .chart-edge-label:disabled,.chart-viewport.is-simulating .chart-edge-hit{cursor:default}.chart-viewport.is-simulating .chart-edge-label:disabled,.chart-viewport.is-simulating .chart-edge-hit{pointer-events:none}.chart-viewport.is-simulating .chart-edge-label.is-walkthrough-available,.chart-viewport.is-simulating .chart-edge-label.is-walkthrough-unavailable,.chart-viewport.is-simulating .chart-edge-group.is-walkthrough-available .chart-edge-hit,.chart-viewport.is-simulating .chart-edge-group.is-walkthrough-unavailable .chart-edge-hit{cursor:pointer}.chart-viewport.is-simulating .chart-edge-group.is-walkthrough-available .chart-edge-hit,.chart-viewport.is-simulating .chart-edge-group.is-walkthrough-unavailable .chart-edge-hit{pointer-events:stroke}.chart-loading,.chart-layout-error{color:#7f8690;gap:7px;max-width:440px;margin:28px;font:11px/1.6 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;display:grid}.chart-layout-error{color:var(--danger)}.chart-layout-error strong{color:var(--danger-strong)}.inspector-eyebrow,.card-title,.card-flags,.branch-main{align-items:center;gap:6px;display:flex}.badge{color:#a8afb8;letter-spacing:.02em;white-space:nowrap;background:#20242a;border-radius:3px;align-items:center;min-height:18px;padding:2px 6px;font:600 10px/1 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;display:inline-flex}.badge-active{color:#b9d2ff;background:#4b7dff38}.badge-trigger{color:#b9d2ff;background:#4b7dff29}.badge-condition{color:#d9b8ef;background:#ac68e026}.badge-activity{color:#acd0e5;background:#5291b729}.badge-activity-process,.badge-activity-effect,.badge-activity-timer,.badge-activity-stream,.badge-activity-machine{color:var(--chart-activity-color);background:var(--chart-activity-background)}.badge-count{color:#858c96;background:0 0}.inspector{z-index:10;background:#0f1114f7;border:1px solid #333943;border-radius:6px;width:min(460px,100% - 28px);min-width:0;padding:0;position:absolute;top:60px;bottom:14px;right:14px;overflow:hidden;box-shadow:0 18px 60px #0000007a}.inspector[hidden]{display:none}.inspector-close{z-index:1;color:#8e949e;cursor:pointer;background:0 0;border:0;border-radius:3px;padding:6px 9px;font-size:11px;position:absolute;top:11px;right:12px}.inspector-content{width:100%;height:100%;padding:48px 24px 24px;overflow:auto}.inspector-close:hover,.inspector-close:focus-visible{color:#fff;background:#20242a;outline:none}.failure-shell{color:#d6d8dc;background:#0b0c0e;align-content:start;gap:12px;min-height:100vh;padding:32px;display:grid}.failure-kind{color:var(--danger-strong);letter-spacing:.08em;text-transform:uppercase;font:600 10px/1.2 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.failure-shell h1{margin:0;font:600 18px/1.4 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.failure-shell pre{border-left:2px solid var(--danger-border);max-width:900px;color:var(--danger-strong);background:var(--danger-background);white-space:pre-wrap;margin:4px 0 0;padding:14px 16px;font:12px/1.6 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;overflow:auto}.failure-shell p{color:#7f8690;margin:0;font-size:12px}.inspector-empty{max-width:420px;color:var(--muted)}.inspector-empty-kind{color:var(--orange);letter-spacing:.08em;text-transform:uppercase;font:600 10px/1.2 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.inspector-empty h2,.inspector-header h2{color:#f1f2f4;overflow-wrap:anywhere;margin:9px 0 0;font:600 18px/1.4 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.inspector-title-row,.inspector-state-title{align-items:center;min-width:0;display:flex}.inspector-title-row{justify-content:space-between;gap:16px}.inspector-state-title{gap:9px}.inspector-title-row h2{min-width:0;margin:0}.inspector-empty p,.section-empty{color:var(--muted);font-size:12px;line-height:1.6}.inspector-header{border-bottom:1px solid var(--line);padding-bottom:24px}.analysis-summary{color:#7f8690;margin:12px 0 0;font-size:12px;line-height:1.6}.state-annotations{margin-top:18px}.state-annotations p{color:#aeb4bd;margin:7px 0 0;font-size:12px;line-height:1.6}.state-annotations .state-documentation{color:#7f8690;white-space:pre-wrap;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.breadcrumbs{flex-wrap:wrap;align-items:center;gap:5px;min-width:0;margin-bottom:16px;display:flex}.breadcrumb-separator{color:#555c65}.state-link{color:#9bbfff;overflow-wrap:anywhere;text-align:left;cursor:pointer;background:0 0;border:0;max-width:100%;padding:0;font:11px/1.5 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.state-link:hover,.state-link:focus-visible{color:#d5e4ff;outline:none;text-decoration:underline}.metadata{grid-template-columns:minmax(74px,max-content) minmax(0,1fr);gap:8px 16px;margin:20px 0 0;font-size:11px;display:grid}.metadata dt{color:#727983}.metadata dd{color:#d2d5da;overflow-wrap:anywhere;min-width:0;margin:0;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.inspector-section{margin-top:28px}.section-heading{justify-content:space-between;align-items:center;margin-bottom:11px;display:flex}.section-heading h3{color:#c9cdd2;margin:0;font-size:12px;font-weight:650}.section-count{color:#737a84;font:11px/1 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.inspection-card{border:1px solid var(--line-soft);background:var(--surface-raised);margin-top:8px}.analysis-card{padding-bottom:12px}.analysis-card .state-link{color:#e2e4e7;font-size:12px;font-weight:600}.analysis-message,.analysis-qualification{margin:0;padding:0 12px;font-size:11px;line-height:1.6}.analysis-message{color:#b9bec6}.analysis-qualification{color:#747c87;margin-top:5px}.card-header{justify-content:space-between;align-items:center;gap:12px;min-height:42px;padding:10px 12px;display:flex}.card-title{min-width:0}.card-title strong{color:#e2e4e7;overflow-wrap:anywhere;font:600 12px/1.4 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.branch-list{border-top:1px solid var(--line-soft)}.branch-row{padding:11px 12px 13px}.branch-row+.branch-row{border-top:1px solid var(--line-soft)}.branch-main{min-width:0}.branch-arrow{color:var(--accent)}.branch-target{color:#d7d9dc;overflow-wrap:anywhere;font:11px/1.4 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.branch-row .metadata,.transition-card .card-metadata,.activity-card .metadata,.incoming-card .metadata{margin-top:10px}.incoming-card{padding-bottom:12px}.incoming-card .metadata{padding:0 12px}.transition-card .card-metadata{padding:0 12px 10px}.branch-updates{grid-template-columns:minmax(74px,max-content) minmax(0,1fr);gap:8px 16px;margin-top:9px;font-size:11px;display:grid}.branch-updates-label{color:#727983}.branch-updates .state-link+.state-link{grid-column:2}.activity-card{padding-bottom:12px}.activity-card .metadata{padding:0 12px}.walkthrough-dock{border-top:1px solid var(--line);background:#0d0f12fa;flex:none;grid-template-rows:auto auto;gap:6px;min-height:0;max-height:76px;padding:8px 14px 10px;font:10px/1.4 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;display:grid;box-shadow:0 -12px 32px #0003}.walkthrough-dock[hidden]{display:none}.walkthrough-heading,.walkthrough-identity,.walkthrough-timeline{align-items:center;min-width:0;display:flex}.walkthrough-heading{color:#d4d7dc;justify-content:space-between;gap:12px}.walkthrough-identity{gap:10px}.walkthrough-status,.walkthrough-hint{color:#777f8a}.walkthrough-hint{font-size:9px}.walkthrough-timeline{scrollbar-width:thin;gap:5px;overflow-x:auto}.walkthrough-step{border:1px solid var(--line-soft);color:#aeb4bd;cursor:pointer;white-space:nowrap;background:#14171b;border-radius:3px;flex:none;padding:5px 8px}.walkthrough-step:hover,.walkthrough-step:focus-visible{color:#fff;border-color:#53657e;outline:none}.walkthrough-step.is-current{color:#d8e6ff;background:#2c4b7a61;border-color:#5f88ca}.transition-picker{z-index:20;background:#0f1114fa;border:1px solid #4e4535;border-radius:5px;grid-template-rows:auto minmax(0,1fr);width:min(380px,100vw - 20px);max-height:min(420px,100vh - 68px);display:grid;position:fixed;overflow:hidden;box-shadow:0 18px 60px #00000085}.transition-picker[hidden]{display:none}.transition-picker-header,.transition-picker-choice-main{align-items:center;min-width:0;display:flex}.transition-picker-header{border-bottom:1px solid var(--line-soft);justify-content:space-between;gap:10px;min-height:38px;padding:8px 10px 8px 12px}.transition-picker-header strong{color:#d8dadd;text-overflow:ellipsis;white-space:nowrap;font:600 11px/1.4 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;overflow:hidden}.transition-picker-close{color:#7f8690;cursor:pointer;background:0 0;border:0;border-radius:3px;padding:4px 6px;font-size:10px}.transition-picker-close:hover,.transition-picker-close:focus-visible{color:#fff;background:#20242a;outline:none}.transition-picker-content{gap:5px;padding:7px;display:grid;overflow:auto}.transition-picker-choice{border:1px solid var(--line-soft);color:#aeb4bd;text-align:left;cursor:pointer;background:#14171b;border-radius:3px;gap:4px;min-width:0;padding:8px 9px;font:10px/1.4 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;display:grid}.transition-picker-choice:hover,.transition-picker-choice:focus-visible{background:#1d1912;border-color:#8d713c;outline:none}.transition-picker-choice-main{gap:7px}.transition-picker-choice-main strong,.transition-picker-choice-title,.transition-picker-choice-route,.transition-picker-choice-contract,.transition-picker-choice-decision,.transition-picker-choice-unavailable{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.transition-picker-choice-main strong{color:#efd18f}.transition-picker-choice-title{color:#d9b8ef}.transition-picker-choice-route{color:#777f8a}.transition-picker-choice-contract{color:#9ebce9}.transition-picker-choice-decision{color:#b69ac9}.transition-picker-choice-unavailable{color:#a38c6f}.transition-picker-choice.is-unavailable{opacity:.68;cursor:default}.input-contract-fields,.input-contract-field,.input-contract-children,.input-contract-alternatives{gap:9px;display:grid}.input-contract-fields{border:1px solid var(--line-soft);background:var(--surface-raised);padding:11px 12px}.input-contract-field+.input-contract-field{border-top:1px solid var(--line-soft);padding-top:9px}.input-contract-children,.input-contract-alternatives{border-top:1px solid var(--line-soft);border-left:1px solid var(--line-soft);margin-top:2px;padding:9px 0 0 12px}.input-contract .section-empty{margin:0}.input-field-heading{justify-content:space-between;align-items:center;gap:12px;display:flex}.input-field-contract,.input-constraints{flex-wrap:wrap;align-items:center;gap:6px;min-width:0;display:flex}.input-field-contract{flex:none;justify-content:flex-end;margin-left:auto}.input-label,.input-required,.input-optional{font-size:11px}.input-label{color:#cfd3d9;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.input-field-type,.input-constraints span{color:#8294ad;font:10px/1.3 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.input-field-type{background:#4b7dff1f;border-radius:3px;padding:2px 5px}.input-constraints{margin-top:-1px}.input-constraints span+span:before{color:#4f5762;content:"·";margin-right:6px}.input-required{color:#737b86}.input-optional{color:#9199a4;align-items:center;gap:6px;display:inline-flex}.input-description,.input-unsupported{margin:0;font-size:11px;line-height:1.55}.input-description{color:#737b86}.input-unsupported{color:var(--danger-strong)}.value-shape-block{border:1px solid var(--line-soft);color:#b8c1ce;background:var(--surface-raised);tab-size:2;white-space:pre;margin:0;padding:12px;font:10px/1.55 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;overflow-x:auto}.trace-topology{gap:10px;display:grid}.trace-topology .section-heading{margin-bottom:1px}.trace-path-group,.trace-values,.trace-transitions{gap:7px;display:grid}.trace-path-group{grid-template-columns:78px minmax(0,1fr);align-items:start}.trace-paths{flex-wrap:wrap;gap:4px 10px;min-width:0;display:flex}.trace-label{color:#747c87;text-transform:uppercase;font-size:10px;line-height:1.5}.trace-card{padding-bottom:12px}.trace-card>.trace-path-group,.trace-card>.trace-values,.trace-card>.trace-transitions{margin:0 12px 10px}.trace-transition{flex-wrap:wrap;align-items:center;gap:6px;min-width:0;display:flex}.trace-transition+.trace-path-group{margin:0 0 4px}.trace-results{padding-bottom:24px}.trace-results>.trace-values{margin-top:12px}@media (width<=900px){.machine-row{min-width:132px;max-width:220px}.inspector{width:min(440px,100% - 16px);top:54px;bottom:8px;right:8px}}@media (width<=600px){.toolbar{align-items:flex-start;padding-inline:10px}.toolbar-actions{flex-wrap:wrap;justify-content:flex-end}.runtime-summary{padding-top:8px}.inspector-content{padding:48px 14px 18px}.inspector{top:84px}.zoom-controls{bottom:8px;left:8px}.chart-panel.has-walkthrough .zoom-controls{bottom:88px}}@media (prefers-reduced-motion:no-preference){.chart-state,.chart-edge-label,.toolbar-button{transition:color .12s,background-color .12s,border-color .12s}}
@@ -5,8 +5,8 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <meta name="description" content="Interactive statechart visualization for Effect Machine" />
7
7
  <title>Effect Machine · Statechart</title>
8
- <script type="module" crossorigin src="./assets/index-gxgK_rqB.js"></script>
9
- <link rel="stylesheet" crossorigin href="./assets/index-ZUqYOHbc.css">
8
+ <script type="module" crossorigin src="./assets/index-CSgOYHLh.js"></script>
9
+ <link rel="stylesheet" crossorigin href="./assets/index-DkC3PbTy.css">
10
10
  </head>
11
11
  <body>
12
12
  <div id="app"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typeonce/effect-machine-devtools",
3
- "version": "0.31.0",
3
+ "version": "0.31.1",
4
4
  "description": "Local development tools for Effect Machine",
5
5
  "author": "Sandro Maglione",
6
6
  "repository": {
@@ -33,7 +33,7 @@
33
33
  "elkjs": "0.12.0",
34
34
  "typescript": "6.0.3",
35
35
  "vite": "8.1.5",
36
- "@typeonce/effect-machine": "^0.31.0"
36
+ "@typeonce/effect-machine": "^0.31.1"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "effect": "4.0.0-rc.112"
@@ -319,10 +319,24 @@ const portsByState = (
319
319
  return ports
320
320
  }
321
321
 
322
- const labelMetric = (label: string): { readonly width: number; readonly height: number } => ({
323
- width: Math.min(230, Math.max(72, label.length * 7 + 20)),
324
- height: 26
325
- })
322
+ const badgeWidth = (badge: ChartEdge["badges"][number]): number => badge.type === "branches" ? 21 : 11
323
+
324
+ const labelMetric = (edge: ChartEdge): { readonly width: number; readonly height: number } => {
325
+ const badgesWidth = edge.badges.reduce((width, badge) => width + badgeWidth(badge), 0) +
326
+ Math.max(0, edge.badges.length - 1) * 3
327
+ if (edge.label.length === 0) {
328
+ return {
329
+ width: Math.max(20, badgesWidth + 4),
330
+ height: 20
331
+ }
332
+ }
333
+ const bodyWidth = Math.min(226, Math.max(52, edge.label.length * 7 + 20))
334
+ const hasCornerBadge = edge.badges.length > 0
335
+ return {
336
+ width: bodyWidth + (hasCornerBadge ? 4 : 0),
337
+ height: 26 + (hasCornerBadge ? 4 : 0)
338
+ }
339
+ }
326
340
 
327
341
  const makeGraph = (
328
342
  model: ChartModel,
@@ -443,14 +457,14 @@ const makeGraph = (
443
457
  children: children(null),
444
458
  edges: [
445
459
  ...model.edges.map((edge): ElkExtendedEdge => {
446
- const label = labelMetric(edge.label)
460
+ const label = labelMetric(edge)
447
461
  const edgeLayout = policy.edge(edge)
448
462
  const runtimeTarget = edge.kind === "runtime" ? runtimeByEdgeId.get(edge.id) : undefined
449
463
  return {
450
464
  id: edge.id,
451
465
  sources: [sourcePortId(edge)],
452
466
  targets: [runtimeTarget === undefined ? targetPortId(edge) : runtimeTargetPortId(runtimeTarget)],
453
- labels: [{ text: edge.label, width: label.width, height: label.height }],
467
+ labels: [{ text: edge.accessibleLabel, width: label.width, height: label.height }],
454
468
  layoutOptions: {
455
469
  "elk.layered.priority.direction": edgeLayout.direction === "forward" ? "10" : "1",
456
470
  "elk.layered.priority.shortness": "5",
@@ -1076,7 +1090,7 @@ const collectLayout = (
1076
1090
  nodesByPath,
1077
1091
  nodes
1078
1092
  )
1079
- const metric = labelMetric(chartEdge.label)
1093
+ const metric = labelMetric(chartEdge)
1080
1094
  const label = edge.labels?.[0]
1081
1095
  const labelWidth = label?.width ?? metric.width
1082
1096
  const labelHeight = label?.height ?? metric.height
@@ -24,6 +24,15 @@ export interface ChartNode {
24
24
  readonly activities: ReadonlyArray<ChartActivity>
25
25
  }
26
26
 
27
+ export type ChartEdgeBadge =
28
+ | { readonly type: "always" }
29
+ | { readonly type: "completion" }
30
+ | { readonly type: "choice" }
31
+ | { readonly type: "failure" }
32
+ | { readonly type: "element" }
33
+ | { readonly type: "snapshot" }
34
+ | { readonly type: "branches"; readonly count: number }
35
+
27
36
  export interface ChartEdge {
28
37
  readonly id: string
29
38
  readonly transitionId: string
@@ -32,6 +41,8 @@ export interface ChartEdge {
32
41
  readonly source: string
33
42
  readonly target: string | null
34
43
  readonly label: string
44
+ readonly accessibleLabel: string
45
+ readonly badges: ReadonlyArray<ChartEdgeBadge>
35
46
  readonly trigger: VisualizationTransition["trigger"]
36
47
  readonly activityKind: ChartActivity["kind"] | null
37
48
  readonly reenter: boolean
@@ -78,6 +89,43 @@ const transitionLabel = (transition: VisualizationTransition, branch: Visualizat
78
89
  return branch.type === "branch" ? `${trigger} · ${branch.title}` : trigger
79
90
  }
80
91
 
92
+ interface TriggerPresentation {
93
+ readonly label: string
94
+ readonly badges: ReadonlyArray<ChartEdgeBadge>
95
+ }
96
+
97
+ const triggerPresentation = (transition: VisualizationTransition): TriggerPresentation => {
98
+ switch (transition.trigger.type) {
99
+ case "event":
100
+ return { label: transition.trigger.event, badges: [] }
101
+ case "always":
102
+ return { label: "", badges: [{ type: "always" }] }
103
+ case "done":
104
+ return { label: "", badges: [{ type: "completion" }] }
105
+ case "choice":
106
+ return { label: "", badges: [{ type: "choice" }] }
107
+ case "invoke":
108
+ return {
109
+ label: transition.trigger.id,
110
+ badges: [{ type: transition.trigger.outcome === "done" ? "completion" : transition.trigger.outcome }]
111
+ }
112
+ }
113
+ }
114
+
115
+ const visibleLabel = (transition: VisualizationTransition, branches: ReadonlyArray<VisualizationBranch>): string => {
116
+ const presentation = triggerPresentation(transition)
117
+ if (branches.length !== 1 || branches[0]?.type !== "branch") return presentation.label
118
+ return [presentation.label, branches[0].title].filter((part) => part.length > 0).join(" · ")
119
+ }
120
+
121
+ const labelBadges = (
122
+ transition: VisualizationTransition,
123
+ branches: ReadonlyArray<VisualizationBranch>
124
+ ): ReadonlyArray<ChartEdgeBadge> => [
125
+ ...triggerPresentation(transition).badges,
126
+ ...(branches.length > 1 ? [{ type: "branches" as const, count: branches.length }] : [])
127
+ ]
128
+
81
129
  interface EdgeGroup {
82
130
  readonly kind: ChartEdge["kind"]
83
131
  readonly target: string | null
@@ -146,9 +194,11 @@ export const makeChartModel = (document: VisualizationDocument): ChartModel => {
146
194
  kind,
147
195
  source: transition.source,
148
196
  target,
149
- label: branches.length === 1
197
+ label: visibleLabel(transition, branches),
198
+ accessibleLabel: branches.length === 1
150
199
  ? transitionLabel(transition, branches[0]!)
151
200
  : `${triggerLabel(transition)} · ${branches.length} branches`,
201
+ badges: labelBadges(transition, branches),
152
202
  trigger: transition.trigger,
153
203
  activityKind: transition.trigger.type === "invoke"
154
204
  ? activitiesBySource.get(transition.source)?.get(transition.trigger.id) ?? null
@@ -8,7 +8,7 @@ import {
8
8
  layoutChart,
9
9
  maxVisibleActivities
10
10
  } from "./chart-layout.js"
11
- import { makeChartModel } from "./chart-model.js"
11
+ import { type ChartEdgeBadge, makeChartModel } from "./chart-model.js"
12
12
 
13
13
  export interface ChartHandlers {
14
14
  readonly selectState: (path: string, anchor: ChartInteractionAnchor) => void
@@ -109,6 +109,57 @@ const svgElement = <Tag extends keyof SVGElementTagNameMap>(
109
109
  return node
110
110
  }
111
111
 
112
+ const badgeIcon = (badge: ChartEdgeBadge): SVGSVGElement => {
113
+ const icon = svgElement("svg", "chart-edge-badge-icon")
114
+ icon.setAttribute("viewBox", "0 0 14 14")
115
+ icon.setAttribute("aria-hidden", "true")
116
+ const path = svgElement("path")
117
+ switch (badge.type) {
118
+ case "completion":
119
+ path.setAttribute("d", "M 3 7.2 L 5.7 9.7 L 11 4.2")
120
+ break
121
+ case "failure":
122
+ path.setAttribute("d", "M 4 4 L 10 10 M 10 4 L 4 10")
123
+ break
124
+ case "element":
125
+ path.setAttribute("d", "M 2 7 H 4.2 L 5.7 3.8 L 8.1 10.2 L 9.7 7 H 12")
126
+ break
127
+ case "snapshot": {
128
+ const ring = svgElement("circle")
129
+ ring.setAttribute("cx", "7")
130
+ ring.setAttribute("cy", "7")
131
+ ring.setAttribute("r", "3.5")
132
+ const point = svgElement("circle")
133
+ point.setAttribute("cx", "7")
134
+ point.setAttribute("cy", "7")
135
+ point.setAttribute("r", "1.2")
136
+ point.classList.add("chart-edge-badge-icon-fill")
137
+ icon.append(ring, point)
138
+ return icon
139
+ }
140
+ case "always":
141
+ path.setAttribute(
142
+ "d",
143
+ "M 2 7 C 3.3 4.5 4.9 4.5 7 7 C 9.1 9.5 10.7 9.5 12 7 C 10.7 4.5 9.1 4.5 7 7 C 4.9 9.5 3.3 9.5 2 7"
144
+ )
145
+ break
146
+ case "choice":
147
+ case "branches":
148
+ path.setAttribute("d", "M 7 11 V 7.5 M 7 7.5 L 3.5 4 M 7 7.5 L 10.5 4")
149
+ break
150
+ }
151
+ icon.append(path)
152
+ return icon
153
+ }
154
+
155
+ const edgeBadge = (badge: ChartEdgeBadge): HTMLSpanElement => {
156
+ const node = element("span", `chart-edge-badge chart-edge-badge-${badge.type}`)
157
+ node.setAttribute("aria-hidden", "true")
158
+ node.append(badgeIcon(badge))
159
+ if (badge.type === "branches") node.append(element("span", "chart-edge-badge-count", String(badge.count)))
160
+ return node
161
+ }
162
+
112
163
  const position = (
113
164
  target: HTMLElement,
114
165
  bounds: { readonly x: number; readonly y: number; readonly width: number; readonly height: number }
@@ -425,13 +476,15 @@ const render = (
425
476
  for (const laidOut of layout.edges) {
426
477
  const parentChild = laidOut.kind === "transition" && laidOut.edge.target !== null &&
427
478
  parentByState.get(laidOut.edge.target) === laidOut.edge.source
479
+ const failure = laidOut.kind === "transition" &&
480
+ laidOut.edge.badges.some((badge) => badge.type === "failure")
428
481
  const group = svgElement(
429
482
  "g",
430
483
  `chart-edge-group chart-edge-${laidOut.kind}${
431
484
  laidOut.kind === "transition"
432
485
  ? ` chart-transition-${laidOut.edge.kind} chart-edge-trigger-${laidOut.edge.trigger.type}${
433
486
  laidOut.edge.activityKind === null ? "" : ` chart-edge-activity-${laidOut.edge.activityKind}`
434
- }${parentChild ? " chart-edge-parent-child" : ""}`
487
+ }${parentChild ? " chart-edge-parent-child" : ""}${failure ? " chart-edge-failure" : ""}`
435
488
  : ""
436
489
  }`
437
490
  )
@@ -476,11 +529,21 @@ const render = (
476
529
  "button",
477
530
  `chart-edge-label chart-edge-label-${laidOut.edge.trigger.type}${
478
531
  laidOut.edge.activityKind === null ? "" : ` chart-edge-activity-${laidOut.edge.activityKind}`
479
- }${parentChild ? " chart-edge-label-parent-child" : ""}`,
480
- laidOut.edge.label
532
+ }${parentChild ? " chart-edge-label-parent-child" : ""}${failure ? " chart-edge-label-failure" : ""}${
533
+ laidOut.edge.label.length === 0 ? " chart-edge-label-icon-only" : ""
534
+ }${laidOut.edge.label.length > 0 && laidOut.edge.badges.length > 0 ? " chart-edge-label-corner-badge" : ""}`
481
535
  )
482
536
  label.type = "button"
537
+ label.setAttribute("aria-label", laidOut.edge.accessibleLabel)
483
538
  if (parentChild) label.title = "Transition declared by the parent state"
539
+ if (laidOut.edge.label.length > 0) {
540
+ label.append(element("span", "chart-edge-label-text", laidOut.edge.label))
541
+ }
542
+ if (laidOut.edge.badges.length > 0) {
543
+ const badges = element("span", "chart-edge-badges")
544
+ badges.append(...laidOut.edge.badges.map(edgeBadge))
545
+ label.append(badges)
546
+ }
484
547
  label.dataset.transitionId = laidOut.edge.transitionId
485
548
  position(label, {
486
549
  x: laidOut.label.x - laidOut.labelWidth / 2,