@sonordev/site-kit 7.1.1 → 7.2.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 (282) hide show
  1. package/AGENTS.md +3 -3
  2. package/CHANGELOG.md +68 -3426
  3. package/README.md +9 -8
  4. package/agent-manifest.json +12 -4
  5. package/dist/{AnalyticsProvider-3MI5RCTL.js → AnalyticsProvider-SLFFBRPE.js} +4 -4
  6. package/dist/{ArticleViewTracker-CMBSJR3N.js → ArticleViewTracker-TM5AMGN2.js} +3 -3
  7. package/dist/{BlocksPopup-X3OAAK2L.js → BlocksPopup-YJNJIVPO.js} +5 -5
  8. package/dist/ChatWidget-XKOSH66S.js +17 -0
  9. package/dist/{FileField-QRSEGO6D.js → FileField-CI4UL5SH.js} +3 -3
  10. package/dist/{FormSpotlight-XKV7VTN4.js → FormSpotlight-F2AAEGBN.js} +20 -6
  11. package/dist/{FormStage-C3YGYAUZ.js → FormStage-BI5R5CNC.js} +27 -7
  12. package/dist/ManagedForm-G6COGHXL.js +16 -0
  13. package/dist/{ManagedNewsletterForm-LPIKGJF4.js → ManagedNewsletterForm-BO3WCGXX.js} +7 -5
  14. package/dist/{SignalCore-ICXXZBYI.js → SignalCore-ZA6WHKBR.js} +3 -3
  15. package/dist/SiteChat-YJADDTKG.js +5 -0
  16. package/dist/{SiteDesignReporter-A7MS2CIP.js → SiteDesignReporter-5YAW36AQ.js} +5 -5
  17. package/dist/SitePopups-ST5PMKZE.js +10 -0
  18. package/dist/SitemapSync-RJTEBINX.js +8 -0
  19. package/dist/SitemapSync.d.ts +1 -1
  20. package/dist/_client/booking-widget.js +5 -5
  21. package/dist/_client/testimonial-section.d.ts +1 -1
  22. package/dist/affiliates/api.d.ts +1 -1
  23. package/dist/affiliates/index.js +3 -3
  24. package/dist/analytics/AnalyticsProvider.d.ts +1 -1
  25. package/dist/analytics/index.js +4 -4
  26. package/dist/analytics/send-gate.d.ts +13 -26
  27. package/dist/articles/Article.d.ts +1 -1
  28. package/dist/articles/ArticleList.d.ts +1 -1
  29. package/dist/articles/ClusterLandingPage.d.ts +2 -2
  30. package/dist/articles/PublicationLayout.d.ts +1 -1
  31. package/dist/articles/PublicationSidebar.d.ts +1 -1
  32. package/dist/articles/RelatedPosts.d.ts +1 -1
  33. package/dist/articles/author-schema.d.ts +1 -1
  34. package/dist/articles/excerpt.d.ts +3 -4
  35. package/dist/articles/index.d.ts +2 -2
  36. package/dist/articles/index.js +2 -2
  37. package/dist/articles/news-sitemap.d.ts +1 -1
  38. package/dist/articles/processArticleHtml.d.ts +1 -1
  39. package/dist/articles/server-core.d.ts +4 -4
  40. package/dist/articles/server-ui.js +3 -2
  41. package/dist/articles/server.d.ts +4 -4
  42. package/dist/articles/server.js +2 -1
  43. package/dist/articles/types.d.ts +1 -1
  44. package/dist/{engage → chat}/ChatWidget.d.ts +8 -7
  45. package/dist/{engage → chat}/EchoUiActions.d.ts +4 -4
  46. package/dist/chat/SiteChat.d.ts +25 -0
  47. package/dist/{engage → chat}/brand-color.d.ts +2 -2
  48. package/dist/{engage → chat}/chat-messages.d.ts +1 -1
  49. package/dist/{engage → chat}/echo-config.d.ts +1 -1
  50. package/dist/chat/index.d.ts +10 -6
  51. package/dist/chat/index.js +14 -8
  52. package/dist/{engage → chat}/launcher-placement.d.ts +1 -7
  53. package/dist/{engage → chat}/socket-loader.d.ts +2 -2
  54. package/dist/chat/types.d.ts +136 -0
  55. package/dist/chunk-27FISYK4.js +4 -0
  56. package/dist/{chunk-QPEEKFCA.js → chunk-4NTBQNHA.js} +249 -80
  57. package/dist/{chunk-RK7GF7PQ.js → chunk-5V2V5C3Y.js} +2 -4
  58. package/dist/{chunk-ICFRH2ED.js → chunk-5YCEMV2L.js} +1 -1
  59. package/dist/{chunk-V4HUSHZO.js → chunk-64DKGVEI.js} +41 -7
  60. package/dist/{chunk-GLHQ3LRO.js → chunk-6U3VLV2C.js} +1 -1
  61. package/dist/{chunk-ZETJTCMV.js → chunk-BC4Y3S3D.js} +1 -1
  62. package/dist/{chunk-JSZN6LDZ.js → chunk-BF7TZYC3.js} +38 -31
  63. package/dist/{chunk-EFPS56JA.js → chunk-BKY2ZNM7.js} +1 -1
  64. package/dist/{chunk-AQSNPZY4.js → chunk-C2FZBUSS.js} +80 -1
  65. package/dist/{chunk-H42PZKVC.js → chunk-CF5QNFYU.js} +2 -2
  66. package/dist/{chunk-JC7KXNNM.js → chunk-D5DCBD4Y.js} +2 -2
  67. package/dist/{chunk-PXZ7LAOY.js → chunk-D6ZC7XKZ.js} +2 -2
  68. package/dist/chunk-EJVQJCG5.js +370 -0
  69. package/dist/{chunk-6OL23QYD.js → chunk-F24FNCTK.js} +1 -1
  70. package/dist/{chunk-NEKEH4CK.js → chunk-FR6BYFPC.js} +53 -21
  71. package/dist/{chunk-KOPVJQ2P.js → chunk-GEXT7BTE.js} +1 -1
  72. package/dist/{chunk-ZAWANWUS.js → chunk-GGORNBSC.js} +18 -6
  73. package/dist/{chunk-DUQMSNF2.js → chunk-HGFAEDG3.js} +1 -1
  74. package/dist/chunk-HODO5BX5.js +28 -0
  75. package/dist/chunk-HW7B43E5.js +14 -0
  76. package/dist/{chunk-EQBZ24VH.js → chunk-IAM3D3RL.js} +43 -24
  77. package/dist/{chunk-ODADQM6Z.js → chunk-JJ3DELUL.js} +2 -2
  78. package/dist/{chunk-542MIHNP.js → chunk-JMLK6MH7.js} +1 -1
  79. package/dist/{chunk-7FWA3I6A.js → chunk-JWTQS5F5.js} +1 -1
  80. package/dist/{chunk-OUNRFXDC.js → chunk-K4ZHAURD.js} +1 -1
  81. package/dist/chunk-NV72HZ4W.js +45 -0
  82. package/dist/{chunk-4Y5FWDPM.js → chunk-NZ4RXN3G.js} +55 -7
  83. package/dist/chunk-OWZ7ATLZ.js +187 -0
  84. package/dist/{chunk-TXBAOEKG.js → chunk-PKGN32AU.js} +5 -4
  85. package/dist/chunk-Q6E4OPGG.js +40 -0
  86. package/dist/{chunk-J4D6ZXRW.js → chunk-QL6XNPSD.js} +3 -3
  87. package/dist/{chunk-HAG4YIZY.js → chunk-R46IQIGK.js} +6 -6
  88. package/dist/{chunk-R3VKF43H.js → chunk-RPZ7OQGD.js} +1 -1
  89. package/dist/{chunk-Q3S26EQA.js → chunk-S54ECQGY.js} +1 -1
  90. package/dist/{chunk-JIL5VY2R.js → chunk-VHKEF5ZB.js} +1 -1
  91. package/dist/{chunk-ILAW3XKD.js → chunk-VO3JYRT5.js} +43 -29
  92. package/dist/chunk-VWWITFWM.js +300 -0
  93. package/dist/{chunk-OPRBF7VE.js → chunk-ZTLMPUO6.js} +3 -2
  94. package/dist/client/index.js +3 -3
  95. package/dist/cms/CmsPreview.d.ts +2 -2
  96. package/dist/cms/index.d.ts +3 -3
  97. package/dist/cms/server-api.d.ts +1 -1
  98. package/dist/cms/types.d.ts +1 -1
  99. package/dist/commerce/EventCheckout.d.ts +1 -1
  100. package/dist/commerce/EventsAgenda.d.ts +3 -3
  101. package/dist/commerce/api.d.ts +1 -1
  102. package/dist/commerce/index.js +4 -4
  103. package/dist/commerce/server.d.ts +3 -4
  104. package/dist/contracts/color.d.ts +1 -1
  105. package/dist/contracts/entries.d.ts +1 -1
  106. package/dist/contracts/error-page.d.ts +183 -0
  107. package/dist/contracts/fleet.d.ts +9 -9
  108. package/dist/contracts/forms.d.ts +4 -10
  109. package/dist/contracts/llms.d.ts +2 -1
  110. package/dist/contracts/portfolio.d.ts +11 -15
  111. package/dist/contracts/proposal-sitemap.d.ts +130 -0
  112. package/dist/contracts/schema-placeholders.d.ts +87 -0
  113. package/dist/contracts/seo-meta.d.ts +11 -12
  114. package/dist/contracts/seo-pages.d.ts +12 -18
  115. package/dist/contracts/site-cache.d.ts +4 -4
  116. package/dist/contracts/sites-normalize.d.ts +2 -4
  117. package/dist/contracts/sites.d.ts +3 -5
  118. package/dist/contracts/slot-content.d.ts +2 -2
  119. package/dist/contracts/slots.d.ts +6 -6
  120. package/dist/contracts/voice.d.ts +56 -0
  121. package/dist/contracts/website.d.ts +2 -2
  122. package/dist/engage/EngageWidget.d.ts +13 -12
  123. package/dist/engage/index.d.ts +10 -9
  124. package/dist/engage/index.js +31 -35
  125. package/dist/engage/types.d.ts +19 -244
  126. package/dist/fleet/FleetHeartbeat.d.ts +2 -2
  127. package/dist/fleet/index.js +4 -4
  128. package/dist/forms/FormEnhancer.d.ts +25 -12
  129. package/dist/forms/FormSpotlight.d.ts +2 -2
  130. package/dist/forms/ManagedForm.d.ts +1 -1
  131. package/dist/forms/ServerForm.d.ts +11 -10
  132. package/dist/forms/StaticForm.d.ts +4 -2
  133. package/dist/forms/field-autocomplete.d.ts +28 -0
  134. package/dist/forms/field-interactions.d.ts +2 -2
  135. package/dist/forms/form-dom-values.d.ts +42 -0
  136. package/dist/forms/form-loaded-at.d.ts +2 -2
  137. package/dist/forms/formsApi.d.ts +2 -2
  138. package/dist/forms/index.d.ts +1 -1
  139. package/dist/forms/index.js +11 -9
  140. package/dist/forms/server.d.ts +1 -1
  141. package/dist/forms/server.js +6 -4
  142. package/dist/forms/static.js +3 -2
  143. package/dist/forms/submitForm.d.ts +9 -2
  144. package/dist/forms/types.d.ts +44 -5
  145. package/dist/forms/useForm.d.ts +21 -4
  146. package/dist/forms/webmcp.d.ts +38 -0
  147. package/dist/images/ManagedFavicon.d.ts +1 -1
  148. package/dist/images/ManagedImage.d.ts +4 -4
  149. package/dist/images/api.d.ts +1 -1
  150. package/dist/images/index.d.ts +2 -2
  151. package/dist/images/index.js +4 -4
  152. package/dist/index.d.ts +4 -1
  153. package/dist/index.js +1 -1
  154. package/dist/landing/contract.d.ts +3 -4
  155. package/dist/layout/SiteKitClientProviders.d.ts +4 -4
  156. package/dist/layout/SiteKitLayout.d.ts +11 -11
  157. package/dist/layout/client.d.ts +4 -4
  158. package/dist/layout/client.js +7 -7
  159. package/dist/layout/index.js +8 -8
  160. package/dist/layout/types.d.ts +7 -6
  161. package/dist/llms/SpeakableSchema.d.ts +2 -2
  162. package/dist/llms/agent-access.d.ts +2 -2
  163. package/dist/llms/aiRobots.d.ts +4 -4
  164. package/dist/llms/api.d.ts +2 -2
  165. package/dist/llms/contract.js +1 -1
  166. package/dist/llms/generateLLMsTxt.d.ts +1 -1
  167. package/dist/llms/index.js +6 -6
  168. package/dist/llms/links.d.ts +1 -1
  169. package/dist/llms/revalidate.d.ts +1 -1
  170. package/dist/llms/seo-revalidate.d.ts +2 -3
  171. package/dist/llms/types.d.ts +6 -6
  172. package/dist/llms/writeLLMsTxt.d.ts +10 -10
  173. package/dist/manifest/index.d.ts +8 -8
  174. package/dist/maps/index.js +3 -3
  175. package/dist/mcp/WebMcpTools.d.ts +1 -1
  176. package/dist/mcp/index.js +2 -14
  177. package/dist/mcp/report.d.ts +2 -2
  178. package/dist/mcp/serverCard.d.ts +1 -1
  179. package/dist/mcp/sonor.d.ts +5 -6
  180. package/dist/mcp/sonor.js +14 -11
  181. package/dist/mcp/transport.d.ts +1 -2
  182. package/dist/mcp/types.d.ts +4 -5
  183. package/dist/motion/engine.d.ts +2 -3
  184. package/dist/motion/failsafe.d.ts +1 -2
  185. package/dist/motion/gsap.d.ts +2 -2
  186. package/dist/motion/three.d.ts +1 -1
  187. package/dist/og/config.d.ts +4 -4
  188. package/dist/og/contrast.d.ts +2 -2
  189. package/dist/og/pages.d.ts +5 -5
  190. package/dist/og/route-fit.d.ts +2 -2
  191. package/dist/og/route.d.ts +1 -2
  192. package/dist/og/template.d.ts +1 -1
  193. package/dist/proxy/index.d.ts +2 -2
  194. package/dist/proxy/securityHeaders.d.ts +10 -12
  195. package/dist/redirects/index.d.ts +7 -7
  196. package/dist/reputation/TestimonialSection.d.ts +1 -1
  197. package/dist/reputation/api.d.ts +1 -1
  198. package/dist/revalidate/index.js +2 -2
  199. package/dist/robots/index.d.ts +5 -5
  200. package/dist/robots/indexnow.d.ts +2 -3
  201. package/dist/seo/ManagedScripts.d.ts +2 -2
  202. package/dist/seo/client.js +4 -4
  203. package/dist/seo/getManagedMetadata.d.ts +1 -1
  204. package/dist/seo/groundingSchema.d.ts +2 -2
  205. package/dist/seo/index.js +15 -8
  206. package/dist/seo/llms/contract.js +1 -1
  207. package/dist/seo/llms.js +6 -6
  208. package/dist/seo/register-sitemap-cli-impl.d.ts +1 -1
  209. package/dist/seo/register-sitemap-cli.d.ts +1 -1
  210. package/dist/seo/register-sitemap-cli.js +2 -2
  211. package/dist/seo/schema-filter.d.ts +5 -6
  212. package/dist/seo/server-api.d.ts +1 -1
  213. package/dist/seo/sitemap.js +4 -4
  214. package/dist/seo/types.d.ts +4 -4
  215. package/dist/seo/withManagedMetadata.d.ts +4 -4
  216. package/dist/server/index.js +2 -2
  217. package/dist/server/mint-site-token.d.ts +1 -2
  218. package/dist/server/server-fetch.d.ts +5 -5
  219. package/dist/shared/build-entries.d.ts +4 -4
  220. package/dist/shared/dialog.d.ts +27 -0
  221. package/dist/shared/frame.d.ts +8 -9
  222. package/dist/shared/fresh-fetch.d.ts +1 -2
  223. package/dist/shared/identity.d.ts +1 -1
  224. package/dist/shared/layers.d.ts +7 -0
  225. package/dist/shared/mid-form.d.ts +53 -0
  226. package/dist/shared/next-files.d.ts +1 -1
  227. package/dist/shared/publishCredential.d.ts +1 -1
  228. package/dist/shared/reporting-gate.d.ts +1 -1
  229. package/dist/shared/uuid.d.ts +1 -2
  230. package/dist/shared/version.d.ts +1 -1
  231. package/dist/shared/visual-viewport-gap.d.ts +3 -3
  232. package/dist/signal/index.js +2 -2
  233. package/dist/signal/types.d.ts +1 -1
  234. package/dist/site-config/index.d.ts +2 -2
  235. package/dist/sitemap/index.d.ts +13 -13
  236. package/dist/sitemap/index.js +4 -4
  237. package/dist/sitemap/shared.d.ts +3 -3
  238. package/dist/sites/site-param.d.ts +2 -2
  239. package/dist/slots/ManagedRichText.d.ts +1 -1
  240. package/dist/slots/ManagedSlot.d.ts +1 -1
  241. package/dist/slots/index.d.ts +1 -3
  242. package/dist/{socket-loader-R24ZSRSQ.js → socket-loader-CGIPEG74.js} +1 -1
  243. package/dist/sync/index.js +5 -5
  244. package/dist/types.d.ts +4 -2
  245. package/dist/website/BlocksPopup.d.ts +1 -1
  246. package/dist/website/PopupBlocks.d.ts +8 -6
  247. package/dist/website/SitePopups.d.ts +25 -0
  248. package/dist/website/images.js +4 -4
  249. package/dist/website/index.js +6 -6
  250. package/dist/website/popup-rules.d.ts +46 -0
  251. package/dist/website/popup-types.d.ts +113 -0
  252. package/dist/website/popups.d.ts +2 -6
  253. package/dist/website/popups.js +6 -14
  254. package/dist/{writeLLMsTxt-QR23OQUE.js → writeLLMsTxt-OV24LQVL.js} +3 -3
  255. package/docs/MIGRATING-TO-7.md +50 -22
  256. package/docs.json +2 -1
  257. package/package.json +2 -2
  258. package/src/admin-auth/README.md +3 -3
  259. package/src/analytics/README.md +9 -11
  260. package/src/articles/README.md +10 -7
  261. package/src/{engage → chat}/README.md +63 -62
  262. package/src/cta-bar/README.md +11 -11
  263. package/src/forms/README.md +60 -12
  264. package/src/layout/README.md +8 -5
  265. package/src/llms/README.md +3 -3
  266. package/src/mcp/README.md +7 -7
  267. package/src/motion/README.md +1 -1
  268. package/src/og/README.md +26 -27
  269. package/src/proxy/README.md +14 -14
  270. package/src/seo/README.md +4 -2
  271. package/src/slots/README.md +1 -1
  272. package/src/sync/README.md +10 -0
  273. package/src/website/README.md +133 -0
  274. package/dist/ChatWidget-JMFBXJ75.js +0 -15
  275. package/dist/EngageWidget-A3QKZ3SU.js +0 -11
  276. package/dist/ManagedForm-2GSSDJPP.js +0 -14
  277. package/dist/SitemapSync-4U654SEA.js +0 -8
  278. package/dist/chunk-B73QPZPH.js +0 -837
  279. package/dist/chunk-NDF4A5JM.js +0 -37
  280. package/dist/chunk-RTMMHTEQ.js +0 -100
  281. package/dist/engage/DesignRenderer.d.ts +0 -57
  282. package/dist/engage/element-rules.d.ts +0 -38
