@agent-native/core 0.131.3 → 0.131.5

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 (60) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +12 -0
  3. package/corpus/core/docs/content/docs-components.mdx +491 -0
  4. package/corpus/core/package.json +1 -1
  5. package/corpus/core/src/client/AgentPanel.tsx +58 -34
  6. package/corpus/core/src/localization/default-messages.ts +6 -0
  7. package/corpus/templates/content/.agents/skills/content-product-development/SKILL.md +47 -0
  8. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +3 -1
  9. package/corpus/templates/design/actions/get-design.ts +11 -3
  10. package/corpus/templates/design/actions/present-design-variants.ts +62 -5
  11. package/corpus/templates/design/app/components/design/BreakpointBar.tsx +64 -1
  12. package/corpus/templates/design/app/components/design/EditPanel.tsx +199 -25
  13. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +160 -46
  14. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +7 -1
  15. package/corpus/templates/design/app/components/design/edit-panel/effects-properties.tsx +59 -12
  16. package/corpus/templates/design/app/components/design/edit-panel/fill-properties.tsx +1 -1
  17. package/corpus/templates/design/app/components/design/edit-panel/inspector-controls.tsx +34 -29
  18. package/corpus/templates/design/app/components/design/edit-panel/stroke-properties.tsx +2 -2
  19. package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +28 -10
  20. package/corpus/templates/design/app/components/design/inspector/design-icons.tsx +15 -28
  21. package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +4 -3
  22. package/corpus/templates/design/app/components/design/multi-screen/chrome-transitions.ts +12 -8
  23. package/corpus/templates/design/app/components/design/multi-screen/culling.ts +34 -9
  24. package/corpus/templates/design/app/components/design/multi-screen/frame-geometry.ts +13 -27
  25. package/corpus/templates/design/app/components/design/multi-screen/types.ts +8 -1
  26. package/corpus/templates/design/app/components/design/multi-screen/zoom-gesture.ts +95 -0
  27. package/corpus/templates/design/app/i18n-data.ts +121 -10
  28. package/corpus/templates/design/app/pages/design-editor/data-operations.ts +45 -0
  29. package/corpus/templates/design/app/pages/design-editor/layout-operations.ts +59 -0
  30. package/corpus/templates/design/app/pages/design-editor/text-edit-utils.ts +115 -40
  31. package/corpus/templates/design/changelog/2026-07-28-generated-design-variants-no-longer-overlap-each-other-on-th.md +6 -0
  32. package/corpus/templates/design/changelog/2026-07-29-auto-layout-direction-icons-show-an-arrow.md +6 -0
  33. package/corpus/templates/design/changelog/2026-07-29-breakpoints-no-longer-overlap-neighbouring-screens.md +6 -0
  34. package/corpus/templates/design/changelog/2026-07-29-canvas-is-more-responsive-when-selecting-and-adding-frames.md +6 -0
  35. package/corpus/templates/design/changelog/2026-07-29-canvas-zoom-is-smoother-and-labels-hold-their-size.md +6 -0
  36. package/corpus/templates/design/changelog/2026-07-29-double-click-a-frame-now-drills-into-its-layers.md +6 -0
  37. package/corpus/templates/design/changelog/2026-07-29-export-preview-shows-the-real-render.md +6 -0
  38. package/corpus/templates/design/changelog/2026-07-29-figma-parity-shortcuts.md +6 -0
  39. package/corpus/templates/design/changelog/2026-07-29-more-breakpoint-width-presets.md +6 -0
  40. package/corpus/templates/design/changelog/2026-07-29-resize-a-selected-frame-to-a-device-preset.md +6 -0
  41. package/corpus/templates/design/changelog/2026-07-29-text-tool-reaches-the-right-surface.md +6 -0
  42. package/corpus/templates/design/shared/canvas-frames.ts +23 -0
  43. package/corpus/templates/design/shared/code-layer.ts +54 -2
  44. package/corpus/templates/design/shared/responsive-frame-layout.ts +55 -0
  45. package/dist/client/AgentPanel.d.ts.map +1 -1
  46. package/dist/client/AgentPanel.js +16 -5
  47. package/dist/client/AgentPanel.js.map +1 -1
  48. package/dist/localization/default-messages.d.ts +6 -0
  49. package/dist/localization/default-messages.d.ts.map +1 -1
  50. package/dist/localization/default-messages.js +6 -0
  51. package/dist/localization/default-messages.js.map +1 -1
  52. package/dist/notifications/routes.d.ts +1 -1
  53. package/dist/observability/routes.d.ts +3 -3
  54. package/dist/progress/routes.d.ts +1 -1
  55. package/dist/resources/handlers.d.ts +1 -1
  56. package/dist/server/transcribe-voice.d.ts +1 -1
  57. package/docs/content/docs-components.mdx +491 -0
  58. package/package.json +1 -1
  59. package/src/client/AgentPanel.tsx +58 -34
  60. package/src/localization/default-messages.ts +6 -0
