@blocksdiy/react-common 1.52.2 → 1.54.0

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,184 @@
1
+ // A floating panel's size, headless: resized from the edges its corner anchoring leaves free by
2
+ // a pointer drag (with capture) or arrow keys on a focused handle, clamped to a floor and to the
3
+ // viewport, remembered per browser. The hook owns the math and the memory; the component owns
4
+ // the handles' markup and spreads `getHandleProps(axis)` on them.
5
+ import { useCallback, useRef, useState } from "react";
6
+ const clampNumber = (value, min, max) => Math.min(Math.max(value, min), max);
7
+ /**
8
+ * A size the panel can take inside `viewport`: never below the floor, never past the viewport
9
+ * minus the inset on both sides — unless the viewport itself is smaller than the floor, where
10
+ * the floor wins (CSS still caps the box to the viewport).
11
+ */
12
+ export const clampPanelSize = (size, viewport, { minSize, inset }) => {
13
+ const maxWidth = Math.max(minSize.width, viewport.width - 2 * inset);
14
+ const maxHeight = Math.max(minSize.height, viewport.height - 2 * inset);
15
+ return {
16
+ width: Math.round(clampNumber(size.width, minSize.width, maxWidth)),
17
+ height: Math.round(clampNumber(size.height, minSize.height, maxHeight)),
18
+ };
19
+ };
20
+ /** A stored size, or null for anything but two finite positive numbers. */
21
+ export const parseStoredPanelSize = (raw) => {
22
+ if (!raw) {
23
+ return null;
24
+ }
25
+ try {
26
+ const parsed = JSON.parse(raw);
27
+ if (typeof parsed !== "object" || parsed === null) {
28
+ return null;
29
+ }
30
+ const { width, height } = parsed;
31
+ if (typeof width !== "number" ||
32
+ typeof height !== "number" ||
33
+ !Number.isFinite(width) ||
34
+ !Number.isFinite(height) ||
35
+ width <= 0 ||
36
+ height <= 0) {
37
+ return null;
38
+ }
39
+ return { width, height };
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ };
45
+ /**
46
+ * The size a drag has reached. The panel is anchored at the viewport's bottom-start corner, so
47
+ * growth is toward the end edge and upward — the horizontal delta flips in RTL, and a drag up
48
+ * counts as more height.
49
+ */
50
+ export const panelSizeFromDrag = (drag, pointer, bounds) => {
51
+ const dx = (pointer.clientX - drag.startX) * (drag.isRtl ? -1 : 1);
52
+ const dy = drag.startY - pointer.clientY;
53
+ return clampPanelSize({
54
+ width: drag.axis === "height" ? drag.startSize.width : drag.startSize.width + dx,
55
+ height: drag.axis === "width" ? drag.startSize.height : drag.startSize.height + dy,
56
+ }, drag.viewport, bounds);
57
+ };
58
+ /** The key's step for a handle: toward the end edge and up grow; null for a key the axis ignores. */
59
+ export const panelKeyboardDelta = (key, axis, step, isRtl) => {
60
+ const grow = isRtl ? "ArrowLeft" : "ArrowRight";
61
+ const shrink = isRtl ? "ArrowRight" : "ArrowLeft";
62
+ if (axis !== "height" && key === grow) {
63
+ return { dx: step, dy: 0 };
64
+ }
65
+ if (axis !== "height" && key === shrink) {
66
+ return { dx: -step, dy: 0 };
67
+ }
68
+ if (axis !== "width" && key === "ArrowUp") {
69
+ return { dx: 0, dy: step };
70
+ }
71
+ if (axis !== "width" && key === "ArrowDown") {
72
+ return { dx: 0, dy: -step };
73
+ }
74
+ return null;
75
+ };
76
+ const KEYBOARD_STEP = 16;
77
+ const KEYBOARD_STEP_LARGE = 64;
78
+ const readStoredSize = (storageKey) => {
79
+ if (!storageKey) {
80
+ return null;
81
+ }
82
+ try {
83
+ return parseStoredPanelSize(window.localStorage.getItem(storageKey));
84
+ }
85
+ catch {
86
+ return null;
87
+ }
88
+ };
89
+ const storeSize = (storageKey, size) => {
90
+ if (!storageKey) {
91
+ return;
92
+ }
93
+ try {
94
+ window.localStorage.setItem(storageKey, JSON.stringify(size));
95
+ }
96
+ catch {
97
+ // Private mode or a full store: the panel still resizes, it just forgets on reload.
98
+ }
99
+ };
100
+ /** The panel's box, the viewport it floats in, and its direction. */
101
+ const measure = (panel) => {
102
+ const rect = panel.getBoundingClientRect();
103
+ return {
104
+ size: { width: rect.width, height: rect.height },
105
+ viewport: { width: document.documentElement.clientWidth, height: document.documentElement.clientHeight },
106
+ isRtl: getComputedStyle(panel).direction === "rtl",
107
+ };
108
+ };
109
+ export const useResizablePanel = (panelRef, { defaultSize, minSize, inset, storageKey }) => {
110
+ const [size, setSize] = useState(() => {
111
+ const stored = readStoredSize(storageKey);
112
+ if (!stored) {
113
+ return defaultSize;
114
+ }
115
+ // Remembered under an earlier, smaller floor: never below today's (CSS caps it to the viewport).
116
+ return {
117
+ width: Math.max(stored.width, minSize.width),
118
+ height: Math.max(stored.height, minSize.height),
119
+ };
120
+ });
121
+ const [isResizing, setResizing] = useState(false);
122
+ const dragRef = useRef(null);
123
+ const bounds = { minSize, inset };
124
+ const commit = useCallback((next) => {
125
+ setSize(next);
126
+ storeSize(storageKey, next);
127
+ }, [storageKey]);
128
+ const getHandleProps = (axis) => ({
129
+ onPointerDown: (event) => {
130
+ const panel = panelRef.current;
131
+ if (!panel || event.button !== 0) {
132
+ return;
133
+ }
134
+ const measured = measure(panel);
135
+ dragRef.current = {
136
+ pointerId: event.pointerId,
137
+ axis,
138
+ startX: event.clientX,
139
+ startY: event.clientY,
140
+ startSize: measured.size,
141
+ viewport: measured.viewport,
142
+ isRtl: measured.isRtl,
143
+ };
144
+ event.currentTarget.setPointerCapture(event.pointerId);
145
+ event.preventDefault(); // no text selection while dragging
146
+ setResizing(true);
147
+ },
148
+ onPointerMove: (event) => {
149
+ const drag = dragRef.current;
150
+ if (!drag || drag.pointerId !== event.pointerId) {
151
+ return;
152
+ }
153
+ setSize(panelSizeFromDrag(drag, event, bounds));
154
+ },
155
+ onPointerUp: (event) => {
156
+ const drag = dragRef.current;
157
+ if (!drag || drag.pointerId !== event.pointerId) {
158
+ return;
159
+ }
160
+ dragRef.current = null;
161
+ setResizing(false);
162
+ // The drag's own final value — a DOM measurement here could lag the last move by a frame.
163
+ commit(panelSizeFromDrag(drag, event, bounds));
164
+ },
165
+ onPointerCancel: () => {
166
+ dragRef.current = null;
167
+ setResizing(false);
168
+ },
169
+ onKeyDown: (event) => {
170
+ const panel = panelRef.current;
171
+ if (!panel) {
172
+ return;
173
+ }
174
+ const { size: current, viewport, isRtl } = measure(panel);
175
+ const delta = panelKeyboardDelta(event.key, axis, event.shiftKey ? KEYBOARD_STEP_LARGE : KEYBOARD_STEP, isRtl);
176
+ if (!delta) {
177
+ return;
178
+ }
179
+ event.preventDefault();
180
+ commit(clampPanelSize({ width: current.width + delta.dx, height: current.height + delta.dy }, viewport, bounds));
181
+ },
182
+ });
183
+ return { size, isResizing, getHandleProps };
184
+ };
@@ -28,12 +28,17 @@ export declare const APPROVAL_STATUS_LINE: {
28
28
  };
29
29
  /** Appended to a decided card's status while another request of the pause is open. */
30
30
  export declare const WAITING_FOR_OTHER_SUFFIX = " \u00B7 waiting for your decision on the other request";
31
- export type ApprovalDecision = "approve" | "reject";
31
+ export type ApprovalDecision = "approve" | "edit" | "reject";
32
+ /** What a stamp records: an edit is an approval of the edited args. */
33
+ type RecordedDecision = "approve" | "reject";
32
34
  export type InterruptAnswer = {
33
35
  type: "respond";
34
36
  message: unknown;
35
37
  } | {
36
- type: ApprovalDecision;
38
+ type: "approve" | "reject";
39
+ } | {
40
+ type: "edit";
41
+ args: Record<string, unknown>;
37
42
  };
38
43
  export interface InterruptRequest {
39
44
  interruptId: string;
@@ -51,7 +56,7 @@ export interface InterruptRequest {
51
56
  }
52
57
  export interface ToolApprovalStamp {
53
58
  toolCallId: string;
54
- decision: ApprovalDecision;
59
+ decision: RecordedDecision;
55
60
  toolName: string;
56
61
  /** Absent on records written before display names. */
57
62
  displayName?: string | null;
@@ -64,6 +69,8 @@ export interface ApprovalCardView {
64
69
  args: Record<string, unknown>;
65
70
  status: "waiting" | "approved" | "rejected";
66
71
  statusLine: string;
72
+ /** True while the card waits AND the request allows an `edit` decision. Absent on older builds: the card stays read-only. */
73
+ editable?: boolean;
67
74
  /** Set only while this card can still be decided. */
68
75
  request: {
69
76
  interruptId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"agui-interrupts.d.ts","sourceRoot":"","sources":["../../src/utils/agui-interrupts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agui-interrupts.d.ts","sourceRoot":"","sources":["../../src/utils/agui-interrupts.ts"],"names":[],"mappings":"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"}
@@ -116,7 +116,15 @@ export const INTERRUPT_NOT_OPEN_ERROR = "answerInterrupt: nothing is waiting for
116
116
  * key, which the server refuses.
117
117
  */
118
118
  export const respondMessageOf = (answer) => JSON.stringify(answer ?? null);
119
- const decisionOf = (answer) => answer.type === "respond" ? { type: "respond", message: respondMessageOf(answer.message) } : { type: answer.type };
119
+ const decisionOf = (answer, request) => {
120
+ if (answer.type === "respond") {
121
+ return { type: "respond", message: respondMessageOf(answer.message) };
122
+ }
123
+ if (answer.type === "edit") {
124
+ return { type: "edit", edited_action: { name: request.name, args: answer.args } };
125
+ }
126
+ return { type: answer.type };
127
+ };
120
128
  /**
121
129
  * The welcome seed (`initialUserChoices`): connect writes an ask_user call that no run made,
122
130
  * so nothing is parked behind it. Its signature is the one the server used
@@ -166,7 +174,7 @@ export const buildResumeEntries = (interrupts, requests, answers) => {
166
174
  if (!answer) {
167
175
  return null;
168
176
  }
169
- decisions.push(decisionOf(answer));
177
+ decisions.push(decisionOf(answer, request));
170
178
  }
171
179
  entries.push({ interruptId: interrupt.id, status: "resolved", payload: { decisions } });
172
180
  }
@@ -203,10 +211,10 @@ export const localStampsByAnchor = (requests, answers) => {
203
211
  list.push({
204
212
  // A sub-agent's call is not in this transcript; its request key stands in.
205
213
  toolCallId: request.toolCallId ?? request.key,
206
- decision: answer.type,
214
+ decision: answer.type === "edit" ? "approve" : answer.type,
207
215
  toolName: request.name,
208
216
  displayName: request.displayName,
209
- args: request.args,
217
+ args: answer.type === "edit" ? answer.args : request.args,
210
218
  });
211
219
  out.set(request.anchorToolCallId, list);
212
220
  }
@@ -288,7 +296,7 @@ const titleOf = (toolName) => {
288
296
  const words = toolWords(toolName);
289
297
  return words.charAt(0).toUpperCase() + words.slice(1);
290
298
  };
291
- const statusOf = (decision) => decision === "approve" ? "approved" : "rejected";
299
+ const statusOf = (decision) => decision === "reject" ? "rejected" : "approved";
292
300
  export const approvalCardsForToolCall = ({ toolCallId, toolName, toolArgs, toolResult, toolMessage, requests, answers, localStamps, }) => {
293
301
  const live = requests.filter((request) => request.anchorToolCallId === toolCallId && isApprovalRequest(request));
294
302
  if (live.length > 0) {
@@ -302,6 +310,7 @@ export const approvalCardsForToolCall = ({ toolCallId, toolName, toolArgs, toolR
302
310
  title: titleOf(request.displayName ?? request.name),
303
311
  args: request.args,
304
312
  status,
313
+ editable: status === "waiting" && request.allowedDecisions.includes("edit"),
305
314
  statusLine: waitingForOthers
306
315
  ? `${APPROVAL_STATUS_LINE[status]}${WAITING_FOR_OTHER_SUFFIX}`
307
316
  : APPROVAL_STATUS_LINE[status],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocksdiy/react-common",
3
- "version": "1.52.2",
3
+ "version": "1.54.0",
4
4
  "type": "module",
5
5
  "description": "React common",
6
6
  "keywords": [],
@@ -39,7 +39,7 @@
39
39
  "penpal": "^8.0.0",
40
40
  "react": "^19.2.8",
41
41
  "use-stick-to-bottom": "1.1.4",
42
- "@blocksdiy/blocks-client-api": "1.26.0"
42
+ "@blocksdiy/blocks-client-api": "1.5.0"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@types/react": "^19.2.18",