vibespot 1.2.0 → 1.3.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.
Files changed (43) hide show
  1. package/README.md +44 -5
  2. package/assets/blog-rules.md +251 -0
  3. package/assets/email-rules.md +390 -0
  4. package/assets/humanify-guide.md +300 -101
  5. package/assets/plan-templates/blog-content-hub.md +18 -9
  6. package/assets/plan-templates/email-announcement.md +41 -0
  7. package/assets/plan-templates/email-event-invite.md +43 -0
  8. package/assets/plan-templates/email-newsletter.md +41 -0
  9. package/assets/plan-templates/email-re-engagement.md +42 -0
  10. package/assets/plan-templates/email-welcome.md +41 -0
  11. package/dist/index.js +1460 -387
  12. package/dist/index.js.map +1 -1
  13. package/package.json +5 -5
  14. package/starters/06-blog-content-hub.json +75 -0
  15. package/starters/06-email-welcome.json +60 -0
  16. package/starters/07-email-announcement.json +60 -0
  17. package/starters/08-email-newsletter.json +52 -0
  18. package/ui/chat.js +777 -63
  19. package/ui/code-editor.js +49 -7
  20. package/ui/dashboard.js +379 -93
  21. package/ui/docs/docs.css +29 -0
  22. package/ui/docs/index.html +186 -108
  23. package/ui/docs/screenshots/brand-kit-preview.png +0 -0
  24. package/ui/docs/screenshots/content-type-dropdown.png +0 -0
  25. package/ui/docs/screenshots/editor-full-layout.png +0 -0
  26. package/ui/docs/screenshots/inline-wysiwyg-editing.png +0 -0
  27. package/ui/docs/screenshots/multi-page-tree.png +0 -0
  28. package/ui/docs/screenshots/onboarding-walkthrough.png +0 -0
  29. package/ui/docs/screenshots/split-pane-view.png +0 -0
  30. package/ui/docs/screenshots/visual-controls-toolbar.png +0 -0
  31. package/ui/docs/screenshots/workspace-tabs.png +0 -0
  32. package/ui/email-preview.js +109 -0
  33. package/ui/field-editor.js +72 -1
  34. package/ui/icons.js +120 -0
  35. package/ui/index.html +877 -629
  36. package/ui/inline-edit.js +710 -0
  37. package/ui/plan.js +0 -0
  38. package/ui/preview.js +101 -198
  39. package/ui/section-controls.js +628 -0
  40. package/ui/settings.js +58 -16
  41. package/ui/setup.js +750 -140
  42. package/ui/styles.css +3430 -952
  43. package/ui/upload-panel.js +47 -20
@@ -8,6 +8,7 @@ let lastUploadErrors = [];
8
8
  let lastUploadPortalId = "";
9
9
  let lastUploadDataCenter = "na1";
10
10
  let lastUploadThemeName = "";
11
+ let lastUploadContentMode = "page";
11
12
  const MAX_UPLOAD_ATTEMPTS = 3;
12
13
 
