@swmansion/argent 0.11.0 → 0.12.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.
- package/bin/argent-android-devtools-0.1.0.apk +0 -0
- package/bin/argent-simulator-server.cjs +11 -3
- package/bin/darwin/ax-service +0 -0
- package/bin/darwin/resources/android/LICENSE.txt +186 -0
- package/bin/darwin/resources/android/README.md +11 -0
- package/bin/darwin/resources/android/arm64-v8a/libscreen-sharing-agent.so +0 -0
- package/bin/darwin/resources/android/armeabi-v7a/libscreen-sharing-agent.so +0 -0
- package/bin/darwin/resources/android/screen-sharing-agent.jar +0 -0
- package/bin/darwin/resources/android/x86_64/libscreen-sharing-agent.so +0 -0
- package/bin/darwin/simulator-server +0 -0
- package/bin/linux/resources/android/LICENSE.txt +186 -0
- package/bin/linux/resources/android/README.md +11 -0
- package/bin/linux/resources/android/arm64-v8a/libscreen-sharing-agent.so +0 -0
- package/bin/linux/resources/android/armeabi-v7a/libscreen-sharing-agent.so +0 -0
- package/bin/linux/resources/android/screen-sharing-agent.jar +0 -0
- package/bin/linux/resources/android/x86_64/libscreen-sharing-agent.so +0 -0
- package/bin/linux/simulator-server +0 -0
- package/bin/linux-arm64/resources/android/LICENSE.txt +186 -0
- package/bin/linux-arm64/resources/android/README.md +11 -0
- package/bin/linux-arm64/resources/android/arm64-v8a/libscreen-sharing-agent.so +0 -0
- package/bin/linux-arm64/resources/android/armeabi-v7a/libscreen-sharing-agent.so +0 -0
- package/bin/linux-arm64/resources/android/screen-sharing-agent.jar +0 -0
- package/bin/linux-arm64/resources/android/x86_64/libscreen-sharing-agent.so +0 -0
- package/bin/linux-arm64/simulator-server +0 -0
- package/dist/cli-cmds.mjs +139 -26
- package/dist/cli.js +0 -3
- package/dist/cli.js.map +1 -1
- package/dist/installer.mjs +111 -97
- package/dist/mcp-server.mjs +204 -62
- package/dist/preview-ui/index.html +4500 -645
- package/dist/preview-ui/theme.css +231 -0
- package/dist/preview-window/main.cjs +182 -0
- package/dist/tool-server.cjs +7719 -3531
- package/dylibs/libArgentInjectionBootstrap.dylib +0 -0
- package/dylibs/libKeyboardPatch.dylib +0 -0
- package/dylibs/libNativeDevtoolsIos.dylib +0 -0
- package/package.json +4 -1
- package/rules/argent.md +8 -2
- package/scripts/postinstall.cjs +6 -2
- package/skills/argent-device-interact/SKILL.md +36 -28
- package/skills/argent-lens/SKILL.md +101 -0
- package/skills/argent-metro-debugger/SKILL.md +18 -16
- package/skills/argent-react-native-app-workflow/SKILL.md +8 -8
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/* =============================================================================
|
|
2
|
+
* Argent Preview — THEME
|
|
3
|
+
*
|
|
4
|
+
* The ONE place every visual value lives. index.html must not contain a single
|
|
5
|
+
* hardcoded colour, pixel, duration, easing, z-index or opacity — only
|
|
6
|
+
* var(--token) references into this file. Tokens are named for what they ARE
|
|
7
|
+
* (their role), not an abstract scale, and shared only when they represent the
|
|
8
|
+
* same design decision. The "Motion & feel" block at the bottom is also read
|
|
9
|
+
* by the JS at boot (getComputedStyle), so animation feel is configured here
|
|
10
|
+
* too — not buried in the script.
|
|
11
|
+
*
|
|
12
|
+
* Light and dark are colocated per token via light-dark(LIGHT, DARK). The
|
|
13
|
+
* active side follows `color-scheme` on :root — the OS theme by default, or a
|
|
14
|
+
* forced value the in-app theme toggle writes to documentElement.style. So
|
|
15
|
+
* every consumer themes for free, with no second palette to keep in sync.
|
|
16
|
+
* ========================================================================== */
|
|
17
|
+
|
|
18
|
+
:root {
|
|
19
|
+
color-scheme: light dark;
|
|
20
|
+
|
|
21
|
+
/* ── Palette ─────────────────────────────────────────────────────────── */
|
|
22
|
+
/* Light + dark live side by side via light-dark(LIGHT, DARK); the active
|
|
23
|
+
side follows the `color-scheme` above (so the OS theme by default, or a
|
|
24
|
+
forced value when the user flips the in-app theme toggle). Tokens that are
|
|
25
|
+
self-contained ink-on-fill pairs (pin, danger) or only ever sit over the
|
|
26
|
+
device stream (touch dots, spotlight scrim, ring) read on any backdrop and
|
|
27
|
+
so stay single-valued. */
|
|
28
|
+
--color-bg: light-dark(#f4f5f7, #0e0e10);
|
|
29
|
+
--color-fg: light-dark(#1b1d21, #eaeaea);
|
|
30
|
+
--color-muted: light-dark(#5f636b, #8a8a90);
|
|
31
|
+
--color-accent: light-dark(
|
|
32
|
+
#2f6fd0,
|
|
33
|
+
#9bc7f0
|
|
34
|
+
); /* brand sky-blue on dark; a deeper blue carries the same role on light */
|
|
35
|
+
--color-on-accent: light-dark(#ffffff, #06122b); /* ink on accent-filled surfaces */
|
|
36
|
+
--color-border: light-dark(#d8dbe2, #2a2a2e);
|
|
37
|
+
--color-surface: light-dark(#ffffff, #16161a); /* panels (toolbar, cards, pops) */
|
|
38
|
+
--color-surface-raised: light-dark(#f6f7f9, #1c1c21); /* card header — lifted off surface */
|
|
39
|
+
--color-surface-hover: light-dark(#eef1f5, #1c1c22); /* hovered list item */
|
|
40
|
+
--color-row-hover: light-dark(#e8ecf3, #20202a); /* hovered variant row */
|
|
41
|
+
--color-ok: light-dark(#138a48, #5cdc8b);
|
|
42
|
+
--color-error: light-dark(#cf2f2f, #ff8080);
|
|
43
|
+
--color-thumb-bg: light-dark(#e3e5ea, #000000); /* letterbox behind variant previews */
|
|
44
|
+
--color-pin-bg: #d8a657; /* saved-annotation pin */
|
|
45
|
+
--color-pin-fg: #1a1205;
|
|
46
|
+
--color-danger-bg: light-dark(#c2334a, #7a2230); /* destructive (delete) button */
|
|
47
|
+
--color-danger-fg: #ffd9df;
|
|
48
|
+
|
|
49
|
+
/* ── Translucent effect colours ──────────────────────────────────────── */
|
|
50
|
+
--color-row-staged: light-dark(
|
|
51
|
+
rgba(19, 138, 72, 0.12),
|
|
52
|
+
rgba(92, 220, 139, 0.13)
|
|
53
|
+
); /* ok tint on staged row */
|
|
54
|
+
--touch-fill: rgba(155, 199, 240, 0.25); /* multi-touch dot body (accent) */
|
|
55
|
+
--touch-fill-pressed: rgba(155, 199, 240, 0.55);
|
|
56
|
+
--touch-stroke: rgba(155, 199, 240, 0.9); /* multi-touch dot ring */
|
|
57
|
+
--touch-anchor-fill: rgba(255, 200, 80, 0.9); /* anchored-touch dot */
|
|
58
|
+
--touch-anchor-stroke: rgba(255, 200, 80, 1);
|
|
59
|
+
--spotlight-scrim: rgba(8, 8, 10, 0.55); /* dim/blur over the stream */
|
|
60
|
+
--footbar-bg: light-dark(
|
|
61
|
+
rgba(255, 255, 255, 0.94),
|
|
62
|
+
rgba(22, 22, 26, 0.94)
|
|
63
|
+
); /* surface, semi-opaque */
|
|
64
|
+
|
|
65
|
+
/* ── Elevation (box-shadow values, by purpose) ───────────────────────── */
|
|
66
|
+
/* Only the shadow COLOUR flips per theme: heavy black halos read as grime on
|
|
67
|
+
a light surface, so light mode uses a soft blue-grey ink at low alpha. */
|
|
68
|
+
--shadow-stream: 0 10px 48px light-dark(rgba(18, 26, 42, 0.14), #0008);
|
|
69
|
+
--shadow-pill: 0 4px 14px light-dark(rgba(18, 26, 42, 0.12), #0008);
|
|
70
|
+
--shadow-card: 0 10px 30px light-dark(rgba(18, 26, 42, 0.13), #0009);
|
|
71
|
+
--shadow-pin: 0 3px 10px light-dark(rgba(18, 26, 42, 0.16), #0008);
|
|
72
|
+
--shadow-pop: 0 12px 36px light-dark(rgba(18, 26, 42, 0.18), #000b);
|
|
73
|
+
--ring-outline: 0 0 0 1px #000a; /* spotlight ring edge (over the stream) */
|
|
74
|
+
--touch-glow: 0 0 12px rgba(155, 199, 240, 0.5);
|
|
75
|
+
--dot-glow: 0 0 8px var(--color-ok);
|
|
76
|
+
--glow-accent: 0 10px 34px light-dark(rgba(47, 111, 208, 0.32), rgba(155, 199, 240, 0.3)); /* accent halo — footbar "ready to submit" pop */
|
|
77
|
+
|
|
78
|
+
/* ── Typography ──────────────────────────────────────────────────────── */
|
|
79
|
+
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
80
|
+
--font-mono: ui-monospace, "SF Mono", Menlo, Monaco, Consolas, monospace;
|
|
81
|
+
--fs-title: 15px;
|
|
82
|
+
--fs-body: 13px;
|
|
83
|
+
--fs-note: 12px;
|
|
84
|
+
--fs-read: 12.5px;
|
|
85
|
+
--fs-label: 11px;
|
|
86
|
+
--fs-tag: 10px;
|
|
87
|
+
--fs-mini: 9px;
|
|
88
|
+
--fw-semibold: 600;
|
|
89
|
+
--fw-bold: 700;
|
|
90
|
+
--fw-extrabold: 800;
|
|
91
|
+
--lh-normal: 1.5;
|
|
92
|
+
--lh-snug: 1.45;
|
|
93
|
+
--tracking-label: 0.04em;
|
|
94
|
+
--tracking-where: 0.03em;
|
|
95
|
+
|
|
96
|
+
/* ── Radii (by role) ─────────────────────────────────────────────────── */
|
|
97
|
+
/* Brand geometry: the argent site rounds generously (terminal card, pills).
|
|
98
|
+
Mid radii bumped a notch toward that softer feel; tiny tags and the
|
|
99
|
+
pin-tail teardrop stay tight so their shape doesn't distort. */
|
|
100
|
+
--radius-chip: 4px;
|
|
101
|
+
--radius-control: 6px; /* toolbar controls, spot ring */
|
|
102
|
+
--radius-input: 7px; /* textareas, pop buttons */
|
|
103
|
+
--radius-button: 8px;
|
|
104
|
+
--radius-item: 10px; /* device-picker item */
|
|
105
|
+
--radius-card: 14px; /* stream, cards, popovers, footbar */
|
|
106
|
+
--radius-pin-tail: 2px; /* annotation-pin teardrop corner */
|
|
107
|
+
--radius-round: 50%;
|
|
108
|
+
--radius-pill: 999px;
|
|
109
|
+
|
|
110
|
+
/* ── Borders ─────────────────────────────────────────────────────────── */
|
|
111
|
+
--border-hairline: 1px;
|
|
112
|
+
--border-strong: 2px; /* spotlight ring, touch dot */
|
|
113
|
+
--connector-width: 1.5; /* SVG stroke-width (unitless) */
|
|
114
|
+
|
|
115
|
+
/* ── Spacing — gaps (recurring roles) ────────────────────────────────── */
|
|
116
|
+
--gap-tight: 5px;
|
|
117
|
+
--gap-inline: 6px;
|
|
118
|
+
--gap-list: 8px;
|
|
119
|
+
--gap-bar: 10px;
|
|
120
|
+
--gap-stack: 12px;
|
|
121
|
+
|
|
122
|
+
/* ── Spacing — padding (per role) ────────────────────────────────────── */
|
|
123
|
+
--pad-bar: 8px 12px; /* toolbar */
|
|
124
|
+
--pad-control: 4px 10px; /* select / button */
|
|
125
|
+
--pad-toggle: 4px 12px;
|
|
126
|
+
--pad-view: 12px; /* viewport */
|
|
127
|
+
--pad-empty: 32px;
|
|
128
|
+
--pad-picker: 24px;
|
|
129
|
+
--pad-item: 12px 14px; /* device-picker item */
|
|
130
|
+
--pad-refresh: 6px 12px;
|
|
131
|
+
--pad-code: 2px 6px;
|
|
132
|
+
--pad-pill: 3px 11px;
|
|
133
|
+
--pad-card-head: 7px 10px;
|
|
134
|
+
--pad-row: 8px 10px;
|
|
135
|
+
--pad-cmt: 6px 10px; /* in-card comment box */
|
|
136
|
+
--pad-input: 6px 8px; /* popover textareas */
|
|
137
|
+
--pad-pop: 10px; /* comment / annotation popover */
|
|
138
|
+
--pad-btn: 6px 10px; /* popover buttons */
|
|
139
|
+
--pad-lab: 1px 7px; /* spotlight ring label */
|
|
140
|
+
--pad-footbar: 8px 10px;
|
|
141
|
+
--pad-footbar-input: 6px 9px;
|
|
142
|
+
--pad-complete: 8px 14px;
|
|
143
|
+
|
|
144
|
+
/* one-off margins / nudges (kept named by what they position) */
|
|
145
|
+
--sub-margin: -4px 0 6px; /* device-picker caption */
|
|
146
|
+
--comment-title-gap: 7px; /* comment popover heading → body */
|
|
147
|
+
--annrow-mt: 9px; /* annotation popover button row */
|
|
148
|
+
--annpop-gap: 8px; /* popover ↔ pin gap, resting */
|
|
149
|
+
--annpop-gap-show: 14px; /* popover ↔ pin gap, shown */
|
|
150
|
+
--press-shift: 1px; /* :active downward nudge */
|
|
151
|
+
|
|
152
|
+
/* ── Component sizes ─────────────────────────────────────────────────── */
|
|
153
|
+
--card-width: 232px;
|
|
154
|
+
--vcard-body-max-h: none; /* JS sets a per-card max-height only when the column overflows the viewport; otherwise the body fits its variant count. */
|
|
155
|
+
--thumb-size: 96px;
|
|
156
|
+
--collapsed-thumb-h: 58px; /* once a variant is picked, the others collapse to a row with the preview ~3 lines of body text tall (3 × --fs-body × --lh-normal ≈ 58px) */
|
|
157
|
+
--pin-size: 20px;
|
|
158
|
+
--dot-size: 8px; /* status dot, device-picker dot */
|
|
159
|
+
--card-dot-size: 7px; /* card-header dot */
|
|
160
|
+
--icon-btn-size: 34px; /* floating top-right icon controls (theme, comment, close) */
|
|
161
|
+
--icon-size: 17px; /* glyph inside an icon button */
|
|
162
|
+
--comment-pop-width: 248px;
|
|
163
|
+
--annpop-width: 232px;
|
|
164
|
+
--annpop-txt-max-h: 160px;
|
|
165
|
+
--textarea-min-h: 64px;
|
|
166
|
+
--cmt-min-h: 28px;
|
|
167
|
+
--footbar-input-width: 260px;
|
|
168
|
+
--footbar-bottom: 14px;
|
|
169
|
+
--footbar-right: 14px;
|
|
170
|
+
--resize-edge: 6px; /* drag-layer inset so the frameless window's edges still resize */
|
|
171
|
+
--footbar-max-width: 70%;
|
|
172
|
+
--select-min-width: 240px;
|
|
173
|
+
--debug-min-width: 220px;
|
|
174
|
+
--empty-max-width: 480px;
|
|
175
|
+
--picker-max-width: 420px;
|
|
176
|
+
--lab-max-width: 240px;
|
|
177
|
+
--lab-top: -22px;
|
|
178
|
+
--complete-note-max-width: 200px;
|
|
179
|
+
--modal-max-width: 360px;
|
|
180
|
+
--pad-modal: 18px;
|
|
181
|
+
--stream-max-h: 80dvh; /* dvh, not vh: in a browser tab `vh` is the toolbar-retracted (large) viewport, so the centered stream overflowed the %-height container and got clipped at the bottom. `dvh` tracks the visible viewport. In the frameless Electron window (no toolbar) dvh == vh, so production is unchanged. */
|
|
182
|
+
--backdrop-blur: 1.67px; /* light haze over the dimmed stream (3× softer than the former 5px) */
|
|
183
|
+
|
|
184
|
+
/* ── Opacities ───────────────────────────────────────────────────────── */
|
|
185
|
+
--opacity-disabled: 0.45;
|
|
186
|
+
--opacity-connector: 0.7;
|
|
187
|
+
--opacity-pill: 0.92;
|
|
188
|
+
|
|
189
|
+
/* ── Z-index layers ──────────────────────────────────────────────────── */
|
|
190
|
+
--z-connectors: 4;
|
|
191
|
+
--z-cards: 5;
|
|
192
|
+
--z-pin: 7;
|
|
193
|
+
--z-spot-hit: 8;
|
|
194
|
+
--z-pop: 9; /* off-screen pill, comment popover */
|
|
195
|
+
--z-overlay: 10; /* annotation popover, footbar */
|
|
196
|
+
--z-modal: 12; /* confirm modal (above the footbar) */
|
|
197
|
+
|
|
198
|
+
/* ── Motion & feel (CSS transitions AND read by JS at boot) ──────────── */
|
|
199
|
+
--ease-out: cubic-bezier(0.22, 1, 0.36, 1);
|
|
200
|
+
--ease-pop: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
201
|
+
--dur-press: 0.06s;
|
|
202
|
+
--dur-hover: 0.15s;
|
|
203
|
+
--dur-fade: 0.18s;
|
|
204
|
+
--dur-pill: 0.2s;
|
|
205
|
+
--dur-card-in: 0.22s;
|
|
206
|
+
--dur-spot: 0.28s;
|
|
207
|
+
--dur-card-move: 0.34s;
|
|
208
|
+
--dither-dur: 0.72s; /* light↔dark dithered wavefront sweep */
|
|
209
|
+
--card-gone-scale: 0.8; /* shrink as a card pops away */
|
|
210
|
+
--footbar-ready-scale: 1.05; /* footbar grows a touch once every element is chosen */
|
|
211
|
+
|
|
212
|
+
/* Spring feel — JS integrates these (ω rad/s, ζ damping ratio). The bubble
|
|
213
|
+
spring is slow & barely-overshooting (cards drift into place); the tight
|
|
214
|
+
spring is fast & critically damped (connectors/pins track every frame). */
|
|
215
|
+
--spring-bubble-omega: 4.2;
|
|
216
|
+
--spring-bubble-zeta: 1; /* DEMO: critically damped — no overshoot/bounce on cards */
|
|
217
|
+
--spring-tight-omega: 26;
|
|
218
|
+
--spring-tight-zeta: 1;
|
|
219
|
+
--card-gone-grace-ms: 550; /* ride out brief edge drop-outs before fading */
|
|
220
|
+
--poll-interval-ms: 1200; /* /preview/variants poll cadence */
|
|
221
|
+
--tree-stale-ms: 6000; /* drop the describe tree if older than this */
|
|
222
|
+
--flick-max-vel: 1500; /* clamp thrown-card release velocity (px/s) */
|
|
223
|
+
--spot-idle-dismiss-ms: 150; /* stopped-aimless grace before releasing spotlight */
|
|
224
|
+
--spot-traj-window-ms: 80; /* recent-sample window used to derive pointer velocity */
|
|
225
|
+
--spot-traj-stopped-speed: 0.05; /* below this normalized speed (1/s) the pointer counts as stopped */
|
|
226
|
+
--spot-traj-reach: 0.5; /* normalized forward distance to look for a trajectory target */
|
|
227
|
+
--spot-traj-hitbox-margin: 0.2; /* per-side margin (fraction of element size). Inflates BOTH the sticky focus hitbox (so a tiny drift out of an element keeps it focused) and the trajectory predictor hitbox. Strict containment still wins, so margins never steal focus from an obviously hovered element. */
|
|
228
|
+
--spot-max-frame-area: 0.85; /* nodes whose frame covers more than this fraction of the screen are not treated as highlightables (catches Android full-screen container roots that lack iOS's explicit root flag) */
|
|
229
|
+
--annpop-hover-grace-ms: 280; /* hover-card grace: pin ↔ popover travel */
|
|
230
|
+
--success-toast-show-ms: 1200; /* how long the post-submit confirmation card lingers (browser mode; in Electron the window closes around it sooner) */
|
|
231
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (let key of __getOwnPropNames(from))
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
+
}
|
|
14
|
+
return to;
|
|
15
|
+
};
|
|
16
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
18
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
19
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
20
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
|
|
25
|
+
// ../preview-window/src/main.ts
|
|
26
|
+
var import_electron = require("electron");
|
|
27
|
+
var readline = __toESM(require("node:readline"));
|
|
28
|
+
var TARGET_WIDTH = 1200;
|
|
29
|
+
var TARGET_HEIGHT = 820;
|
|
30
|
+
var ANIMATION_MS = 320;
|
|
31
|
+
var win = null;
|
|
32
|
+
function squeezeSnippet(toScale, durationMs) {
|
|
33
|
+
const clearWhenDone = toScale === 1;
|
|
34
|
+
return `
|
|
35
|
+
new Promise(resolve => {
|
|
36
|
+
const root = document.documentElement;
|
|
37
|
+
const s = root.style;
|
|
38
|
+
s.transformOrigin = '50% 50%';
|
|
39
|
+
s.transition = 'transform ${durationMs}ms cubic-bezier(0.22, 1, 0.36, 1)';
|
|
40
|
+
const done = () => {
|
|
41
|
+
${clearWhenDone ? "s.transition = ''; s.transform = '';" : ""}
|
|
42
|
+
resolve();
|
|
43
|
+
};
|
|
44
|
+
// Two rAFs so the previous transform (set just before this snippet)
|
|
45
|
+
// has been committed and rendered before the transition starts.
|
|
46
|
+
// Without this, the browser collapses both writes into one frame
|
|
47
|
+
// and skips the animation.
|
|
48
|
+
requestAnimationFrame(() => requestAnimationFrame(() => {
|
|
49
|
+
const onEnd = () => { root.removeEventListener('transitionend', onEnd); done(); };
|
|
50
|
+
root.addEventListener('transitionend', onEnd, { once: true });
|
|
51
|
+
// Safety in case transitionend never fires (off-screen tab, e.g.):
|
|
52
|
+
setTimeout(done, ${durationMs + 80});
|
|
53
|
+
s.transform = 'scaleY(${toScale})';
|
|
54
|
+
}));
|
|
55
|
+
});
|
|
56
|
+
`;
|
|
57
|
+
}
|
|
58
|
+
var HOST_CSS = `
|
|
59
|
+
html, body { background: transparent !important; }
|
|
60
|
+
#root { background: var(--color-bg); }
|
|
61
|
+
`;
|
|
62
|
+
async function runInRenderer(snippet, label) {
|
|
63
|
+
const current = win;
|
|
64
|
+
if (!current) return;
|
|
65
|
+
try {
|
|
66
|
+
await current.webContents.executeJavaScript(snippet);
|
|
67
|
+
} catch (err) {
|
|
68
|
+
process.stderr.write(
|
|
69
|
+
`[preview-window] ${label} failed: ${err instanceof Error ? err.message : err}
|
|
70
|
+
`
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async function prepareSqueeze() {
|
|
75
|
+
await runInRenderer(
|
|
76
|
+
`
|
|
77
|
+
(() => {
|
|
78
|
+
const style = document.createElement('style');
|
|
79
|
+
style.setAttribute('data-argent-preview-host', '');
|
|
80
|
+
style.textContent = ${JSON.stringify(HOST_CSS)};
|
|
81
|
+
document.head.appendChild(style);
|
|
82
|
+
const s = document.documentElement.style;
|
|
83
|
+
s.transformOrigin = '50% 50%';
|
|
84
|
+
s.transition = 'none';
|
|
85
|
+
s.transform = 'scaleY(0)';
|
|
86
|
+
void document.documentElement.offsetHeight;
|
|
87
|
+
})();
|
|
88
|
+
`,
|
|
89
|
+
"prepareSqueeze"
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
async function squeezeIn() {
|
|
93
|
+
await runInRenderer(squeezeSnippet(1, ANIMATION_MS), "squeezeIn");
|
|
94
|
+
}
|
|
95
|
+
async function squeezeOut() {
|
|
96
|
+
await runInRenderer(squeezeSnippet(0, ANIMATION_MS), "squeezeOut");
|
|
97
|
+
}
|
|
98
|
+
async function createWindow() {
|
|
99
|
+
const url = process.env.ARGENT_PREVIEW_URL;
|
|
100
|
+
if (!url) {
|
|
101
|
+
process.stderr.write("[preview-window] ARGENT_PREVIEW_URL not set, exiting\n");
|
|
102
|
+
import_electron.app.quit();
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
win = new import_electron.BrowserWindow({
|
|
106
|
+
width: TARGET_WIDTH,
|
|
107
|
+
height: TARGET_HEIGHT,
|
|
108
|
+
frame: false,
|
|
109
|
+
show: false,
|
|
110
|
+
// Transparent + no native shadow: the OS window is just a passthrough
|
|
111
|
+
// for the renderer. The visible "card" is whatever <html> + <body>
|
|
112
|
+
// paints, which is what we squeeze with the CSS transform.
|
|
113
|
+
transparent: true,
|
|
114
|
+
hasShadow: false,
|
|
115
|
+
backgroundColor: "#00000000",
|
|
116
|
+
webPreferences: {
|
|
117
|
+
contextIsolation: true,
|
|
118
|
+
nodeIntegration: false,
|
|
119
|
+
sandbox: true
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
win.on("closed", () => {
|
|
123
|
+
win = null;
|
|
124
|
+
import_electron.app.quit();
|
|
125
|
+
});
|
|
126
|
+
try {
|
|
127
|
+
await win.loadURL(url);
|
|
128
|
+
} catch (err) {
|
|
129
|
+
process.stderr.write(
|
|
130
|
+
`[preview-window] loadURL failed for ${url}: ${err instanceof Error ? err.message : err}
|
|
131
|
+
`
|
|
132
|
+
);
|
|
133
|
+
import_electron.app.quit();
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
win.center();
|
|
137
|
+
await prepareSqueeze();
|
|
138
|
+
win.show();
|
|
139
|
+
void squeezeIn();
|
|
140
|
+
}
|
|
141
|
+
function foreground(url) {
|
|
142
|
+
if (!win) return;
|
|
143
|
+
if (win.isMinimized()) win.restore();
|
|
144
|
+
win.show();
|
|
145
|
+
win.focus();
|
|
146
|
+
if (url && win.webContents.getURL() !== url) {
|
|
147
|
+
win.loadURL(url).catch((err) => {
|
|
148
|
+
process.stderr.write(
|
|
149
|
+
`[preview-window] foreground loadURL failed: ${err instanceof Error ? err.message : err}
|
|
150
|
+
`
|
|
151
|
+
);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
async function closeWithAnimation() {
|
|
156
|
+
if (!win) {
|
|
157
|
+
import_electron.app.quit();
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
await squeezeOut();
|
|
161
|
+
import_electron.app.quit();
|
|
162
|
+
}
|
|
163
|
+
import_electron.app.whenReady().then(createWindow).catch((err) => {
|
|
164
|
+
process.stderr.write(
|
|
165
|
+
`[preview-window] initialization failed: ${err instanceof Error ? err.message : err}
|
|
166
|
+
`
|
|
167
|
+
);
|
|
168
|
+
import_electron.app.quit();
|
|
169
|
+
});
|
|
170
|
+
import_electron.app.on("window-all-closed", () => import_electron.app.quit());
|
|
171
|
+
var rl = readline.createInterface({ input: process.stdin });
|
|
172
|
+
rl.on("line", (line) => {
|
|
173
|
+
let msg;
|
|
174
|
+
try {
|
|
175
|
+
msg = JSON.parse(line);
|
|
176
|
+
} catch {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
if (msg.cmd === "foreground") foreground(msg.url);
|
|
180
|
+
else if (msg.cmd === "close") void closeWithAnimation();
|
|
181
|
+
});
|
|
182
|
+
rl.on("close", () => import_electron.app.quit());
|