@theoremjs/studio 0.3.4-next.454.gaa3f549 → 0.3.4-next.458.gbf7b487

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 (28) hide show
  1. package/package.json +4 -4
  2. package/page/assets/{Banner-QCiHVb5K.js → Banner-C4MPbvft.js} +2 -2
  3. package/page/assets/{ConsoleFrame-DqN62wL7.js → ConsoleFrame-BkzieVRC.js} +1 -1
  4. package/page/assets/{ContextMenu-DIzJdlQ5.js → ContextMenu-BGP2gdee.js} +2 -2
  5. package/page/assets/{ToolResultCharts-CjuviquY.js → ToolResultCharts-xDwNDd-T.js} +1 -1
  6. package/page/assets/{TraceInspector-CwGSe8Oe.js → TraceInspector-CHpdhiVX.js} +1 -1
  7. package/page/assets/{TraceOverview-isg4ubrd.js → TraceOverview-DCGew7UN.js} +1 -1
  8. package/page/assets/{browser-engine-DA4ZywPN.js → browser-engine-Ca2pvYX0.js} +1 -1
  9. package/page/assets/{browser-transport-B0zaH_Aw.js → browser-transport-DYgEItHi.js} +3 -3
  10. package/page/assets/{export-agent-vV5u7tzN.js → export-agent-5rXmF-g1.js} +1 -1
  11. package/page/assets/{guardrail-tester-D70vg-Zv.js → guardrail-tester-B-ZfQFVu.js} +1 -1
  12. package/page/assets/{index-CvrD0wqP.js → index-Dajtrq_Z.js} +6 -6
  13. package/page/assets/{studio-code-pane-CPon5udY.js → studio-code-pane-CKYRitdD.js} +1 -1
  14. package/page/assets/{studio-console-BSV-XHe9.js → studio-console-DwhqnNyw.js} +1 -1
  15. package/page/assets/{studio-decision-Dk1Tsfah.js → studio-decision-Ckj4UNNt.js} +1 -1
  16. package/page/assets/{studio-embedding-BkBuVy1T.js → studio-embedding-8qL_dVlz.js} +1 -1
  17. package/page/assets/{studio-host-console-C6f389Xp.js → studio-host-console-BXwwloN4.js} +2 -2
  18. package/page/assets/{studio-labels-DEEMSKuk.js → studio-labels-C1pvg0JC.js} +1 -1
  19. package/page/assets/{studio-live-uDkVyN2h.js → studio-live-26srJ74m.js} +1 -1
  20. package/page/assets/{studio-map-BVIl4fqd.js → studio-map-C5zsJusF.js} +1 -1
  21. package/page/assets/{studio-trace-replay-DG90ujMk.js → studio-trace-replay-B38TicvO.js} +1 -1
  22. package/page/assets/{use-one-call-DIEEQ4qF.js → use-one-call-DjVkallj.js} +1 -1
  23. package/page/index.html +5 -5
  24. package/ui/pan.js +5 -1
  25. package/ui/studio-map.js +7 -7
  26. package/ui/tree-map.css +43 -0
  27. package/ui/tree-map.d.ts +7 -1
  28. package/ui/tree-map.js +10 -5
package/ui/pan.js CHANGED
@@ -21,6 +21,7 @@ export function fieldStart(field, scroller) {
21
21
  top: box.top - port.top + scroller.scrollTop,
22
22
  };
23
23
  }
24
+ const clamp = (value, most) => Math.min(Math.max(value, 0), Math.max(most, 0));
24
25
  /**
25
26
  * Scroll the box around `field` to `at`, once it can: a field that is still opening has no box that
26
27
  * scrolls yet, so it tries again each frame until the scroll lands. Returns what stops the tries.
@@ -32,7 +33,10 @@ export function scrollOnce(field, at) {
32
33
  tries -= 1;
33
34
  const scroller = scrollerOf(field);
34
35
  if (scroller && scroller.scrollWidth > scroller.clientWidth) {
35
- const { left, top } = at(scroller);
36
+ const wanted = at(scroller);
37
+ // A place past either end lands at that end.
38
+ const left = clamp(wanted.left, scroller.scrollWidth - scroller.clientWidth);
39
+ const top = clamp(wanted.top, scroller.scrollHeight - scroller.clientHeight);
36
40
  scroller.scrollTo({ left, top, behavior: 'instant' });
37
41
  if (Math.abs(scroller.scrollLeft - left) < 1 && Math.abs(scroller.scrollTop - top) < 1)
38
42
  return;
package/ui/studio-map.js CHANGED
@@ -212,14 +212,15 @@ function useLit(layout) {
212
212
  return { lit, on, onLines, lights };
213
213
  }
214
214
  /**
215
- * A family, and the map with or without detail, each start from the top left, or as near it as
216
- * shows the node that is open.
215
+ * A family starts from the top left. The map, opened or turned to or from detail, centres the node
216
+ * that is open, or starts from the top left when none is.
217
217
  */