13
14
  async function startUpload() {
@@ -249,7 +250,7 @@ function confirmUpload(portalName, portalId) {
249
250
  let html = '<div style="display:flex;flex-direction:column;gap:6px">';
250
251
  for (const acct of accounts) {
251
252
  const isActive = acct.portalId === activeId;
252
- html += `<button class="btn btn--${isActive ? "primary" : "secondary"} confirm-acct-btn" data-portal="${esc(acct.portalId)}" style="text-align:left;padding:6px 12px;font-size:13px">${esc(acct.portalName || acct.portalId)} (${esc(acct.portalId)})${isActive ? " " : ""}</button>`;
253
+ html += `<button class="btn btn--${isActive ? "primary" : "secondary"} confirm-acct-btn" data-portal="${esc(acct.portalId)}" style="text-align:left;padding:6px 12px;font-size:13px">${esc(acct.portalName || acct.portalId)} (${esc(acct.portalId)})${isActive ? ' <span class="vs-icon-inline">' + vsIcon("check", {size: "sm"}) + '</span>' : ""}</button>`;
253
254
  }
254
255
  html += `<button class="btn btn--secondary confirm-acct-btn" data-portal="__new" style="text-align:left;padding:6px 12px;font-size:13px">+ Add another account</button>`;
255
256
  html += '</div>';
@@ -326,10 +327,10 @@ function setUploadState(state, data) {
326
327
 
327
328
  case "success":
328
329
  panel.classList.add("upload-panel--success");
329
- statusEl.innerHTML = '<span class="upload-status-icon">&#10003;</span> Upload complete!';
330
+ statusEl.innerHTML = '<span class="upload-status-icon">' + vsIcon("check-circle", {size: "sm"}) + '</span> Upload complete!';
330
331
  if (uploadBtn) {
331
332
  uploadBtn.textContent = "Deploy";
332
- uploadBtn.disabled = false;
333
+ uploadBtn.disabled = true;
333
334
  }
334
335
  const dismissBtn = document.createElement("button");
335
336
  dismissBtn.className = "upload-action-btn";
@@ -337,13 +338,16 @@ function setUploadState(state, data) {
337
338
  dismissBtn.addEventListener("click", () => setUploadState("idle"));
338
339
  actions.appendChild(dismissBtn);
339
340
 
340
- // Show the Create Page button
341
341
  if (lastUploadPortalId) {
342
+ const isEmail = lastUploadContentMode === "email";
342
343
  const createBtn = document.createElement("button");
343
344
  createBtn.className = "upload-action-btn upload-action-btn--primary";
344
- createBtn.textContent = "Create Page in HubSpot";
345
+ createBtn.textContent = isEmail ? "Create Email in HubSpot" : "Create Page in HubSpot";
345
346
  createBtn.addEventListener("click", () => {
346
- window.open(buildHubSpotPagesUrl(lastUploadPortalId, lastUploadDataCenter), "_blank");
347
+ const url = isEmail
348
+ ? buildHubSpotEmailUrl(lastUploadPortalId, lastUploadDataCenter)
349
+ : buildHubSpotPagesUrl(lastUploadPortalId, lastUploadDataCenter);
350
+ window.open(url, "_blank");
347
351
  });
348
352
  actions.insertBefore(createBtn, dismissBtn);
349
353
  }
@@ -351,10 +355,10 @@ function setUploadState(state, data) {
351
355
 
352
356
  case "failed":
353
357
  panel.classList.add("upload-panel--error");
354
- statusEl.innerHTML = '<span class="upload-status-icon">&#10007;</span> Upload failed';
358
+ statusEl.innerHTML = '<span class="upload-status-icon">' + vsIcon("x-circle", {size: "sm"}) + '</span> Upload failed';
355
359
  if (uploadBtn) {
356
360
  uploadBtn.textContent = "Deploy";
357
- uploadBtn.disabled = false;
361
+ uploadBtn.disabled = true;
358
362
  }
359
363
 
360
364
  const retryBtn = document.createElement("button");
@@ -387,10 +391,10 @@ function setUploadState(state, data) {
387
391
 
388
392
  case "fix_done":
389
393
  panel.classList.add("upload-panel--fixing");
390
- statusEl.innerHTML = '<span class="upload-status-icon">&#10003;</span> AI fixes applied';
394
+ statusEl.innerHTML = '<span class="upload-status-icon">' + vsIcon("check-circle", {size: "sm"}) + '</span> AI fixes applied';
391
395
  if (uploadBtn) {
392
396
  uploadBtn.textContent = "Deploy";
393
- uploadBtn.disabled = false;
397
+ uploadBtn.disabled = true;
394
398
  }
395
399
 
396
400
  const redeployBtn = document.createElement("button");
@@ -490,12 +494,13 @@ function handleUploadWsMessage(msg) {
490
494
  break;
491
495
 
492
496
  case "upload_complete":
497
+ lastUploadContentMode = msg.contentMode || "page";
493
498
  setUploadState("success");
494
499
  // Update status bar
495
500
  const statusText = document.getElementById("status-text");
496
501
  if (statusText) statusText.textContent = "Upload complete!";
497
502
  // Show celebration popup
498
- showDeploySuccessPopup(msg.portalId, msg.dataCenter || "na1", msg.themeName);
503
+ showDeploySuccessPopup(msg.portalId, msg.dataCenter || "na1", msg.themeName, lastUploadContentMode);
499
504
  break;
500
505
 
501
506
  case "upload_failed":
@@ -538,32 +543,54 @@ function buildHubSpotPagesUrl(portalId, dataCenter) {
538
543
  return `https://${host}/page-ui/${portalId}/management/pages/landing`;
539
544
  }
540
545
 
541
- function showDeploySuccessPopup(portalId, dataCenter, themeName) {
546
+ function buildHubSpotEmailUrl(portalId, dataCenter) {
547
+ const host = dataCenter === "eu1" ? "app-eu1.hubspot.com" : "app.hubspot.com";
548
+ return `https://${host}/email/${portalId}`;
549
+ }
550
+
551
+ function showDeploySuccessPopup(portalId, dataCenter, themeName, contentMode) {
542
552
  lastUploadPortalId = portalId || "";
543
553
  lastUploadDataCenter = dataCenter || "na1";
544
554
  lastUploadThemeName = themeName || "";
545
555
 
546
556
  const name = themeName || "your theme";
547
- const lpLabel = `${name} Landing Page`;
548
- const pagesUrl = portalId ? buildHubSpotPagesUrl(portalId, dataCenter) : "";
557
+ const isEmail = contentMode === "email";
549
558
 
550
559
  // Spawn confetti
551
560
  spawnConfetti();
552
561
 
562
+ let stepsHtml, actionUrl, actionLabel;
563
+ if (isEmail) {
564
+ actionUrl = portalId ? buildHubSpotEmailUrl(portalId, dataCenter) : "";
565
+ actionLabel = "Create Email in HubSpot";
566
+ stepsHtml = `
567
+ <div class="deploy-success__step"><span class="deploy-success__num">1</span> Go to <strong>Marketing &rarr; Email</strong></div>
568
+ <div class="deploy-success__step"><span class="deploy-success__num">2</span> Click <strong>"Create email"</strong></div>
569
+ <div class="deploy-success__step"><span class="deploy-success__num">3</span> Select your <strong>"${esc(name)}"</strong> template</div>
570
+ `;
571
+ } else {
572
+ const lpLabel = `${name} Landing Page`;
573
+ actionUrl = portalId ? buildHubSpotPagesUrl(portalId, dataCenter) : "";
574
+ actionLabel = "Create Page in HubSpot";
575
+ stepsHtml = `
576
+ <div class="deploy-success__step"><span class="deploy-success__num">1</span> Go to <strong>Content &rarr; Landing Pages</strong></div>
577
+ <div class="deploy-success__step"><span class="deploy-success__num">2</span> Click <strong>"Create" &rarr; "Landing page"</strong></div>
578
+ <div class="deploy-success__step"><span class="deploy-success__num">3</span> Select the <strong>"${esc(lpLabel)}"</strong> template</div>
579
+ `;
580
+ }
581
+
553
582
  const overlay = document.createElement("div");
554
583
  overlay.className = "confirm-overlay";
555
584
  overlay.innerHTML = `
556
585
  <div class="deploy-success">
557
- <div class="deploy-success__icon">&#127881;</div>
558
- <h2 class="deploy-success__title">Theme deployed!</h2>
586
+ <div class="deploy-success__icon">${vsIcon("rocket", {size: "md"})}</div>
587
+ <h2 class="deploy-success__title">${isEmail ? "Email template deployed!" : "Theme deployed!"}</h2>
559
588
  <p class="deploy-success__subtitle">"${esc(name)}" is now live on HubSpot.</p>
560
589
  <div class="deploy-success__steps">
561
- <div class="deploy-success__step"><span class="deploy-success__num">1</span> Go to <strong>Content &rarr; Landing Pages</strong></div>
562
- <div class="deploy-success__step"><span class="deploy-success__num">2</span> Click <strong>"Create" &rarr; "Landing page"</strong></div>
563
- <div class="deploy-success__step"><span class="deploy-success__num">3</span> Select the <strong>"${esc(lpLabel)}"</strong> template</div>
590
+ ${stepsHtml}
564
591
  </div>
565
592
  <div class="deploy-success__actions">
566
- ${pagesUrl ? `<a href="${pagesUrl}" target="_blank" class="btn btn--primary deploy-success__link">Create Page in HubSpot &rarr;</a>` : ""}
593
+ ${actionUrl ? `<a href="${actionUrl}" target="_blank" class="btn btn--primary deploy-success__link">${actionLabel} &rarr;</a>` : ""}
567
594
  <button class="btn btn--secondary" id="deploy-success-dismiss">Close</button>
568
595
  </div>
569
596
  </div>