@@ -1,7 +1,38 @@
1
1
  import { POINTER_TEXT_EDIT_ACTIVATION_DELAY_MS } from "@/components/design/design-canvas/pending-text-edit";
2
+ import { findCanvasIframeForScreen } from "@/components/design/multi-screen/iframe-targeting";
2
3
 
3
4
  import { queryUniqueSelector } from "./dom-utils";
4
5
 
6
+ /**
7
+ * Why one begin-text-edit attempt did not end up in an editing session. These
8
+ * stay distinct on purpose: a screen whose iframe is not mounted yet
9
+ * ("no-iframe") is a retry-worthy race, while an iframe that answered and does
10
+ * not have the node ("node-missing") or has it un-focused ("not-editing") is a
11
+ * different situation entirely. Collapsing them all to `false` is what made the
12
+ * board-space text bug invisible — every probe failed identically, so nothing
13
+ * distinguished "asked the wrong window" from "user has not typed yet".
14
+ */
15
+ export type BeginTextEditOutcome =
16
+ | "active"
17
+ | "done"
18
+ | "node-missing"
19
+ | "not-editing"
20
+ | "no-iframe"
21
+ | "no-reply"
22
+ /** begin-text-edit was posted; the iframe has not been re-probed yet. Never
23
+ * settle on this — it is not evidence the node was abandoned, and the
24
+ * caller's exhaustion path deletes untouched nodes. */
25
+ | "activation-requested";
26
+
27
+ export function isTextEditSessionOutcome(
28
+ outcome: BeginTextEditOutcome,
29
+ ): boolean {
30
+ return outcome === "active" || outcome === "done";
31
+ }
32
+
33
+ /** Grace period before re-probing a just-requested activation. */
34
+ const ACTIVATION_CONFIRM_DELAY_MS = 300;
35
+
5
36
  /**
6
37
  * Ask a single iframe's editor-chrome bridge whether a text-edit session for
7
38
  * `nodeId` is "active" (focused), "done" (non-empty committed text), or
@@ -13,16 +44,16 @@ import { queryUniqueSelector } from "./dom-utils";
13
44
  function queryTextEditStatus(
14
45
  iframe: HTMLIFrameElement,
15
46
  nodeId: string,
16
- ): Promise<"active" | "done" | false> {
47
+ ): Promise<"active" | "done" | "node-missing" | "not-editing" | "no-reply"> {
17
48
  const win = iframe.contentWindow;
18
- if (!win) return Promise.resolve(false);
49
+ if (!win) return Promise.resolve("no-reply");
19
50
  const correlationId = `text-edit-status-${Date.now()}-${Math.random()
20
51
  .toString(36)
21
52
  .slice(2, 6)}`;
22
53
  return new Promise((resolve) => {
23
54
  const timer = window.setTimeout(() => {
24
55
  window.removeEventListener("message", listener);
25
- resolve(false);
56
+ resolve("no-reply");
26
57
  }, 250);
27
58
  const listener = (event: MessageEvent) => {
28
59
  if (
@@ -38,7 +69,13 @@ function queryTextEditStatus(
38
69
  window.clearTimeout(timer);
39
70
  window.removeEventListener("message", listener);
40
71
  const status = event.data.status;
41
- resolve(status === "active" || status === "done" ? status : false);
72
+ if (status === "active" || status === "done") {
73
+ resolve(status);
74
+ return;
75
+ }
76
+ // Older bridges answer a bare `false` for both cases; treat that as
77
+ // "present but not editing" so the retry ladder behaves as before.
78
+ resolve(status === "missing" ? "node-missing" : "not-editing");
42
79
  };
43
80
  window.addEventListener("message", listener);
44
81
  win.postMessage(
@@ -48,31 +85,50 @@ function queryTextEditStatus(
48
85
  });
49
86
  }
50
87
 
51
- async function postBeginTextEditToPreviewIframes(
88
+ async function probeTextEdit(
89
+ screenId: string | null,
90
+ nodeId: string,
91
+ boardFileId: string | null,
92
+ ): Promise<BeginTextEditOutcome> {
93
+ if (typeof document === "undefined" || !nodeId || !screenId) {
94
+ return "no-iframe";
95
+ }
96
+ // The board surface's live iframe carries no `data-screen-iframe-id`, so the
97
+ // old `dataset.screenIframeId === screenId` filter never matched it and every
98
+ // attempt fell through to broadcasting at all the *screen* iframes — none of
99
+ // which own a board node. findCanvasIframeForScreen is the one resolver that
100
+ // already knows the board's `[data-board-surface-layer]` shape.
101
+ const iframe = findCanvasIframeForScreen(
102
+ document.body,
103
+ screenId,
104
+ boardFileId ?? undefined,
105
+ );
106
+ if (!iframe?.contentWindow) return "no-iframe";
107
+ return queryTextEditStatus(iframe, nodeId);
108
+ }
109
+
110
+ /** Probes, and asks the iframe to enter edit mode when it is not already
111
+ * editing. Reports `activation-requested` rather than the status observed
112
+ * *before* the request: that pre-activation status is not an answer about the
113
+ * session it just asked for. */
114
+ async function requestTextEdit(
52
115
  screenId: string | null,
53
116
  nodeId: string,
54
- ): Promise<"active" | "done" | false> {
55
- if (typeof document === "undefined" || !nodeId) return false;
56
- const iframes = Array.from(
57
- document.querySelectorAll<HTMLIFrameElement>(
58
- "iframe[data-design-preview-iframe]",
59
- ),
117
+ boardFileId: string | null,
118
+ ): Promise<BeginTextEditOutcome> {
119
+ const status = await probeTextEdit(screenId, nodeId, boardFileId);
120
+ if (isTextEditSessionOutcome(status) || status === "no-iframe") return status;
121
+ const iframe = findCanvasIframeForScreen(
122
+ document.body,
123
+ screenId ?? "",
124
+ boardFileId ?? undefined,
60
125
  );
61
- const targetIframes = iframes.filter(
62
- (iframe) => screenId && iframe.dataset.screenIframeId === screenId,
126
+ if (!iframe?.contentWindow) return "no-iframe";
127
+ iframe.contentWindow.postMessage(
128
+ { type: "begin-text-edit", nodeId, force: true },
129
+ "*",
63
130
  );
64
- const orderedIframes = targetIframes.length > 0 ? targetIframes : iframes;
65
- for (const iframe of orderedIframes) {
66
- const status = await queryTextEditStatus(iframe, nodeId);
67
- if (status === "active" || status === "done") return status;
68
- }
69
- orderedIframes.forEach((iframe) => {
70
- iframe.contentWindow?.postMessage(
71
- { type: "begin-text-edit", nodeId, force: true },
72
- "*",
73
- );
74
- });
75
- return false;
131
+ return "activation-requested";
76
132
  }
77
133
 
78
134
  /**
@@ -93,13 +149,20 @@ async function postBeginTextEditToPreviewIframes(
93
149
  export function scheduleBeginTextEditForScreen(
94
150
  screenId: string | null,
95
151
  nodeId: string,
96
- onExhausted?: (finalStatus: "active" | "done" | false) => void,
152
+ options?: {
153
+ /** Board file id, so a board-space text node resolves the board surface's
154
+ * iframe instead of looking for a `data-screen-iframe-id` it never has. */
155
+ boardFileId?: string | null;
156
+ onExhausted?: (finalStatus: BeginTextEditOutcome) => void;
157
+ },
97
158
  ): () => void {
98
159
  if (typeof window === "undefined") return () => {};
160
+ const onExhausted = options?.onExhausted;
161
+ const boardFileId = options?.boardFileId ?? null;
99
162
  let finished = false;
100
- let lastStatus: "active" | "done" | false = false;
163
+ let lastStatus: BeginTextEditOutcome = "no-iframe";
101
164
  const timers: number[] = [];
102
- const settle = (status: "active" | "done" | false) => {
165
+ const settle = (status: BeginTextEditOutcome) => {
103
166
  if (finished) return;
104
167
  finished = true;
105
168
  lastStatus = status;
@@ -119,19 +182,31 @@ export function scheduleBeginTextEditForScreen(
119
182
  delays.forEach((delay, index) => {
120
183
  const timer = window.setTimeout(() => {
121
184
  if (finished) return;
122
- void postBeginTextEditToPreviewIframes(screenId, nodeId).then(
123
- (status) => {
185
+ void requestTextEdit(screenId, nodeId, boardFileId).then((status) => {
186
+ if (finished) return;
187
+ lastStatus = status;
188
+ if (isTextEditSessionOutcome(status)) {
189
+ settle(status);
190
+ return;
191
+ }
192
+ if (index !== delays.length - 1) return;
193
+ if (status !== "activation-requested") {
194
+ settle(status);
195
+ return;
196
+ }
197
+ // Activation is still in flight, and the caller deletes untouched nodes
198
+ // on exhaustion. Settle on what the iframe reports, never on the request.
199
+ const confirmTimer = window.setTimeout(() => {
124
200
  if (finished) return;
125
- lastStatus = status;
126
- if (status === "active" || status === "done") {
127
- settle(status);
128
- return;
129
- }
130
- if (index === delays.length - 1) {
131
- settle(false);
132
- }
133
- },
134
- );
201
+ void probeTextEdit(screenId, nodeId, boardFileId).then(
202
+ (confirmed) => {
203
+ if (finished) return;
204
+ settle(confirmed);
205
+ },
206
+ );
207
+ }, ACTIVATION_CONFIRM_DELAY_MS);
208
+ timers.push(confirmTimer);
209
+ });
135
210
  }, delay);
136
211
  timers.push(timer);
137
212
  });
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-28
4
+ ---
5
+
6
+ Generated design variants no longer overlap each other on the overview board, and zooming or panning a board with breakpoint frames no longer flashes screen content
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-29
4
+ ---
5
+
6
+ Auto-layout direction buttons now show a direction arrow, so the flow direction is readable without hovering for the tooltip.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-29
4
+ ---
5
+
6
+ Adding a breakpoint now re-packs the board when the new frames would overlap a neighbouring screen, and the add control says it applies to all screens.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-29
4
+ ---
5
+
6
+ Selecting layers and adding frames are faster: the layer projection is reused for unchanged screens and creating a frame no longer refetches every screen's contents.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-29
4
+ ---
5
+
6
+ Canvas zoom now steps about 10% per mouse notch like Figma instead of nearly tripling, and frame labels hold a constant size throughout the gesture instead of scaling and snapping back.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-29
4
+ ---
5
+
6
+ Double-clicking a frame now selects the layer under the pointer so its styling options open, instead of switching the editor into Interact.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-29
4
+ ---
5
+
6
+ The inspector's export preview now shows the actual rendered output instead of a plain coloured rectangle, and says so when it cannot render.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-29
4
+ ---
5
+
6
+ Added Figma-parity shortcuts: A also picks the frame tool, Shift+Cmd+G ungroups, and Shift+0 resets zoom to 100%.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-29
4
+ ---
5
+
6
+ The breakpoint + menu keeps offering device widths after the default Desktop, Tablet, and Phone breakpoints are added, instead of falling back to a bare number input.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: added
3
+ date: 2026-07-29
4
+ ---
5
+
6
+ A selected frame's size is now editable, with a device-preset picker on the Size section, so an existing frame can be set to a phone, tablet, or desktop size.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-29
4
+ ---
5
+
6
+ The text tool now reaches the board's own editing surface, so a text box you draw on the canvas can be typed into immediately, and boxes left empty are cleaned up instead of lingering invisibly.
@@ -58,6 +58,29 @@ export function parseCanvasFrameGeometryById(
58
58
  );
59
59
  }
60
60
 
61
+ /** Y a new group must start at to clear existing frames, or 0 when the board is
62
+ * empty. Placing at y=0 unconditionally stacks each new group on the last. */
63
+ export function nextFreeCanvasRowY(
64
+ existing: unknown,
65
+ gap: number,
66
+ options: { ignoreFileIds?: readonly string[] } = {},
67
+ ): number {
68
+ const ignored = new Set(options.ignoreFileIds ?? []);
69
+ const frames = Object.entries(parseCanvasFrameGeometryById(existing)).filter(
70
+ ([id]) => !ignored.has(id),
71
+ );
72
+ let bottom = 0;
73
+ let sawFrame = false;
74
+ for (const [, frame] of frames) {
75
+ const y = frame.y ?? 0;
76
+ const height = frame.height ?? 0;
77
+ if (!Number.isFinite(y) || !Number.isFinite(height)) continue;
78
+ sawFrame = true;
79
+ bottom = Math.max(bottom, y + height);
80
+ }
81
+ return sawFrame ? bottom + gap : 0;
82
+ }
83
+
61
84
  export function mergeCanvasFramePlacements({
62
85
  existing,
63
86
  placements,
@@ -2230,6 +2230,38 @@ function buildProjection(
2230
2230
  };
2231
2231
  }
2232
2232
 
2233
+ /**
2234
+ * Most-recently-used projections, keyed by the exact document they came from.
2235
+ *
2236
+ * Projecting means a full HTML parse plus a tree walk, and the editor calls
2237
+ * this on nearly every selection and content change from dozens of call sites —
2238
+ * repeatedly, synchronously, on the main thread, for documents that have not
2239
+ * changed. That is the canvas "freezing while just clicking" and the sluggish
2240
+ * cursor.
2241
+ *
2242
+ * Keyed on the whole HTML string rather than a hash on purpose: a 32-bit hash
2243
+ * collision would hand a caller a confidently wrong layer tree, and every
2244
+ * id-keyed edit downstream would target the wrong node. The string is already
2245
+ * retained by the file/query cache, so the key costs a reference, not a copy.
2246
+ *
2247
+ * Callers must treat the result as read-only — it is shared now. Every consumer
2248
+ * only reads (`find`/`filter`/`map`); `applyCodeLayer*`-style writers build new
2249
+ * HTML and re-project rather than editing a projection in place.
2250
+ */
2251
+ const PROJECTION_CACHE_MAX = 24;
2252
+ const projectionCache = new Map<string, CodeLayerProjection>();
2253
+
2254
+ /** Every own field of the source, sorted, so adding a field to
2255
+ * CodeLayerSource later cannot silently start returning a projection whose
2256
+ * `.source` came from a different call. */
2257
+ function projectionSourceKey(source: CodeLayerSource): string {
2258
+ const record = source as unknown as Record<string, unknown>;
2259
+ return Object.keys(source)
2260
+ .sort()
2261
+ .map((field) => `${field}=${record[field] ?? ""}`)
2262
+ .join("\u0000");
2263
+ }
2264
+
2233
2265
  export function buildCodeLayerProjection(
2234
2266
  html: string,
2235
2267
  options: { source?: CodeLayerSource } = {},
@@ -2238,8 +2270,28 @@ export function buildCodeLayerProjection(
2238
2270
  // (e.g. `activeContent` is briefly undefined on first render). Projecting a
2239
2271
  // non-string must yield an empty projection, never crash the editor.
2240
2272
  const safeHtml = typeof html === "string" ? html : "";
2241
- return buildProjection(safeHtml, options.source ?? { kind: "inline-html" })
2242
- .projection;
2273
+ const source = options.source ?? { kind: "inline-html" };
2274
+ const key = `${projectionSourceKey(source)}\u0000${safeHtml}`;
2275
+ const cached = projectionCache.get(key);
2276
+ if (cached) {
2277
+ // Re-insert so the Map's insertion order stays least-recently-used first.
2278
+ projectionCache.delete(key);
2279
+ projectionCache.set(key, cached);
2280
+ return cached;
2281
+ }
2282
+ const projection = buildProjection(safeHtml, source).projection;
2283
+ projectionCache.set(key, projection);
2284
+ if (projectionCache.size > PROJECTION_CACHE_MAX) {
2285
+ const oldest = projectionCache.keys().next();
2286
+ if (!oldest.done) projectionCache.delete(oldest.value);
2287
+ }
2288
+ return projection;
2289
+ }
2290
+
2291
+ /** Drops every cached projection. Exists for tests that assert projection
2292
+ * identity/eviction; production has no reason to call it. */
2293
+ export function clearCodeLayerProjectionCache(): void {
2294
+ projectionCache.clear();
2243
2295
  }
2244
2296
 
2245
2297
  export function ensureCodeLayerNodeIdsInHtml(
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Geometry of one screen's responsive frame group: the primary frame plus the
3
+ * breakpoint previews painted to its right.
4
+ *
5
+ * This lives in `shared/` because both sides of the contract need it. Actions
6
+ * that *place* screens on the overview board (present-design-variants) must
7
+ * reserve the same width the canvas will actually *paint*, or the next screen
8
+ * lands underneath the previous screen's breakpoint row. Keeping the width in
9
+ * one place is what makes writer and renderer agree.
10
+ */
11
+
12
+ /** Gap between the primary frame and each breakpoint preview beside it. */
13
+ export const BREAKPOINT_FRAME_GAP = 24;
14
+
15
+ /** Drops any breakpoint whose width equals the primary frame's own width — a
16
+ * redundant duplicate of the base — also cleaning up designs authored before
17
+ * the default set excluded the primary width. */
18
+ export function visibleBreakpointWidths(
19
+ breakpointWidths: readonly number[] | undefined,
20
+ primaryWidthPx: number | undefined,
21
+ ): number[] {
22
+ const deduped = Array.from(
23
+ new Set(
24
+ (breakpointWidths ?? []).filter(
25
+ (width) => Number.isFinite(width) && width > 0,
26
+ ),
27
+ ),
28
+ );
29
+ if (primaryWidthPx === undefined || !Number.isFinite(primaryWidthPx)) {
30
+ return deduped;
31
+ }
32
+ return deduped.filter((width) => Math.abs(width - primaryWidthPx) > 1);
33
+ }
34
+
35
+ /**
36
+ * Total painted width of a screen's frame group: the primary box plus every
37
+ * breakpoint preview beside it, each drawn at the primary's own uniform
38
+ * `scale`. `visibleWidths` must already be filtered through
39
+ * `visibleBreakpointWidths` — callers differ in which width they dedupe
40
+ * against, but the arithmetic must not.
41
+ */
42
+ export function getResponsiveGroupWidth({
43
+ primaryWidth,
44
+ scale,
45
+ visibleWidths,
46
+ }: {
47
+ primaryWidth: number;
48
+ scale: number;
49
+ visibleWidths: readonly number[];
50
+ }): number {
51
+ return visibleWidths.reduce(
52
+ (total, width) => total + BREAKPOINT_FRAME_GAP + width * scale,
53
+ Math.max(1, primaryWidth),
54
+ );
55
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"AgentPanel.d.ts","sourceRoot":"","sources":["../../src/client/AgentPanel.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AgentPanel.d.ts","sourceRoot":"","sources":["../../src/client/AgentPanel.tsx"],"names":[],"mappings":"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"}
@@ -1245,14 +1245,25 @@ class AgentPanelErrorBoundary extends React.Component {
1245
1245
  return this.props.children;
1246
1246
  if (assistantUiRecoverableRenderErrorKind(this.state.error) &&
1247
1247
  this.state.staleIndexRecoveryCount < 2) {
1248
- return (_jsx("div", { className: "flex h-full items-center justify-center p-6 text-center text-xs text-muted-foreground", children: "Reloading chat UI..." }));
1248
+ return _jsx(AgentPanelReloadingNotice, {});
1249
1249
  }
1250
- return (_jsxs("div", { className: "flex h-full flex-col items-center justify-center gap-3 p-6 text-center", children: [_jsxs("div", { className: "max-w-[260px] space-y-1", children: [_jsx("p", { className: "text-sm font-medium text-foreground", children: "Agent panel hit an internal UI error." }), _jsx("p", { className: "text-xs leading-relaxed text-muted-foreground", children: "The app is still usable. Reset the panel to reload the chat UI." })] }), _jsx("button", { type: "button", className: "rounded-md border border-border bg-background px-3 py-1.5 text-xs font-medium text-foreground hover:bg-accent", onClick: () => {
1251
- this.setState({ error: null, staleIndexRecoveryCount: 0 });
1252
- this.props.onReset();
1253
- }, children: "Reset agent panel" }), _jsx(ErrorReportActions, { appName: "Agent panel", title: "Agent panel UI error", details: this.state.error.message, issueTitle: "Agent panel UI error", className: "max-w-[260px]", feedbackClassName: "h-7", githubClassName: "h-7" })] }));
1250
+ return (_jsx(AgentPanelErrorFallback, { details: this.state.error.message, onReset: () => {
1251
+ this.setState({ error: null, staleIndexRecoveryCount: 0 });
1252
+ this.props.onReset();
1253
+ } }));
1254
1254
  }
1255
1255
  }
1256
+ // The boundary must stay a class (componentDidCatch), but its copy still has to
1257
+ // come from the catalog like every other string in this file — so the fallback
1258
+ // UI lives in function components that can call useT.
1259
+ function AgentPanelReloadingNotice() {
1260
+ const t = useT();
1261
+ return (_jsx("div", { className: "flex h-full items-center justify-center p-6 text-center text-xs text-muted-foreground", children: t("agentPanel.uiError.reloading") }));
1262
+ }
1263
+ function AgentPanelErrorFallback({ details, onReset, }) {
1264
+ const t = useT();
1265
+ return (_jsxs("div", { className: "flex h-full flex-col items-center justify-center gap-3 p-6 text-center", children: [_jsxs("div", { className: "max-w-[260px] space-y-1", children: [_jsx("p", { className: "text-sm font-medium text-foreground", children: t("agentPanel.uiError.title") }), _jsx("p", { className: "text-xs leading-relaxed text-muted-foreground", children: t("agentPanel.uiError.description") })] }), _jsx("button", { type: "button", className: "rounded-md border border-border bg-background px-3 py-1.5 text-xs font-medium text-foreground hover:bg-accent", onClick: onReset, children: t("agentPanel.uiError.reset") }), _jsx(ErrorReportActions, { appName: "Agent panel", title: t("agentPanel.uiError.title"), details: details, issueTitle: "Agent panel UI error", className: "max-w-[260px]", feedbackClassName: "h-7", githubClassName: "h-7" })] }));
1266
+ }
1256
1267
  export function AgentPanel(props) {
1257
1268
  const [resetKey, setResetKey] = useState(0);
1258
1269
  const resetPanel = useCallback(() => {