@cueloop/client 0.1.0-alpha.54 → 0.1.0-alpha.58

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cueloop/client",
3
- "version": "0.1.0-alpha.54",
3
+ "version": "0.1.0-alpha.58",
4
4
  "description": "The cueloop review UI: projection renderer, keyboard grammar, review rail",
5
5
  "homepage": "https://github.com/mmurakaru/cueloop#readme",
6
6
  "bugs": {
@@ -26,10 +26,10 @@
26
26
  "access": "public"
27
27
  },
28
28
  "dependencies": {
29
- "@cueloop/daemon": "0.1.0-alpha.54",
30
- "@cueloop/extension-api": "0.1.0-alpha.54",
31
- "@cueloop/integration-obsidian": "0.1.0-alpha.54",
32
- "@cueloop/schema": "0.1.0-alpha.54",
29
+ "@cueloop/daemon": "0.1.0-alpha.58",
30
+ "@cueloop/extension-api": "0.1.0-alpha.58",
31
+ "@cueloop/integration-obsidian": "0.1.0-alpha.58",
32
+ "@cueloop/schema": "0.1.0-alpha.58",
33
33
  "@opentui/core": "^0.5.8",
34
34
  "@opentui/keymap": "0.5.8",
35
35
  "@opentui/react": "^0.5.8",
@@ -50,6 +50,9 @@ export interface PrototypeSheetProps {
50
50
  type SheetStatus = "loading" | "ready" | "unsupported" | "error";
51
51
 
52
52
  const POPOVER_ROWS = 3;
53
+ /** Compose-card width, so the floating composer reads like the plan/diff one
54
+ * instead of shrinking to its content. */
55
+ const COMPOSE_COLS = 46;
53
56
  const PROTOTYPE_IMAGE_ID = 811;
54
57
  /** Page pixels scrolled per wheel notch. */
55
58
  const SCROLL_STEP = 240;
@@ -143,7 +146,11 @@ function PrototypeSheetImpl({
143
146
  const [status, setStatus] = useState<SheetStatus>("loading");
144
147
  const [errorMessage, setErrorMessage] = useState<string>("");
145
148
  const [selected, setSelected] = useState<PrototypeElement | null>(null);
146
- const [overlayCell, setOverlayCell] = useState<{ left: number; top: number } | null>(null);
149
+ const [overlayCell, setOverlayCell] = useState<{
150
+ left: number;
151
+ top: number;
152
+ regionColumns: number;
153
+ } | null>(null);
147
154
  const [actionsOpen, setActionsOpen] = useState(false);
148
155
  const [composing, setComposing] = useState(false);
149
156
  const [draftText, setDraftText] = useState("");
@@ -289,6 +296,7 @@ function PrototypeSheetImpl({
289
296
  setOverlayCell({
290
297
  left: Math.max(0, cell.column - geometry.x),
291
298
  top: Math.max(0, topRaw < POPOVER_ROWS ? topRaw + 1 : topRaw - POPOVER_ROWS),
299
+ regionColumns: geometry.width,
292
300
  });
293
301
  setActionsOpen(false);
294
302
  setComposing(false);
@@ -325,6 +333,15 @@ function PrototypeSheetImpl({
325
333
  flexDirection: "column" as const,
326
334
  backgroundColor: tokens.elevated,
327
335
  };
336
+ // keep the composer inside the region: never wider than the region, and
337
+ // clamped so it cannot run off either edge on a narrow preview
338
+ const regionColumns = overlayCell?.regionColumns ?? 0;
339
+ const composeWidth = regionColumns > 0 ? Math.min(COMPOSE_COLS, regionColumns) : COMPOSE_COLS;
340
+ const composeStyle = {
341
+ ...overlayStyle,
342
+ left: Math.max(0, Math.min(overlayStyle.left, regionColumns - composeWidth)),
343
+ width: composeWidth,
344
+ };
328
345
 
329
346
  return (
330
347
  <box
@@ -372,7 +389,7 @@ function PrototypeSheetImpl({
372
389
  </box>
373
390
  ) : null}
374
391
  {selected && composing ? (
375
- <box style={overlayStyle}>
392
+ <box style={composeStyle}>
376
393
  <AnnotationCard
377
394
  kind="comment"
378
395
  quote={selected.quote}
@@ -140,6 +140,16 @@ export async function launchPrototypeRenderer(options: LaunchOptions): Promise<P
140
140
  // `load` waits for images and styles but skips networkidle0's fixed 500ms
141
141
  // idle window, which a static local file would otherwise always pay
142
142
  await page.goto(pathToFileURL(options.filePath).href, { waitUntil: "load" });
143
+ // Render the mockup on the terminal's own surface rather than on an opaque
144
+ // page: strip the root background so it never paints a square box, and the
145
+ // capture (taken with alpha, below) lets the active terminal theme show
146
+ // through around the mockup's own components - the prototype emerges into
147
+ // whatever theme is running instead of sitting in a grey card.
148
+ await page.evaluate(() => {
149
+ for (const element of [document.documentElement, document.body]) {
150
+ element?.style.setProperty("background", "transparent", "important");
151
+ }
152
+ });
143
153
  } catch (error) {
144
154
  await page.close().catch(() => undefined);
145
155
  throw error;
@@ -148,7 +158,13 @@ export async function launchPrototypeRenderer(options: LaunchOptions): Promise<P
148
158
  return {
149
159
  viewport: options.viewport,
150
160
  async screenshot() {
151
- const buffer = await page.screenshot({ type: "png", encoding: "binary" });
161
+ // omitBackground keeps the alpha from the stripped page background, so the
162
+ // terminal composites the mockup over its own theme surface.
163
+ const buffer = await page.screenshot({
164
+ type: "png",
165
+ encoding: "binary",
166
+ omitBackground: true,
167
+ });
152
168
  return new Uint8Array(buffer as Buffer);
153
169
  },
154
170
  async elementAt(cssX, cssY) {
@@ -212,7 +228,12 @@ function elementAtScript(x: number, y: number): unknown {
212
228
  };
213
229
  const hit = document.elementFromPoint(x, y);
214
230
  if (!(hit instanceof Element)) return null;
215
- const node = componentRoot(hit);
231
+ // A click on an interactive control anchors to that control - a button in a
232
+ // grid is the target, not the grid. Everything else climbs to its component.
233
+ const control = hit.closest(
234
+ "button, a, [role='button'], input, select, textarea, label, summary",
235
+ );
236
+ const node = control ?? componentRoot(hit);
216
237
  const selector = selectorFor(node);
217
238
  if (!selector) return null;
218
239
  const text = (node.textContent || "").replace(/\s+/g, " ").trim();