@@ -21,8 +21,7 @@
21
21
  * that directory between builds (Netlify does), so every later build
22
22
  * replays the first response. That's how public/llms.txt shipped a
23
23
  * months-old copy: its fetch carried no option, was cached with a one-year
24
- * revalidate, and each build rewrote the same stale file (found on
25
- * vsfconsultingservices.com, 2026-09-15).
24
+ * revalidate, and each build rewrote the same stale file.
26
25
  *
27
26
  * So we call the original fetch Next keeps on the patched one and stay
28
27
  * invisible to the framework: no bailout, no cache entry, no effect on the
@@ -2,7 +2,7 @@
2
2
  * @sonordev/site-kit/shared — Unified Identity Management
3
3
  *
4
4
  * Single source of truth for visitor and session IDs across
5
- * Analytics, Signal, and Engage modules.
5
+ * Analytics, Signal, chat and popups.
6
6
  *
7
7
  * Storage keys:
8
8
  * localStorage: _sk_vid (visitor ID, persists ~forever)
@@ -0,0 +1,7 @@
1
+ /**
2
+ * The layer a site's widgets stack on when the site sets nothing: popups,
3
+ * banners and toasts (SitePopups) and the chat launcher (SiteChat), with the
4
+ * chat window one below. Single source of truth for that default; the
5
+ * layout's `chat.zIndex` (or the deprecated `engage.zIndex`) overrides it.
6
+ */
7
+ export declare const DEFAULT_WIDGET_Z_INDEX = 9999;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @sonordev/site-kit shared: is the visitor in the middle of a form?
3
+ *
4
+ * SINGLE SOURCE OF TRUTH for whether something may open over the page right
5
+ * now. SitePopups asks before any popup or toast opens on its own (whatever
6
+ * the trigger: immediate, delay, scroll or exit intent) and waits while the
7
+ * answer is yes.
8
+ * Don't write a second check; extend this one.
9
+ *
10
+ * Why it matters: a modal popup takes focus and hides the rest of the page
11
+ * from assistive technology while it's open. Opening one mid-form throws a
12
+ * person out of the field they're typing in, and an agent browser filling the
13
+ * form for someone (they act on the accessibility tree) loses every field it
14
+ * was about to fill.
15
+ *
16
+ * Mid-form means any of:
17
+ * - focus is on a field (input, textarea, select) that belongs to a form, or
18
+ * inside a frame in a form (a payment provider's card field);
19
+ * - a form has a field the visitor filled: a value that isn't empty and isn't
20
+ * the one the page rendered with, or one they typed into (watchFormInput);
21
+ * - a site-kit form is carrying what the visitor typed into its server-rendered
22
+ * shell before it upgraded (FormEnhancer marks its wrapper
23
+ * `data-sk-carried`; the upgraded fields are new elements nobody typed into
24
+ * yet, and React keeps their default equal to their value);
25
+ * - a site-kit form is sending (`data-sk-state="submitting"`).
26
+ *
27
+ * Fields a visitor doesn't fill don't count: hidden inputs, buttons, fields
28
+ * nobody can see or reach (inert or aria-hidden), and site-kit's trap field.
29
+ */
30
+ /**
31
+ * Remember which fields the visitor types into from here on. React keeps a
32
+ * controlled field's default value equal to its current value, so comparing
33
+ * the two can't see what someone typed into one; the input event can.
34
+ * Idempotent: one pair of capture listeners per document, kept for the page's
35
+ * life. SitePopups starts it when it mounts.
36
+ */
37
+ export declare function watchFormInput(doc?: Document): void;
38
+ /** Whether the visitor is in the middle of a form (see the module comment for what counts). */
39
+ export declare function isVisitorMidForm(doc?: Document): boolean;
40
+ export interface MidFormWaitOptions {
41
+ doc?: Document;
42
+ /** How long after focus leaves a field to look again. Default 1500ms. */
43
+ settleMs?: number;
44
+ /** How often to look again while waiting. Default 5000ms. */
45
+ pollMs?: number;
46
+ }
47
+ /**
48
+ * Run `open` now if the visitor isn't mid-form, otherwise as soon as they
49
+ * aren't: a moment after focus leaves a field, or on the next poll (a form
50
+ * that sent and cleared, or went away). Never gives up on its own; the
51
+ * returned function cancels the wait. `open` runs at most once.
52
+ */
53
+ export declare function whenNotMidForm(open: () => void, options?: MidFormWaitOptions): () => void;
@@ -4,7 +4,7 @@
4
4
  * SINGLE SOURCE OF TRUTH for "find the root layout / a page / the proxy". Each
5
5
  * CLI check used to carry its own candidate list, and the lists drifted: the OG
6
6
  * wiring rule only looked for `app/layout.tsx`, so `doctor` told a site whose
7
- * root layout is `app/layout.jsx` (heinrich-law-nextjs, 2026-09-14) that it had
7
+ * root layout is `app/layout.jsx` that it had
8
8
  * no layout at all. `geo` knew about `.jsx` but not `src/app`, and none of them
9
9
  * knew about `proxy.ts`. Route every lookup through here; never re-fork a list.
10
10
  *
@@ -10,7 +10,7 @@
10
10
  * `@sonordev/agency-site-kit`'s `AgencySiteKitLayout`.
11
11
  *
12
12
  * Do not re-fork this. Before it existed, agency sites hand-rolled their own
13
- * "set the globals on mount" component (upforge's `UptradeSiteKitInit`), and
13
+ * "set the globals on mount" component, and
14
14
  * because those copies had no access to the token manager they published the
15
15
  * RAW `sonor_` key into the client bundle — the exact exposure the mint exists
16
16
  * to prevent. Any layout that puts a credential on `window` goes through here.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Single source of truth for client reporting eligibility and credentials.
3
- * Analytics, fleet, SitemapSync and Engage all resolve through this gate.
3
+ * Analytics, fleet, SitemapSync, chat and popups all resolve through this gate.
4
4
  * Kept separate from transport wrappers so non-analytics modules stay lean.
5
5
  */
6
6
  /** Resolved destination for an analytics send. */
@@ -10,8 +10,7 @@
10
10
  * deployed site viewed before its TLS cert provisions — or in older Safari,
11
11
  * `crypto.randomUUID` is `undefined`, so calling it unguarded throws
12
12
  * "crypto.randomUUID is not a function" DURING RENDER and crashes the whole
13
- * page. (Observed live on ramseydeal.com, 2026-07-21, while its cert was
14
- * pending.)
13
+ * page. (Observed live on a site whose cert was still pending.)
15
14
  *
16
15
  * `uuid()` degrades gracefully and NEVER throws:
17
16
  * 1. crypto.randomUUID() — fast path; modern secure contexts.
@@ -7,4 +7,4 @@
7
7
  * it matches package.json at publish time, and version.test.ts asserts it in
8
8
  * dev, so it can't silently drift.
9
9
  */
10
- export declare const SITE_KIT_VERSION = "7.1.1";
10
+ export declare const SITE_KIT_VERSION = "7.2.0";
@@ -3,8 +3,8 @@
3
3
  *
4
4
  * Single source of truth for measuring how far the layout viewport extends
5
5
  * below the visual viewport and publishing it as `--sk-vv-layout-gap` on
6
- * <html>. Moved into the kit from queencityriverboats.com and
7
- * destinyyachtcharters.com, which each carried a byte-identical copy.
6
+ * <html>. Moved into the kit from two sites that each carried a
7
+ * byte-identical copy.
8
8
  *
9
9
  * On a phone the two viewports can disagree (browser chrome, in-app browsers,
10
10
  * pinch zoom, an on-screen keyboard), and `position: fixed; bottom: …` is
@@ -15,7 +15,7 @@
15
15
  * bottom: calc(24px + env(safe-area-inset-bottom, 0px) + var(--sk-vv-layout-gap, 0px));
16
16
  *
17
17
  * The Echo launcher and chat popup already include it (see
18
- * engage/launcher-placement.ts), so mounting the tracker is all a site needs
18
+ * chat/launcher-placement.ts), so mounting the tracker is all a site needs
19
19
  * for those; the property is also there for the site's own fixed UI.
20
20
  *
21
21
  * Opt-in on purpose. The gap also grows to the keyboard's height while a
@@ -1,6 +1,6 @@
1
1
  'use client';
2
- import { useSignalExperiment, useSignalEvent } from '../chunk-Q3S26EQA.js';
3
- export { SignalBridge, useSignal, useSignalConfig, useSignalEvent, useSignalExperiment, useSignalOutcome } from '../chunk-Q3S26EQA.js';
2
+ import { useSignalExperiment, useSignalEvent } from '../chunk-S54ECQGY.js';
3
+ export { SignalBridge, useSignal, useSignalConfig, useSignalEvent, useSignalExperiment, useSignalOutcome } from '../chunk-S54ECQGY.js';
4
4
  import '../chunk-PKBMQBKP.js';
5
5
  import React, { useEffect } from 'react';
6
6
  import { jsx, Fragment } from 'react/jsx-runtime';
@@ -8,7 +8,7 @@ export interface SignalConfig {
8
8
  version: string;
9
9
  /** Whether Signal is enabled for this project */
10
10
  enabled: boolean;
11
- /** Engage element overrides */
11
+ /** Popup overrides (the key keeps the retired Engage module's name) */
12
12
  engage?: {
13
13
  popups?: Record<string, EngageOverride>;
14
14
  nudges?: Record<string, EngageOverride>;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Site config from Portal (project-info) by API key.
2
+ * Site config from Sonor (project-info) by API key.
3
3
  * Resolves site_url and domain so consumers only need SONOR_API_KEY.
4
4
  */
5
5
  export interface SiteConfig {
@@ -11,7 +11,7 @@ export interface GetSiteConfigOptions {
11
11
  apiUrl?: string;
12
12
  }
13
13
  /**
14
- * Fetch site_url and domain from Portal project-info for the given API key.
14
+ * Fetch site_url and domain from Sonor project-info for the given API key.
15
15
  * Uses in-memory cache (TTL 10 min) keyed by apiKey.
16
16
  * Safe for Edge (middleware) and Node (route handlers).
17
17
  */
@@ -2,7 +2,7 @@
2
2
  * @sonordev/site-kit - Sitemap Generator
3
3
  *
4
4
  * Automatically generates sitemap.xml from Next.js app directory structure.
5
- * Works at build time to discover all pages and sync them to Portal API.
5
+ * Works at build time to discover all pages and sync them to Sonor API.
6
6
  *
7
7
  * @example
8
8
  * ```ts
@@ -36,10 +36,10 @@ export interface SitemapEntry {
36
36
  images?: string[];
37
37
  }
38
38
  export interface SitemapConfig {
39
- /** Base URL for the site (optional when apiKey is set; then resolved from Portal project-info) */
39
+ /** Base URL for the site (optional when apiKey is set; then resolved from Sonor project-info) */
40
40
  baseUrl?: string;
41
41
  /**
42
- * Sub-site host this build belongs to (e.g. `bd-charlotte.com`) — the
42
+ * Sub-site host this build belongs to (e.g. `charlotte.example.com`) — the
43
43
  * multi-site `site` dimension. One Sonor project can host many domains, and
44
44
  * seo_pages is unique on (project_id, site, url), so shared paths like `/`
45
45
  * and `/terms` keep one row PER HOST. Tagging the sync keeps this build's
@@ -95,11 +95,11 @@ export interface SitemapConfig {
95
95
  resolveGenerateStaticParams?: boolean;
96
96
  /** Priority overrides by path pattern */
97
97
  priorities?: Record<string, number>;
98
- /** Portal API URL for syncing (defaults to SONOR_API_URL or https://api.sonor.io) */
98
+ /** Sonor API URL for syncing (defaults to SONOR_API_URL or https://api.sonor.io) */
99
99
  apiUrl?: string;
100
- /** Portal API key for syncing (defaults to SONOR_API_KEY) */
100
+ /** Sonor API key for syncing (defaults to SONOR_API_KEY) */
101
101
  apiKey?: string;
102
- /** Disable auto-sync to Portal API */
102
+ /** Disable auto-sync to Sonor API */
103
103
  disableSync?: boolean;
104
104
  /** When true, await meta optimization before build completes (for build-time llms.txt with managed_llm_schema) */
105
105
  awaitMetaOptimization?: boolean;
@@ -111,7 +111,7 @@ export interface SitemapConfig {
111
111
  * build. It used to default to 120000ms, which only worked because a stale
112
112
  * Data Cache entry answered the request instantly (see shared/fresh-fetch.ts).
113
113
  *
114
- * The write still often won't fit, and no value here makes it fit. Measured against a 191-page site, Portal takes ~27s for
114
+ * The write still often won't fit, and no value here makes it fit. Measured against a 191-page site, Sonor takes ~27s for
115
115
  * llms.txt and ~53s for llms-full.txt, because it generates each through
116
116
  * Signal's AEO skill (an LLM call). ~80s combined, inside a route Next
117
117
  * allows 60s. Any value low enough to protect the route is too low for the
@@ -123,7 +123,7 @@ export interface SitemapConfig {
123
123
  * dropped from the build — the fix is architectural, not numeric: set
124
124
  * `optimizedLLMsTxt: false` here and call `writeLLMsTxtToPublic` from a
125
125
  * postbuild script instead, where nothing imposes a 60s ceiling. Run it
126
- * after `next build` so the sitemap has already synced to Portal, which is
126
+ * after `next build` so the sitemap has already synced to Sonor, which is
127
127
  * what the generation reads.
128
128
  *
129
129
  * Timing out is safe either way: writeLLMsTxtToPublic never persists a
@@ -136,10 +136,10 @@ export interface SitemapConfig {
136
136
  /**
137
137
  * The llms.txt "Agent access" section (writeLLMsTxtToPublic's `mcp`).
138
138
  * Default: on only for site-kit's built-in MCP server; a site with its own
139
- * (upforge.io) is left alone. `false` forces it off, `true` on.
139
+ * is left alone. `false` forces it off, `true` on.
140
140
  */
141
141
  llmsAgentAccess?: boolean;
142
- /** When Portal returns empty services, use this to supply local site data for llms.txt */
142
+ /** When Sonor returns empty services, use this to supply local site data for llms.txt */
143
143
  getLocalData?: () => Promise<import('../llms/types').LLMsDataResponse | null>;
144
144
  /** Pass-through to GET /api/public/llms/txt?publicSummaryOnly=true and local llms fallback */
145
145
  llmsPublicSummaryOnly?: boolean;
@@ -180,7 +180,7 @@ export interface SyncSitemapOptions {
180
180
  site?: string;
181
181
  }
182
182
  /**
183
- * Sync sitemap entries to Portal API
183
+ * Sync sitemap entries to Sonor API
184
184
  * Called automatically by createSitemap at build time
185
185
  */
186
186
  export declare function syncSitemapToPortal(entries: SitemapEntry[], apiUrl: string, apiKey: string, options?: SyncSitemapOptions): Promise<{
@@ -190,7 +190,7 @@ export declare function syncSitemapToPortal(entries: SitemapEntry[], apiUrl: str
190
190
  }>;
191
191
  /**
192
192
  * Create a sitemap generator function for Next.js
193
- * Automatically syncs to Portal API at build time.
193
+ * Automatically syncs to Sonor API at build time.
194
194
  *
195
195
  * @example
196
196
  * ```ts
@@ -203,7 +203,7 @@ export declare function syncSitemapToPortal(entries: SitemapEntry[], apiUrl: str
203
203
  * ```
204
204
  */
205
205
  /**
206
- * Fetches published portfolio items from Portal API and returns them as sitemap paths.
206
+ * Fetches published portfolio items from Sonor API and returns them as sitemap paths.
207
207
  * Use this in createSitemap's additionalPaths to include portfolio routes.
208
208
  *
209
209
  * @example
@@ -1,11 +1,11 @@
1
- export { createSitemap, getPortfolioPaths, syncSitemapToPortal } from '../chunk-HAG4YIZY.js';
1
+ export { createSitemap, getPortfolioPaths, syncSitemapToPortal } from '../chunk-R46IQIGK.js';
2
2
  import '../chunk-Z22QVHT4.js';
3
- import '../chunk-J4D6ZXRW.js';
4
- import '../chunk-GLHQ3LRO.js';
3
+ import '../chunk-QL6XNPSD.js';
4
+ import '../chunk-6U3VLV2C.js';
5
5
  import '../chunk-L5UOHS6E.js';
6
6
  import '../chunk-WMVK77ND.js';
7
7
  import '../chunk-VX5CMNMM.js';
8
- import '../chunk-4Y5FWDPM.js';
8
+ import '../chunk-NZ4RXN3G.js';
9
9
  import '../chunk-MJP63SSS.js';
10
10
  import '../chunk-ZEGVKVD5.js';
11
11
  import '../chunk-YVKRYQRG.js';
@@ -15,8 +15,8 @@
15
15
  * carry it when the site does.
16
16
  *
17
17
  * The copies had already drifted (one treated `''` as the homepage, the others
18
- * didn't; one stripped embedded domains, another only rejected them). Keeping
19
- * one implementation is the CLAUDE.md "consolidate duplicated logic" rule.
18
+ * didn't; one stripped embedded domains, another only rejected them), so
19
+ * there's one implementation now.
20
20
  *
21
21
  * Pure string logic only — NO Node built-ins, NO React — so this file is safe to
22
22
  * import from the browser `SitemapSync` client component AND from the Node CLI.
@@ -100,7 +100,7 @@ export declare function isMalformedSitemapPath(path: string): boolean;
100
100
  * Next gives a prerendered route 60s (`staticPageGenerationTimeout`), then
101
101
  * retries it and fails the build. Sonor generates llms.txt through an LLM call
102
102
  * that takes roughly 27-60s, so the write can't reliably fit, and it runs
103
- * after the Portal sync has already spent part of the budget. Until 2026-09 a
103
+ * after Sonor sync has already spent part of the budget. Until 2026-09 a
104
104
  * one-year Data Cache entry hid this: the call ran live only on a site's first
105
105
  * build, and every later build replayed the stored response (a stale file).
106
106
  * With reads fresh (shared/fresh-fetch.ts), the write gets whatever is left of
@@ -2,8 +2,8 @@
2
2
  * Append `site=<host>` to an API URL or endpoint path. Returns the input
3
3
  * unchanged when the host resolves empty.
4
4
  *
5
- * withSiteParam('/public/articles/posts?page=2', 'bd-charlotte.com')
6
- * → '/public/articles/posts?page=2&site=bd-charlotte.com'
5
+ * withSiteParam('/public/articles/posts?page=2', 'charlotte.example.com')
6
+ * → '/public/articles/posts?page=2&site=charlotte.example.com'
7
7
  */
8
8
  export declare function withSiteParam(url: string, site?: string): string;
9
9
  /**
@@ -23,7 +23,7 @@ export interface ManagedRichTextProps extends Omit<SlotResolveOptions, 'fallback
23
23
  * ```tsx
24
24
  * <div className="prose">
25
25
  * <ManagedRichText id="about-intro" page="/about">
26
- * {`We've built homes in **Cincinnati** since 1998.\n\n- Custom builds\n- Remodels`}
26
+ * {`We've built homes in **Springfield** since 1998.\n\n- Custom builds\n- Remodels`}
27
27
  * </ManagedRichText>
28
28
  * </div>
29
29
  * ```
@@ -22,7 +22,7 @@ export interface ManagedSlotProps extends Omit<SlotResolveOptions, 'fallback'> {
22
22
  * ```tsx
23
23
  * <h1 className="hero-title">
24
24
  * <ManagedSlot id="home-hero-headline" page="/">
25
- * New Homes in Cincinnati & Northern Kentucky
25
+ * New Homes in Springfield and Beyond
26
26
  * </ManagedSlot>
27
27
  * </h1>
28
28
  * ```
@@ -2,9 +2,7 @@
2
2
  * @sonordev/site-kit/website/slots — Managed Slots (3.0 spine, Pillar 1)
3
3
  *
4
4
  * Named, Sonor-managed copy inside developer-owned markup: text, rich text,
5
- * links and lists (the Website CMS; docs/WEBSITE-CMS.md).
6
- * Static-safe, fallback-first, signature-verified.
7
- * See docs/SITE-KIT-3.0-SPEC-SLOTS.md.
5
+ * links and lists. Static-safe, fallback-first, signature-verified.
8
6
  */
9
7
  export { ManagedSlot, default } from './ManagedSlot';
10
8
  export type { ManagedSlotProps } from './ManagedSlot';
@@ -1,6 +1,6 @@
1
1
  import './chunk-PKBMQBKP.js';
2
2
 
3
- // src/engage/socket-loader.ts
3
+ // src/chat/socket-loader.ts
4
4
  async function createSocket(url, opts) {
5
5
  const { io } = await import(
6
6
  /* webpackChunkName: "socket-io" */
@@ -1,6 +1,6 @@
1
- export { BookingWidget } from '../chunk-ZAWANWUS.js';
2
- export { createBooking, createSlotHold, detectTimezone, fetchAvailability, fetchAvailableDates, fetchBookingTypeDetails, fetchBookingTypes, formatDate, formatDuration, formatTime, prepareMeeting, releaseSlotHold } from '../chunk-EFPS56JA.js';
3
- import '../chunk-PXZ7LAOY.js';
4
- import '../chunk-OUNRFXDC.js';
5
- import '../chunk-6OL23QYD.js';
1
+ export { BookingWidget } from '../chunk-GGORNBSC.js';
2
+ export { createBooking, createSlotHold, detectTimezone, fetchAvailability, fetchAvailableDates, fetchBookingTypeDetails, fetchBookingTypes, formatDate, formatDuration, formatTime, prepareMeeting, releaseSlotHold } from '../chunk-BKY2ZNM7.js';
3
+ import '../chunk-D6ZC7XKZ.js';
4
+ import '../chunk-K4ZHAURD.js';
5
+ import '../chunk-F24FNCTK.js';
6
6
  import '../chunk-PKBMQBKP.js';
package/dist/types.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @sonordev/site-kit - Shared types across all modules
3
3
  *
4
- * Site-kit ONLY calls Portal API - never Supabase directly.
4
+ * Site-kit ONLY calls Sonor API - never Supabase directly.
5
5
  * All data access goes through api.sonor.io with API key auth.
6
6
  */
7
7
  export interface BaseEntity {
@@ -14,6 +14,8 @@ export interface ProjectScoped {
14
14
  }
15
15
  export * from './seo/types';
16
16
  export * from './analytics/types';
17
- export * from './engage/types';
17
+ export * from './chat/types';
18
+ export * from './website/popup-types';
19
+ export type { EngageAnalytics, EngageConfig, EngageElement, TargetingRules, TriggerConfig, WidgetConfig, WidgetType } from './engage/types';
18
20
  export * from './forms/types';
19
21
  export * from './articles/types';
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * The site side of a blocks popup: re-checks the blocks, measures the site's
5
5
  * design once when the popup opens, and hands both to PopupBlocks.
6
- * EngageWidget loads this with a dynamic import, so the renderer, the
6
+ * SitePopups loads this with a dynamic import, so the renderer, the
7
7
  * contract and the design measurement download only when a blocks popup is
8
8
  * actually about to show (most page loads have none).
9
9
  */
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Draws a popup from its blocks (heading, formatted text, image, button,
5
5
  * divider) in the site's own design. SINGLE renderer for both places a popup
6
- * appears: on the site (EngageWidget, fed the measured tokens) and in Sonor's
6
+ * appears: on the site (SitePopups, fed the measured tokens) and in Sonor's
7
7
  * builder preview (fed the tokens the site reported). React only, no Next
8
8
  * imports, so the dashboard can import it as-is.
9
9
  *
@@ -11,15 +11,17 @@
11
11
  * `--sk-site-*` variables, set on this popup's root from `tokens` (never on
12
12
  * :root, so nothing leaks into the site's own CSS).
13
13
  *
14
- * The dashboard keeps a byte-identical copy (sonor-frontend
15
- * src/lib/site-kit/website/PopupBlocks.tsx, with contract.ts and color.ts
16
- * beside it) until @sonordev/contracts replaces the mirrors; its drift test
17
- * fails when they differ. Edit here, then copy.
14
+ * The dashboard keeps a byte-identical copy until @sonordev/contracts
15
+ * replaces the mirrors; its drift test fails when they differ. Edit here,
16
+ * then copy.
18
17
  *
19
18
  * Accessibility: a centred popup is a modal dialog (labelled by its heading,
20
19
  * focus moves in and is kept there, Escape and the overlay close it, focus
21
20
  * goes back where it was). A bar is a labelled region, a slide-in a
22
- * non-modal dialog; both close on Escape. Text HTML is re-sanitized on render.
21
+ * non-modal dialog; both close on Escape. The focus and Escape behavior is
22
+ * usePopupDialog (../shared/dialog), so the builder's copy needs that file
23
+ * beside it. Text HTML is re-sanitized on
24
+ * render.
23
25
  */
24
26
  import React from 'react';
25
27
  import { type PopupBlock, type SiteDesignTokens } from './contract';
@@ -0,0 +1,25 @@
1
+ /**
2
+ * @sonordev/site-kit/website/popups - SitePopups: the popups, banners and
3
+ * toasts published for this site (Sonor → Website → Popups & Banners).
4
+ *
5
+ * Each shows where and when Sonor says (pages, devices, trigger, frequency,
6
+ * schedule), drawn from its blocks in the site's own design by PopupBlocks.
7
+ * SiteKitLayout mounts it for you (its `popups` prop); mount it yourself only
8
+ * on a site without SiteKitLayout. A project with nothing published costs one
9
+ * request and draws nothing. The renderer downloads when a popup first opens.
10
+ */
11
+ import React from 'react';
12
+ import { type AnalyticsGateOptions } from '../shared/reporting-gate';
13
+ export interface SitePopupsProps extends AnalyticsGateOptions {
14
+ apiUrl?: string;
15
+ apiKey?: string;
16
+ /** The layer popups, banners and toasts stack on. Default: 9999. */
17
+ zIndex?: number;
18
+ debug?: boolean;
19
+ }
20
+ /**
21
+ * Same gate as analytics (frames, localhost, a key to send with): a popup in
22
+ * a case study's device frame is shown to the agency's visitor, not this
23
+ * site's, and its impressions would count against this site.
24
+ */
25
+ export declare function SitePopups(props: SitePopupsProps): React.JSX.Element | null;
@@ -1,6 +1,6 @@
1
- export { ManagedImage, assignImageToSlot, clearImageSlot, fetchManagedImage, fetchManagedImages, listImageFiles, uploadImage } from '../chunk-542MIHNP.js';
1
+ export { ManagedImage, assignImageToSlot, clearImageSlot, fetchManagedImage, fetchManagedImages, listImageFiles, uploadImage } from '../chunk-JMLK6MH7.js';
2
2
  export { ManagedFavicon, getManagedFaviconUrl } from '../chunk-GW7GSBO7.js';
3
- import '../chunk-PXZ7LAOY.js';
4
- import '../chunk-OUNRFXDC.js';
5
- import '../chunk-6OL23QYD.js';
3
+ import '../chunk-D6ZC7XKZ.js';
4
+ import '../chunk-K4ZHAURD.js';
5
+ import '../chunk-F24FNCTK.js';
6
6
  import '../chunk-PKBMQBKP.js';
@@ -1,13 +1,13 @@
1
1
  'use client';
2
- export { SiteDesignReporter } from '../chunk-ICFRH2ED.js';
3
- export { SITE_DESIGN_PATH, cleanFontStack, colorToHex, getSiteDesignTokens, measureSiteDesign, readDeclaredDesign, sendSiteDesign } from '../chunk-ODADQM6Z.js';
4
- export { DEFAULT_POPUP_TOKENS, PopupBlocks } from '../chunk-JSZN6LDZ.js';
2
+ export { SiteDesignReporter } from '../chunk-5YCEMV2L.js';
3
+ export { SITE_DESIGN_PATH, cleanFontStack, colorToHex, getSiteDesignTokens, measureSiteDesign, readDeclaredDesign, sendSiteDesign } from '../chunk-JJ3DELUL.js';
4
+ export { DEFAULT_POPUP_TOKENS, PopupBlocks } from '../chunk-BF7TZYC3.js';
5
5
  import '../chunk-IHG36STL.js';
6
6
  import '../chunk-YC7ELZS3.js';
7
7
  import '../chunk-S22FSH7C.js';
8
8
  import '../chunk-43OCZ3JA.js';
9
9
  import '../chunk-EKBEOXTH.js';
10
- import '../chunk-PXZ7LAOY.js';
11
- import '../chunk-OUNRFXDC.js';
12
- import '../chunk-6OL23QYD.js';
10
+ import '../chunk-D6ZC7XKZ.js';
11
+ import '../chunk-K4ZHAURD.js';
12
+ import '../chunk-F24FNCTK.js';
13
13
  import '../chunk-PKBMQBKP.js';
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @sonordev/site-kit/website/popups - the rules SitePopups applies to the
3
+ * popups, banners and toasts published for a site, as pure functions (the
4
+ * package's tests have no DOM).
5
+ */
6
+ import type { SitePopup } from './popup-types';
7
+ import type { PopupPlacement } from './PopupBlocks';
8
+ /** Exact path, or a prefix ending in `*`. The grammar Sonor stores page patterns in. */
9
+ export declare function matchPath(pathname: string, pattern: string): boolean;
10
+ export type DeviceType = 'desktop' | 'mobile' | 'tablet';
11
+ export declare function deviceFromUserAgent(ua: string): DeviceType;
12
+ /**
13
+ * The storage key that remembers a visitor saw (closed or clicked) a popup.
14
+ * The `_engage_` prefix predates the Website module; renaming it would show
15
+ * every "once" popup to visitors who already closed it.
16
+ */
17
+ export declare function seenKey(popupId: string): string;
18
+ interface SeenStore {
19
+ local: Pick<Storage, 'getItem'> | null;
20
+ session: Pick<Storage, 'getItem'> | null;
21
+ }
22
+ /** Whether a popup's targeting and frequency cap allow it on this page, for this visitor. */
23
+ export declare function isEligible(popup: SitePopup, pathname: string, device: DeviceType, store: SeenStore, now?: number): boolean;
24
+ /**
25
+ * What a popup draws as: centred over a dimmed page, a bar along an edge, or
26
+ * a slide-in (a toast) in a corner. Its `layout` says what it actually is;
27
+ * `type` describes it for older kits. Undefined for a popup without blocks:
28
+ * that's Sonor's Engage Studio `design_json`, which this kit doesn't draw.
29
+ * Single source of truth for which popups SitePopups draws, the
30
+ * one-popup-at-a-time rule and the form wait.
31
+ */
32
+ export declare function popupPlacement(popup: SitePopup): PopupPlacement | undefined;
33
+ /**
34
+ * Whether a popup waits until the visitor isn't mid-form before it opens on
35
+ * its own (shared/mid-form). Popups and toasts do. Banners don't: they
36
+ * neither take focus nor hide the page.
37
+ */
38
+ export declare function waitsForForms(popup: SitePopup): boolean;
39
+ /**
40
+ * The active list after `id` asks to show. A popup (the kind centred over a
41
+ * dimmed page) waits while another is open, so two never stack; banners and
42
+ * toasts show alongside. Popups arrive from Sonor highest priority first, so
43
+ * the first popup to trigger is the one that wins a tie.
44
+ */
45
+ export declare function activatePopup(active: string[], id: string, popups: SitePopup[]): string[];
46
+ export {};