@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.
|
|
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.
|
|
30
|
-
"@cueloop/extension-api": "0.1.0-alpha.
|
|
31
|
-
"@cueloop/integration-obsidian": "0.1.0-alpha.
|
|
32
|
-
"@cueloop/schema": "0.1.0-alpha.
|
|
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<{
|
|
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={
|
|
392
|
+
<box style={composeStyle}>
|
|
376
393
|
<AnnotationCard
|
|
377
394
|
kind="comment"
|
|
378
395
|
quote={selected.quote}
|
package/src/prototype-browser.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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();
|