vibespot 0.9.3 → 0.9.4

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": "vibespot",
3
- "version": "0.9.3",
3
+ "version": "0.9.4",
4
4
  "description": "AI-powered HubSpot CMS landing page builder — vibe coding & React converter",
5
5
  "type": "module",
6
6
  "bin": {
package/ui/dashboard.js CHANGED
@@ -330,7 +330,7 @@ async function viewStyleguide() {
330
330
  const res = await fetch("/api/brand-assets");
331
331
  const data = await res.json();
332
332
  if (data.styleguide) {
333
- await vibeViewContent(data.styleguide, "Styleguide");
333
+ await vibeViewContent(data.styleguide, "Styleguide", "styleguide.md");
334
334
  } else {
335
335
  await vibeAlert("No styleguide found.", "Info");
336
336
  }
@@ -344,7 +344,7 @@ async function viewBrandvoice() {
344
344
  const res = await fetch("/api/brand-assets");
345
345
  const data = await res.json();
346
346
  if (data.brandvoice) {
347
- await vibeViewContent(data.brandvoice, "Brand Voice");
347
+ await vibeViewContent(data.brandvoice, "Brand Voice", "brandvoice.md");
348
348
  } else {
349
349
  await vibeAlert("No brand voice found.", "Info");
350
350
  }
@@ -563,7 +563,7 @@ document.getElementById("btn-extract-design")?.addEventListener("click", async (
563
563
  await refreshDashboard();
564
564
  const view = await vibeConfirm("Design system extracted and saved as styleguide.", "Would you like to view it?", { confirmLabel: "View Styleguide", confirmClass: "btn--primary" });
565
565
  if (view && data.styleguide) {
566
- await vibeViewContent(data.styleguide, "Styleguide");
566
+ await vibeViewContent(data.styleguide, "Styleguide", "styleguide.md");
567
567
  }
568
568
  } else {
569
569
  await vibeAlert(data.error || "Extraction failed", "Error");
@@ -607,7 +607,7 @@ document.getElementById("btn-import-reference")?.addEventListener("click", async
607
607
  await refreshDashboard();
608
608
  const view = await vibeConfirm("Design imported and saved as styleguide.", "Would you like to view it?", { confirmLabel: "View Styleguide", confirmClass: "btn--primary" });
609
609
  if (view && data.styleguide) {
610
- await vibeViewContent(data.styleguide, "Styleguide");
610
+ await vibeViewContent(data.styleguide, "Styleguide", "styleguide.md");
611
611
  }
612
612
  } else {
613
613
  await vibeAlert(data.error || "Import failed", "Error");
package/ui/dialog.js CHANGED
@@ -217,7 +217,7 @@ function vibeFeedback() {
217
217
  * @param {string} [title] — dialog title
218
218
  * @returns {Promise<void>}
219
219
  */
220
- function vibeViewContent(content, title) {
220
+ function vibeViewContent(content, title, downloadFilename) {
221
221
  return new Promise((resolve) => {
222
222
  const overlay = document.createElement("div");
223
223
  overlay.className = "confirm-overlay";
@@ -232,17 +232,36 @@ function vibeViewContent(content, title) {
232
232
  const body = document.createElement("div");
233
233
  body.className = "confirm-dialog__content-view md-body";
234
234
  body.innerHTML = typeof marked !== "undefined" ? marked.parse(content) : esc(content);
235
+ // Inject color swatches next to hex codes
236
+ body.innerHTML = body.innerHTML.replace(
237
+ /(#[0-9A-Fa-f]{3,8})(?![0-9A-Fa-f])/g,
238
+ '<span class="color-swatch-wrap">$1<span class="color-swatch" style="background:$1"></span></span>'
239
+ );
235
240
  dialog.appendChild(body);
236
241
 
237
242
  const actions = document.createElement("div");
238
243
  actions.className = "confirm-dialog__actions";
239
- actions.innerHTML = '<button class="btn btn--primary" data-action="ok">Close</button>';
244
+ if (downloadFilename) {
245
+ actions.innerHTML = '<button class="btn btn--secondary" data-action="download">Download</button>';
246
+ }
247
+ actions.innerHTML += '<button class="btn btn--primary" data-action="ok">Close</button>';
240
248
  dialog.appendChild(actions);
241
249
 
242
250
  overlay.appendChild(dialog);
243
251
  document.body.appendChild(overlay);
244
252
 
245
253
  const close = () => { overlay.remove(); resolve(); };
254
+ if (downloadFilename) {
255
+ overlay.querySelector('[data-action="download"]').addEventListener("click", () => {
256
+ const blob = new Blob([content], { type: "text/markdown" });
257
+ const url = URL.createObjectURL(blob);
258
+ const a = document.createElement("a");
259
+ a.href = url;
260
+ a.download = downloadFilename;
261
+ a.click();
262
+ URL.revokeObjectURL(url);
263
+ });
264
+ }
246
265
  overlay.querySelector('[data-action="ok"]').addEventListener("click", close);
247
266
  overlay.addEventListener("click", (e) => { if (e.target === overlay) close(); });
248
267
  document.addEventListener("keydown", function onKey(e) {
package/ui/styles.css CHANGED
@@ -1151,6 +1151,16 @@ body { display: flex; }
1151
1151
  border-radius: 0;
1152
1152
  font-size: inherit;
1153
1153
  }
1154
+ .color-swatch-wrap { white-space: nowrap; }
1155
+ .color-swatch {
1156
+ display: inline-block;
1157
+ width: 12px;
1158
+ height: 12px;
1159
+ border-radius: 3px;
1160
+ margin-left: 4px;
1161
+ vertical-align: middle;
1162
+ border: 1px solid var(--border);
1163
+ }
1154
1164
  .confirm-dialog__title {
1155
1165
  font-size: 16px;
1156
1166
  font-weight: 600;