vibespot 1.6.5 → 1.8.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/README.md +24 -3
- package/assets/whats-new.json +27 -0
- package/dist/index.js +579 -681
- package/dist/index.js.map +1 -1
- package/package.json +8 -5
- package/ui/chat.js +671 -9
- package/ui/dashboard.js +53 -12
- package/ui/docs/index.html +57 -2
- package/ui/email-preview.js +1 -5
- package/ui/escape-html.js +14 -0
- package/ui/field-editor.js +6 -12
- package/ui/field-save.js +82 -0
- package/ui/index.html +10 -4
- package/ui/inline-edit.js +116 -570
- package/ui/plan.js +22 -13
- package/ui/preview-agent.js +1050 -0
- package/ui/preview.js +248 -265
- package/ui/section-controls.js +16 -622
- package/ui/setup.js +73 -20
- package/ui/styles.css +424 -0
- package/ui/upload-panel.js +7 -8
- package/ui/whats-new.js +249 -0
- package/assets/readme/00-hero-banner.png +0 -0
- package/assets/readme/00-hero-banner.svg +0 -59
- package/assets/readme/01-vibe-coding-hero.png +0 -0
- package/assets/readme/02-plan-mode.png +0 -0
- package/assets/readme/03-figma-import.png +0 -0
- package/assets/readme/04-multi-page-sites.png +0 -0
- package/assets/readme/05-inline-wysiwyg.png +0 -0
- package/assets/readme/06-hubspot-upload.png +0 -0
- package/ui/docs/screenshots/brand-kit-preview.png +0 -0
- package/ui/docs/screenshots/content-type-dropdown.png +0 -0
- package/ui/docs/screenshots/editor-full-layout.png +0 -0
- package/ui/docs/screenshots/inline-wysiwyg-editing.png +0 -0
- package/ui/docs/screenshots/module-overview-slideout.png +0 -0
- package/ui/docs/screenshots/multi-page-tree.png +0 -0
- package/ui/docs/screenshots/onboarding-walkthrough.png +0 -0
- package/ui/docs/screenshots/split-pane-view.png +0 -0
- package/ui/docs/screenshots/visual-controls-toolbar.png +0 -0
- package/ui/docs/screenshots/workspace-tabs.png +0 -0
package/ui/setup.js
CHANGED
|
@@ -136,19 +136,27 @@ async function initSetup() {
|
|
|
136
136
|
// Show "Continue where you left off" cards above the create options
|
|
137
137
|
populateRecentProjects(info);
|
|
138
138
|
|
|
139
|
-
// Auto-select engine if available but not yet chosen
|
|
139
|
+
// Auto-select engine if available but not yet chosen. Guarded on its own:
|
|
140
|
+
// a transient failure here just leaves the "no engine" alert visible —
|
|
141
|
+
// it must not abort the rest of setup rendering.
|
|
140
142
|
if (info.availableEngines && info.availableEngines.length > 0 && !info.activeEngine) {
|
|
141
143
|
const engine = info.availableEngines[0];
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
144
|
+
try {
|
|
145
|
+
const engineRes = await fetch("/api/settings/engine", {
|
|
146
|
+
method: "POST",
|
|
147
|
+
headers: { "Content-Type": "application/json" },
|
|
148
|
+
body: JSON.stringify({ engine }),
|
|
149
|
+
});
|
|
150
|
+
if (engineRes.ok) {
|
|
151
|
+
info.activeEngine = engine;
|
|
152
|
+
info.aiAvailable = true;
|
|
153
|
+
// Update statusbar
|
|
154
|
+
const statusEngine = document.getElementById("status-engine");
|
|
155
|
+
if (statusEngine) statusEngine.textContent = ENGINE_DISPLAY_NAMES[engine] || engine;
|
|
156
|
+
}
|
|
157
|
+
} catch (err) {
|
|
158
|
+
console.warn("[setup] engine auto-select failed", err);
|
|
159
|
+
}
|
|
152
160
|
}
|
|
153
161
|
|
|
154
162
|
// Show environment alerts
|
|
@@ -1069,25 +1077,48 @@ async function handleCliAction(engineId, action, btn) {
|
|
|
1069
1077
|
const data = await res.json();
|
|
1070
1078
|
if (data.jobId) {
|
|
1071
1079
|
// Poll until complete
|
|
1072
|
-
await
|
|
1080
|
+
await pollJobUntilDone(data.jobId);
|
|
1073
1081
|
}
|
|
1074
1082
|
// Refresh walkthrough to show updated status
|
|
1075
1083
|
showWalkthrough();
|
|
1076
|
-
} catch {
|
|
1084
|
+
} catch (err) {
|
|
1077
1085
|
btn.disabled = false;
|
|
1078
1086
|
btn.textContent = origText;
|
|
1087
|
+
await vibeAlert((action === "install" ? "Install failed: " : "Sign-in failed: ") + (err.message || err), "Error");
|
|
1079
1088
|
}
|
|
1080
1089
|
}
|
|
1081
1090
|
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1091
|
+
// Poll a background job until it finishes. Resolves with the job payload on
|
|
1092
|
+
// success; throws on failure, on a vanished job (404 — the server restarted
|
|
1093
|
+
// or GC'd it, so it will never complete), and on timeout — so callers can't
|
|
1094
|
+
// spin forever on a dead job. Also used by upload-panel.js.
|
|
1095
|
+
// NOT named pollJob: settings.js declares a legacy callback-style pollJob in
|
|
1096
|
+
// the same global scope and loads later, so that name gets shadowed (VIB-1931).
|
|
1097
|
+
async function pollJobUntilDone(jobId, { timeoutMs = 5 * 60 * 1000, intervalMs = 2000 } = {}) {
|
|
1098
|
+
const deadline = Date.now() + timeoutMs;
|
|
1099
|
+
while (Date.now() < deadline) {
|
|
1100
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
1101
|
+
let res;
|
|
1085
1102
|
try {
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
}
|
|
1103
|
+
res = await fetch("/api/settings/job/" + jobId);
|
|
1104
|
+
} catch {
|
|
1105
|
+
continue; // transient network error — keep polling until the deadline
|
|
1106
|
+
}
|
|
1107
|
+
if (res.status === 404) {
|
|
1108
|
+
throw new Error("The background job was lost (server restarted?). Please try again.");
|
|
1109
|
+
}
|
|
1110
|
+
let data;
|
|
1111
|
+
try {
|
|
1112
|
+
data = await res.json();
|
|
1113
|
+
} catch {
|
|
1114
|
+
continue;
|
|
1115
|
+
}
|
|
1116
|
+
if (data.status === "completed") return data;
|
|
1117
|
+
if (data.status === "failed") {
|
|
1118
|
+
throw new Error(data.output ? String(data.output).slice(-500) : "The background job failed.");
|
|
1119
|
+
}
|
|
1090
1120
|
}
|
|
1121
|
+
throw new Error("Timed out waiting for the job to finish. Please try again.");
|
|
1091
1122
|
}
|
|
1092
1123
|
|
|
1093
1124
|
// ---------------------------------------------------------------------------
|
|
@@ -2123,6 +2154,17 @@ document.getElementById("figma-extract-btn")?.addEventListener("click", async ()
|
|
|
2123
2154
|
body: JSON.stringify({ url }),
|
|
2124
2155
|
});
|
|
2125
2156
|
|
|
2157
|
+
// Non-streaming failure (auth gate, 4xx/5xx JSON error) — surface it
|
|
2158
|
+
// instead of letting getReader() throw an opaque TypeError.
|
|
2159
|
+
if (!res.ok || !res.body) {
|
|
2160
|
+
let msg = "Extraction failed (" + res.status + ")";
|
|
2161
|
+
try {
|
|
2162
|
+
const errData = await res.json();
|
|
2163
|
+
if (errData.error) msg = errData.error;
|
|
2164
|
+
} catch { /* non-JSON error body */ }
|
|
2165
|
+
throw new Error(msg);
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2126
2168
|
const reader = res.body.getReader();
|
|
2127
2169
|
const decoder = new TextDecoder();
|
|
2128
2170
|
let buffer = "";
|
|
@@ -2280,6 +2322,17 @@ async function startFigmaImport(extractionId, themeName, useAssets = true) {
|
|
|
2280
2322
|
body: JSON.stringify({ extractionId, themeName, useAssets }),
|
|
2281
2323
|
});
|
|
2282
2324
|
|
|
2325
|
+
// Non-streaming failure (auth gate, 4xx/5xx JSON error) — surface it
|
|
2326
|
+
// instead of letting getReader() throw an opaque TypeError.
|
|
2327
|
+
if (!res.ok || !res.body) {
|
|
2328
|
+
let msg = "Conversion failed (" + res.status + ")";
|
|
2329
|
+
try {
|
|
2330
|
+
const errData = await res.json();
|
|
2331
|
+
if (errData.error) msg = errData.error;
|
|
2332
|
+
} catch { /* non-JSON error body */ }
|
|
2333
|
+
throw new Error(msg);
|
|
2334
|
+
}
|
|
2335
|
+
|
|
2283
2336
|
const reader = res.body.getReader();
|
|
2284
2337
|
const decoder = new TextDecoder();
|
|
2285
2338
|
let buffer = "";
|
package/ui/styles.css
CHANGED
|
@@ -8216,3 +8216,427 @@ body { display: flex; }
|
|
|
8216
8216
|
display: none;
|
|
8217
8217
|
}
|
|
8218
8218
|
}
|
|
8219
|
+
|
|
8220
|
+
/* ---------------------------------------------------------------------------
|
|
8221
|
+
Checkpoint gate card (VIB-1877) — design preview before the module build.
|
|
8222
|
+
--------------------------------------------------------------------------- */
|
|
8223
|
+
.checkpoint {
|
|
8224
|
+
border: 1px solid var(--border-hover);
|
|
8225
|
+
border-radius: var(--radius);
|
|
8226
|
+
background: var(--bg-elevated);
|
|
8227
|
+
padding: var(--space-4);
|
|
8228
|
+
display: flex;
|
|
8229
|
+
flex-direction: column;
|
|
8230
|
+
gap: var(--space-3);
|
|
8231
|
+
max-width: 520px;
|
|
8232
|
+
}
|
|
8233
|
+
.checkpoint__head {
|
|
8234
|
+
display: flex;
|
|
8235
|
+
align-items: center;
|
|
8236
|
+
gap: var(--space-2);
|
|
8237
|
+
flex-wrap: wrap;
|
|
8238
|
+
}
|
|
8239
|
+
.checkpoint__badge {
|
|
8240
|
+
font-size: var(--text-xs);
|
|
8241
|
+
font-weight: 600;
|
|
8242
|
+
letter-spacing: 0.08em;
|
|
8243
|
+
text-transform: uppercase;
|
|
8244
|
+
color: var(--accent);
|
|
8245
|
+
background: var(--accent-dim);
|
|
8246
|
+
border-radius: var(--radius-pill);
|
|
8247
|
+
padding: 3px 9px;
|
|
8248
|
+
}
|
|
8249
|
+
.checkpoint__headline {
|
|
8250
|
+
font-family: var(--font-display);
|
|
8251
|
+
font-size: var(--text-md);
|
|
8252
|
+
color: var(--text);
|
|
8253
|
+
}
|
|
8254
|
+
.checkpoint__hero {
|
|
8255
|
+
border-radius: var(--radius-sm);
|
|
8256
|
+
overflow: hidden;
|
|
8257
|
+
border: 1px solid var(--border);
|
|
8258
|
+
background: #000;
|
|
8259
|
+
}
|
|
8260
|
+
.checkpoint__hero-frame {
|
|
8261
|
+
display: block;
|
|
8262
|
+
width: 100%;
|
|
8263
|
+
height: 230px;
|
|
8264
|
+
border: 0;
|
|
8265
|
+
}
|
|
8266
|
+
.checkpoint__tokens {
|
|
8267
|
+
display: flex;
|
|
8268
|
+
flex-wrap: wrap;
|
|
8269
|
+
gap: var(--space-4);
|
|
8270
|
+
align-items: flex-start;
|
|
8271
|
+
}
|
|
8272
|
+
.checkpoint__palette {
|
|
8273
|
+
display: flex;
|
|
8274
|
+
flex-wrap: wrap;
|
|
8275
|
+
gap: var(--space-2);
|
|
8276
|
+
flex: 1 1 220px;
|
|
8277
|
+
}
|
|
8278
|
+
.checkpoint__swatch {
|
|
8279
|
+
display: flex;
|
|
8280
|
+
align-items: center;
|
|
8281
|
+
gap: 6px;
|
|
8282
|
+
font-size: var(--text-sm);
|
|
8283
|
+
color: var(--text-dim);
|
|
8284
|
+
}
|
|
8285
|
+
.checkpoint__swatch-chip {
|
|
8286
|
+
width: 16px;
|
|
8287
|
+
height: 16px;
|
|
8288
|
+
border-radius: 4px;
|
|
8289
|
+
border: 1px solid var(--border-hover);
|
|
8290
|
+
display: inline-block;
|
|
8291
|
+
}
|
|
8292
|
+
.checkpoint__type {
|
|
8293
|
+
display: flex;
|
|
8294
|
+
flex-direction: column;
|
|
8295
|
+
gap: 2px;
|
|
8296
|
+
}
|
|
8297
|
+
.checkpoint__type-row {
|
|
8298
|
+
font-size: var(--text-lg);
|
|
8299
|
+
color: var(--text);
|
|
8300
|
+
line-height: 1.2;
|
|
8301
|
+
}
|
|
8302
|
+
.checkpoint__type-row--body {
|
|
8303
|
+
font-size: var(--text-base);
|
|
8304
|
+
color: var(--text-dim);
|
|
8305
|
+
}
|
|
8306
|
+
.checkpoint__muted { color: var(--text-dim); font-size: var(--text-sm); }
|
|
8307
|
+
.checkpoint__meta { font-size: var(--text-sm); color: var(--text-dim); }
|
|
8308
|
+
.checkpoint__cost { color: var(--text-dim); }
|
|
8309
|
+
.checkpoint__steer-input {
|
|
8310
|
+
width: 100%;
|
|
8311
|
+
resize: vertical;
|
|
8312
|
+
background: var(--bg-input);
|
|
8313
|
+
border: 1px solid var(--border-hover);
|
|
8314
|
+
border-radius: var(--radius-sm);
|
|
8315
|
+
color: var(--text);
|
|
8316
|
+
font-family: var(--font);
|
|
8317
|
+
font-size: var(--text-base);
|
|
8318
|
+
padding: var(--space-2);
|
|
8319
|
+
}
|
|
8320
|
+
.checkpoint__actions {
|
|
8321
|
+
display: flex;
|
|
8322
|
+
flex-wrap: wrap;
|
|
8323
|
+
gap: var(--space-2);
|
|
8324
|
+
}
|
|
8325
|
+
.checkpoint__btn { font-size: var(--text-base); }
|
|
8326
|
+
.checkpoint__btn:disabled { opacity: 0.5; cursor: default; }
|
|
8327
|
+
|
|
8328
|
+
/* Structure checkpoint (VIB-1879) — editable module outline. */
|
|
8329
|
+
.checkpoint__narrative {
|
|
8330
|
+
font-size: var(--text-sm);
|
|
8331
|
+
color: var(--text-dim);
|
|
8332
|
+
line-height: 1.5;
|
|
8333
|
+
}
|
|
8334
|
+
.checkpoint__outline {
|
|
8335
|
+
display: flex;
|
|
8336
|
+
flex-direction: column;
|
|
8337
|
+
gap: var(--space-2);
|
|
8338
|
+
}
|
|
8339
|
+
.checkpoint__row {
|
|
8340
|
+
display: flex;
|
|
8341
|
+
align-items: center;
|
|
8342
|
+
gap: var(--space-2);
|
|
8343
|
+
background: var(--bg-input);
|
|
8344
|
+
border: 1px solid var(--border);
|
|
8345
|
+
border-radius: var(--radius-sm);
|
|
8346
|
+
padding: 6px 8px;
|
|
8347
|
+
}
|
|
8348
|
+
.checkpoint__row-move {
|
|
8349
|
+
display: flex;
|
|
8350
|
+
flex-direction: column;
|
|
8351
|
+
gap: 1px;
|
|
8352
|
+
}
|
|
8353
|
+
.checkpoint__row-btn {
|
|
8354
|
+
border: 0;
|
|
8355
|
+
background: transparent;
|
|
8356
|
+
color: var(--text-dim);
|
|
8357
|
+
cursor: pointer;
|
|
8358
|
+
line-height: 1;
|
|
8359
|
+
font-size: 9px;
|
|
8360
|
+
padding: 1px 2px;
|
|
8361
|
+
border-radius: 3px;
|
|
8362
|
+
}
|
|
8363
|
+
.checkpoint__row-btn:hover { color: var(--text); background: var(--bg-elevated); }
|
|
8364
|
+
.checkpoint__row-main {
|
|
8365
|
+
display: flex;
|
|
8366
|
+
flex-direction: column;
|
|
8367
|
+
gap: 1px;
|
|
8368
|
+
flex: 1 1 auto;
|
|
8369
|
+
min-width: 0;
|
|
8370
|
+
}
|
|
8371
|
+
.checkpoint__row-name {
|
|
8372
|
+
background: transparent;
|
|
8373
|
+
border: 1px solid transparent;
|
|
8374
|
+
border-radius: var(--radius-sm);
|
|
8375
|
+
color: var(--text);
|
|
8376
|
+
font-family: var(--font-mono, monospace);
|
|
8377
|
+
font-size: var(--text-base);
|
|
8378
|
+
padding: 2px 4px;
|
|
8379
|
+
width: 100%;
|
|
8380
|
+
}
|
|
8381
|
+
.checkpoint__row-name:hover { border-color: var(--border-hover); }
|
|
8382
|
+
.checkpoint__row-name:focus {
|
|
8383
|
+
outline: none;
|
|
8384
|
+
border-color: var(--accent);
|
|
8385
|
+
background: var(--bg);
|
|
8386
|
+
}
|
|
8387
|
+
.checkpoint__row-desc {
|
|
8388
|
+
font-size: var(--text-xs);
|
|
8389
|
+
color: var(--text-dim);
|
|
8390
|
+
padding: 0 4px;
|
|
8391
|
+
overflow: hidden;
|
|
8392
|
+
text-overflow: ellipsis;
|
|
8393
|
+
white-space: nowrap;
|
|
8394
|
+
}
|
|
8395
|
+
.checkpoint__row-remove {
|
|
8396
|
+
border: 0;
|
|
8397
|
+
background: transparent;
|
|
8398
|
+
color: var(--text-dim);
|
|
8399
|
+
cursor: pointer;
|
|
8400
|
+
font-size: var(--text-base);
|
|
8401
|
+
padding: 2px 6px;
|
|
8402
|
+
border-radius: var(--radius-sm);
|
|
8403
|
+
flex: 0 0 auto;
|
|
8404
|
+
}
|
|
8405
|
+
.checkpoint__row-remove:hover { color: var(--danger, #e5484d); background: var(--bg-elevated); }
|
|
8406
|
+
.checkpoint__add {
|
|
8407
|
+
align-self: flex-start;
|
|
8408
|
+
font-size: var(--text-sm);
|
|
8409
|
+
}
|
|
8410
|
+
|
|
8411
|
+
/* One-shot send button — slightly dimmer than the primary send. */
|
|
8412
|
+
.chat__send--oneshot {
|
|
8413
|
+
opacity: 0.7;
|
|
8414
|
+
}
|
|
8415
|
+
.chat__send--oneshot:hover:not(:disabled) {
|
|
8416
|
+
opacity: 1;
|
|
8417
|
+
}
|
|
8418
|
+
|
|
8419
|
+
/* Brand-intake gate (VIB-1878) — front-of-flow ask-back card. */
|
|
8420
|
+
.brand-intake__choices {
|
|
8421
|
+
display: flex;
|
|
8422
|
+
flex-direction: column;
|
|
8423
|
+
gap: var(--space-2);
|
|
8424
|
+
margin: var(--space-3) 0;
|
|
8425
|
+
}
|
|
8426
|
+
.brand-intake__choice {
|
|
8427
|
+
display: flex;
|
|
8428
|
+
flex-direction: column;
|
|
8429
|
+
align-items: flex-start;
|
|
8430
|
+
gap: 2px;
|
|
8431
|
+
text-align: left;
|
|
8432
|
+
padding: var(--space-3);
|
|
8433
|
+
height: auto;
|
|
8434
|
+
}
|
|
8435
|
+
.brand-intake__choice-title { font-weight: 600; }
|
|
8436
|
+
.brand-intake__choice-hint { font-size: var(--text-sm); opacity: 0.75; }
|
|
8437
|
+
.brand-intake__form {
|
|
8438
|
+
display: flex;
|
|
8439
|
+
flex-direction: column;
|
|
8440
|
+
gap: var(--space-2);
|
|
8441
|
+
margin: var(--space-3) 0;
|
|
8442
|
+
}
|
|
8443
|
+
.brand-intake__field {
|
|
8444
|
+
display: flex;
|
|
8445
|
+
flex-direction: column;
|
|
8446
|
+
gap: 4px;
|
|
8447
|
+
}
|
|
8448
|
+
.brand-intake__label { font-size: var(--text-sm); font-weight: 600; }
|
|
8449
|
+
.brand-intake__input {
|
|
8450
|
+
width: 100%;
|
|
8451
|
+
font-family: inherit;
|
|
8452
|
+
font-size: var(--text-base);
|
|
8453
|
+
padding: var(--space-2);
|
|
8454
|
+
border: 1px solid var(--border);
|
|
8455
|
+
border-radius: var(--radius-sm);
|
|
8456
|
+
background: var(--surface);
|
|
8457
|
+
color: var(--text);
|
|
8458
|
+
resize: vertical;
|
|
8459
|
+
}
|
|
8460
|
+
.brand-intake__form-actions {
|
|
8461
|
+
display: flex;
|
|
8462
|
+
gap: var(--space-2);
|
|
8463
|
+
margin-top: var(--space-1);
|
|
8464
|
+
}
|
|
8465
|
+
.brand-intake__top-actions { margin-top: var(--space-2); }
|
|
8466
|
+
|
|
8467
|
+
/* ===========================================================================
|
|
8468
|
+
"What's new" release dialog (VIB-1886)
|
|
8469
|
+
One-time post-upgrade modal. Reuses overlay/dialog tokens — no one-off values.
|
|
8470
|
+
=========================================================================== */
|
|
8471
|
+
.whatsnew-overlay {
|
|
8472
|
+
position: fixed;
|
|
8473
|
+
inset: 0;
|
|
8474
|
+
background: var(--overlay-bg);
|
|
8475
|
+
z-index: var(--z-confirm);
|
|
8476
|
+
display: flex;
|
|
8477
|
+
align-items: center;
|
|
8478
|
+
justify-content: center;
|
|
8479
|
+
padding: var(--space-5);
|
|
8480
|
+
animation: fadeIn var(--duration-fast) var(--ease-default);
|
|
8481
|
+
}
|
|
8482
|
+
|
|
8483
|
+
.whatsnew-dialog {
|
|
8484
|
+
position: relative;
|
|
8485
|
+
background: var(--bg-panel-solid);
|
|
8486
|
+
border: 1px solid var(--border);
|
|
8487
|
+
border-radius: var(--radius-lg);
|
|
8488
|
+
padding: var(--space-6);
|
|
8489
|
+
width: 460px;
|
|
8490
|
+
max-width: 100%;
|
|
8491
|
+
max-height: calc(100vh - var(--space-8));
|
|
8492
|
+
overflow-y: auto;
|
|
8493
|
+
box-shadow: var(--shadow-xl);
|
|
8494
|
+
animation: whatsnewIn var(--duration-slow) var(--ease-spring);
|
|
8495
|
+
}
|
|
8496
|
+
|
|
8497
|
+
@keyframes whatsnewIn {
|
|
8498
|
+
from { opacity: 0; transform: translateY(8px) scale(0.98); }
|
|
8499
|
+
to { opacity: 1; transform: none; }
|
|
8500
|
+
}
|
|
8501
|
+
|
|
8502
|
+
.whatsnew__close {
|
|
8503
|
+
position: absolute;
|
|
8504
|
+
top: var(--space-4);
|
|
8505
|
+
right: var(--space-4);
|
|
8506
|
+
width: 32px;
|
|
8507
|
+
height: 32px;
|
|
8508
|
+
display: inline-flex;
|
|
8509
|
+
align-items: center;
|
|
8510
|
+
justify-content: center;
|
|
8511
|
+
background: transparent;
|
|
8512
|
+
border: none;
|
|
8513
|
+
border-radius: var(--radius-sm);
|
|
8514
|
+
color: var(--text-dim);
|
|
8515
|
+
cursor: pointer;
|
|
8516
|
+
transition: color var(--duration-fast) var(--ease-default),
|
|
8517
|
+
background var(--duration-fast) var(--ease-default);
|
|
8518
|
+
}
|
|
8519
|
+
.whatsnew__close:hover { color: var(--text); background: var(--bg-hover); }
|
|
8520
|
+
.whatsnew__close:focus-visible { box-shadow: var(--shadow-focus); outline: none; }
|
|
8521
|
+
|
|
8522
|
+
/* Brand lockup — accent star on its dark container (brand rule: container intact) */
|
|
8523
|
+
.whatsnew__brand {
|
|
8524
|
+
display: flex;
|
|
8525
|
+
align-items: center;
|
|
8526
|
+
gap: var(--space-2);
|
|
8527
|
+
margin-bottom: var(--space-5);
|
|
8528
|
+
}
|
|
8529
|
+
.whatsnew__logo {
|
|
8530
|
+
width: 40px;
|
|
8531
|
+
height: 40px;
|
|
8532
|
+
display: inline-flex;
|
|
8533
|
+
align-items: center;
|
|
8534
|
+
justify-content: center;
|
|
8535
|
+
background: var(--bg);
|
|
8536
|
+
border: 1px solid var(--border);
|
|
8537
|
+
border-radius: var(--radius);
|
|
8538
|
+
}
|
|
8539
|
+
.whatsnew__wordmark {
|
|
8540
|
+
font-family: var(--font-display);
|
|
8541
|
+
font-size: var(--text-lg);
|
|
8542
|
+
font-weight: var(--weight-semibold);
|
|
8543
|
+
letter-spacing: var(--tracking-tight);
|
|
8544
|
+
color: var(--text);
|
|
8545
|
+
}
|
|
8546
|
+
.whatsnew__version {
|
|
8547
|
+
font-family: var(--font-mono);
|
|
8548
|
+
font-size: var(--text-xs);
|
|
8549
|
+
font-weight: var(--weight-medium);
|
|
8550
|
+
letter-spacing: var(--tracking-wide);
|
|
8551
|
+
color: var(--accent);
|
|
8552
|
+
background: var(--accent-tint);
|
|
8553
|
+
border: 1px solid var(--accent-dim);
|
|
8554
|
+
border-radius: var(--radius-pill);
|
|
8555
|
+
padding: 2px var(--space-2);
|
|
8556
|
+
}
|
|
8557
|
+
|
|
8558
|
+
.whatsnew__title {
|
|
8559
|
+
font-family: var(--font-display);
|
|
8560
|
+
font-size: var(--text-2xl);
|
|
8561
|
+
font-weight: var(--weight-bold);
|
|
8562
|
+
line-height: var(--leading-tight);
|
|
8563
|
+
letter-spacing: var(--tracking-tight);
|
|
8564
|
+
color: var(--text);
|
|
8565
|
+
margin: 0 0 var(--space-1);
|
|
8566
|
+
}
|
|
8567
|
+
.whatsnew__date {
|
|
8568
|
+
font-size: var(--text-sm);
|
|
8569
|
+
color: var(--text-dim);
|
|
8570
|
+
margin: 0 0 var(--space-5);
|
|
8571
|
+
}
|
|
8572
|
+
|
|
8573
|
+
.whatsnew__list {
|
|
8574
|
+
list-style: none;
|
|
8575
|
+
margin: 0 0 var(--space-6);
|
|
8576
|
+
padding: 0;
|
|
8577
|
+
display: flex;
|
|
8578
|
+
flex-direction: column;
|
|
8579
|
+
gap: var(--space-4);
|
|
8580
|
+
}
|
|
8581
|
+
.whatsnew__item {
|
|
8582
|
+
display: flex;
|
|
8583
|
+
align-items: flex-start;
|
|
8584
|
+
gap: var(--space-3);
|
|
8585
|
+
}
|
|
8586
|
+
.whatsnew__marker {
|
|
8587
|
+
flex: 0 0 auto;
|
|
8588
|
+
width: 28px;
|
|
8589
|
+
height: 28px;
|
|
8590
|
+
display: inline-flex;
|
|
8591
|
+
align-items: center;
|
|
8592
|
+
justify-content: center;
|
|
8593
|
+
background: var(--accent-tint);
|
|
8594
|
+
border-radius: var(--radius-sm);
|
|
8595
|
+
}
|
|
8596
|
+
.whatsnew__marker svg { width: 16px; height: 16px; }
|
|
8597
|
+
.whatsnew__item-text { display: flex; flex-direction: column; gap: 2px; }
|
|
8598
|
+
.whatsnew__item-title {
|
|
8599
|
+
font-size: var(--text-md);
|
|
8600
|
+
font-weight: var(--weight-semibold);
|
|
8601
|
+
color: var(--text);
|
|
8602
|
+
line-height: var(--leading-tight);
|
|
8603
|
+
}
|
|
8604
|
+
.whatsnew__item-body {
|
|
8605
|
+
font-size: var(--text-base);
|
|
8606
|
+
line-height: var(--leading-relaxed);
|
|
8607
|
+
color: var(--text-dim);
|
|
8608
|
+
}
|
|
8609
|
+
|
|
8610
|
+
.whatsnew__actions {
|
|
8611
|
+
display: flex;
|
|
8612
|
+
justify-content: flex-end;
|
|
8613
|
+
gap: var(--space-3);
|
|
8614
|
+
}
|
|
8615
|
+
.whatsnew__actions .btn { text-decoration: none; }
|
|
8616
|
+
|
|
8617
|
+
/* Narrow widths — modal becomes a bottom-anchored sheet, actions stack full-width */
|
|
8618
|
+
@media (max-width: 520px) {
|
|
8619
|
+
.whatsnew-overlay { align-items: flex-end; padding: 0; }
|
|
8620
|
+
.whatsnew-dialog {
|
|
8621
|
+
width: 100%;
|
|
8622
|
+
max-width: 100%;
|
|
8623
|
+
max-height: 90vh;
|
|
8624
|
+
padding: var(--space-5);
|
|
8625
|
+
border-radius: var(--radius-lg) var(--radius-lg) 0 0;
|
|
8626
|
+
border-bottom: none;
|
|
8627
|
+
animation: whatsnewSheetIn var(--duration-slow) var(--ease-out);
|
|
8628
|
+
}
|
|
8629
|
+
.whatsnew__title { font-size: var(--text-xl); }
|
|
8630
|
+
.whatsnew__actions { flex-direction: column-reverse; }
|
|
8631
|
+
.whatsnew__actions .btn { width: 100%; }
|
|
8632
|
+
}
|
|
8633
|
+
|
|
8634
|
+
@keyframes whatsnewSheetIn {
|
|
8635
|
+
from { opacity: 0; transform: translateY(100%); }
|
|
8636
|
+
to { opacity: 1; transform: none; }
|
|
8637
|
+
}
|
|
8638
|
+
|
|
8639
|
+
@media (prefers-reduced-motion: reduce) {
|
|
8640
|
+
.whatsnew-overlay,
|
|
8641
|
+
.whatsnew-dialog { animation: none; }
|
|
8642
|
+
}
|
package/ui/upload-panel.js
CHANGED
|
@@ -116,16 +116,15 @@ function showHubSpotSetupDialog(mode) {
|
|
|
116
116
|
});
|
|
117
117
|
const data = await res.json();
|
|
118
118
|
if (data.jobId) {
|
|
119
|
-
//
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
if (jr.status === "failed") { close(false); return; }
|
|
125
|
-
}
|
|
119
|
+
// pollJobUntilDone (setup.js) resolves on success and throws on
|
|
120
|
+
// failure / lost job (404) / timeout.
|
|
121
|
+
await pollJobUntilDone(data.jobId);
|
|
122
|
+
close(true);
|
|
123
|
+
return;
|
|
126
124
|
}
|
|
127
125
|
close(false);
|
|
128
|
-
} catch {
|
|
126
|
+
} catch (err) {
|
|
127
|
+
await vibeAlert("Install failed: " + (err.message || err), "Error");
|
|
129
128
|
close(false);
|
|
130
129
|
}
|
|
131
130
|
});
|