218
218
  function useStart(field, family, open) {
219
219
  const latest = useRef(open.place);
220
220
  latest.current = open.place;
221
221
  // invariant: the sizes are one of two constants, so they change exactly when the detail does.
222
222
  const { sizes } = open;
223
+ // why: Not on a click: the node clicked is already in view, and the map stays where the reader put it.
223
224
  useEffect(() => {
224
225
  const node = field.current;
225
226
  if (!node)
@@ -228,13 +229,12 @@ function useStart(field, family, open) {
228
229
  const at = family === undefined ? place : undefined;
229
230
  // The field starts past the room around it.
230
231
  return scrollOnce(node, (scroller) => {
231
- const hidden = at !== undefined &&
232
- (at.x + sizes.node.width > scroller.clientWidth ||
233
- at.y + at.height > scroller.clientHeight);
234
232
  const { left, top } = fieldStart(node, scroller);
233
+ if (at === undefined)
234
+ return { left, top };
235
235
  return {
236
- left: left + (hidden ? at.x - sizes.padding : 0),
237
- top: top + (hidden ? at.y - sizes.padding - sizes.heading : 0),
236
+ left: left + at.x + sizes.node.width / 2 - scroller.clientWidth / 2,
237
+ top: top + at.y + at.height / 2 - scroller.clientHeight / 2,
238
238
  };
239
239
  });
240
240
  }, [field, family, sizes]);
package/ui/tree-map.css CHANGED
@@ -13,3 +13,46 @@
13
13
  .studio-tree-map-lines .map-line {
14
14
  stroke: color-mix(in srgb, var(--color-border-emphasized) 60%, var(--color-background-surface));
15
15
  }
16
+
17
+ /*
18
+ * Feeds draw in as the loader's map draws (read-map.css), one after another: the line from the
19
+ * tree, then the token at its end. Hidden, they leave in the reverse order.
20
+ * invariant: Transitions, not keyframes, so drawing and leaving both ease, and a turn mid-draw
21
+ * goes back from where it is.
22
+ */
23
+ .studio-tree-map {
24
+ --feed-step: 70ms;
25
+ }
26
+
27
+ .studio-tree-map-lines [data-feed] {
28
+ stroke-dasharray: 1;
29
+ stroke-dashoffset: 0;
30
+ transition: stroke-dashoffset var(--duration-medium, 240ms) var(--ease-standard, ease-out)
31
+ calc(var(--feed-i) * var(--feed-step));
32
+ }
33
+
34
+ .studio-tree-map > [data-feed] {
35
+ transition: opacity var(--duration-medium, 240ms) var(--ease-standard, ease-out)
36
+ calc(var(--feed-i) * var(--feed-step) + var(--duration-medium, 240ms));
37
+ }
38
+
39
+ .studio-tree-map[data-feeds="hidden"] > [data-feed] {
40
+ opacity: 0;
41
+ transition-delay: calc((var(--feed-n) - var(--feed-i)) * var(--feed-step));
42
+ }
43
+
44
+ .studio-tree-map[data-feeds="hidden"] .studio-tree-map-lines [data-feed] {
45
+ stroke-dashoffset: var(--feed-from);
46
+ transition-delay: calc(
47
+ (var(--feed-n) - var(--feed-i)) *
48
+ var(--feed-step) +
49
+ var(--duration-medium, 240ms)
50
+ );
51
+ }
52
+
53
+ @media (prefers-reduced-motion: reduce) {
54
+ .studio-tree-map-lines [data-feed],
55
+ .studio-tree-map > [data-feed] {
56
+ transition: none;
57
+ }
58
+ }
package/ui/tree-map.d.ts CHANGED
@@ -3,5 +3,11 @@ export interface StudioTreeMapProps {
3
3
  workspace: StudioWorkspace;
4
4
  /** The keys of the agents to draw, in the workspace's order; every agent when unset. */
5
5
  agents?: readonly string[] | undefined;
6
+ /**
7
+ * Whether what feeds the tree is drawn beside it. Turned on, each feed draws in after the one
8
+ * before, its line from the tree first, as the loader's map draws; turned off, they leave in the
9
+ * reverse order. Shown when unset.
10
+ */
11
+ feeds?: 'shown' | 'hidden' | undefined;
6
12
  }
7
- export declare function StudioTreeMap({ workspace, agents }: StudioTreeMapProps): import("react").JSX.Element;
13
+ export declare function StudioTreeMap({ workspace, agents, feeds: shown }: StudioTreeMapProps): import("react").JSX.Element;
package/ui/tree-map.js CHANGED
@@ -142,7 +142,9 @@ function linePath(from, to) {
142
142
  const x = from.x + TRUNK;
143
143
  return `M ${x} ${from.y + HALF} V ${to.y - TURN} Q ${x} ${to.y} ${x + TURN} ${to.y} H ${to.x - LINE_GAP}`;
144
144
  }
145
- export function StudioTreeMap({ workspace, agents }) {
145
+ /** The order a feed draws in, and which end its line starts from: 1 the path's start, -1 its end. */
146
+ const feedStyle = (index, from = 1) => ({ '--feed-i': index, '--feed-from': from });
147
+ export function StudioTreeMap({ workspace, agents, feeds: shown = 'shown' }) {
146
148
  const root = useRef(null);
147
149
  const rows = rowsOf(workspace, agents);
148
150
  const feeds = feedsOf(workspace, rows);
@@ -166,12 +168,14 @@ export function StudioTreeMap({ workspace, agents }) {
166
168
  return above && feed.depth <= above.depth ? [railFor(feed, above)] : [];
167
169
  });
168
170
  const width = Math.max(GUESS, ...feeds.map(feedRight), ...rails) + PAD;
169
- return (_jsxs("div", { ref: root, className: "studio-tree-map", style: { width, height }, children: [_jsxs("svg", { className: "studio-tree-map-lines", width: width, height: height, "aria-hidden": "true", children: [rows.map((row) => row.parent && (_jsx("path", { className: "map-line", d: linePath(row.parent, row) }, rowId(row)))), feeds.flatMap((feed) => feed.into.map((id) => {
171
+ const order = new Map(feeds.map((feed, index) => [feed.id, index]));
172
+ return (_jsxs("div", { ref: root, className: "studio-tree-map", "data-feeds": shown, style: { width, height, '--feed-n': feeds.length }, children: [_jsxs("svg", { className: "studio-tree-map-lines", width: width, height: height, "aria-hidden": "true", children: [rows.map((row) => row.parent && (_jsx("path", { className: "map-line", d: linePath(row.parent, row) }, rowId(row)))), feeds.flatMap((feed) => feed.into.map((id) => {
170
173
  const row = byId.get(id);
171
174
  if (!row)
172
175
  return null;
173
176
  const { d } = mapCurve({ x: feedX - LINE_GAP, y: feed.y }, { x: right(row) + LINE_GAP, y: row.y });
174
- return _jsx("path", { className: "map-line", d: d }, `${feed.id}>${id}`);
177
+ // The line runs from the feed to the row; it draws from the row.
178
+ return (_jsx("path", { className: "map-line", d: d, pathLength: 1, "data-feed": "", style: feedStyle(order.get(feed.id) ?? 0, -1) }, `${feed.id}>${id}`));
175
179
  })), feeds.map((feed) => {
176
180
  const above = feed.under === undefined ? undefined : feedById.get(feed.under);
177
181
  if (above === undefined)
@@ -182,9 +186,10 @@ export function StudioTreeMap({ workspace, agents }) {
182
186
  const d = feed.depth > above.depth
183
187
  ? linePath(from, { x: feedLeft(feed), y: feed.y })
184
188
  : sidePath({ x: feedRight(feed) + LINE_GAP, y: feed.y }, { x: feedRight(above) + LINE_GAP, y: above.y }, railFor(feed, above));
185
- return _jsx("path", { className: "map-line", d: d }, `${feed.id}^`);
189
+ // A turn in runs from the feed above; a line round the side runs from this one.
190
+ return (_jsx("path", { className: "map-line", d: d, pathLength: 1, "data-feed": "", style: feedStyle(order.get(feed.id) ?? 0, feed.depth > above.depth ? 1 : -1) }, `${feed.id}^`));
186
191
  })] }), rows.map((row) => {
187
192
  const draft = drafts.get(row.agent) ?? createBlankDraft();
188
193
  return (_jsx(MapToken, { id: rowId(row), label: row.node.label, icon: nodeIcon(draft, row.node.ref), x: row.x, y: row.y }, rowId(row)));
189
- }), feeds.map((feed) => (_jsx(MapToken, { id: feed.id, label: feed.label, icon: feed.icon, x: feedLeft(feed), y: feed.y }, feed.id)))] }));
194
+ }), feeds.map((feed) => (_jsx(MapToken, { id: feed.id, label: feed.label, icon: feed.icon, x: feedLeft(feed), y: feed.y, "data-feed": "", style: feedStyle(order.get(feed.id) ?? 0) }, feed.id)))] }));
190
195
  }