@sonordev/site-kit 5.8.3 → 6.0.1
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 +11 -11
- package/agent-manifest.json +17 -11
- package/dist/{AnalyticsProvider-DPXR6FSV.js → AnalyticsProvider-4RLYTVWO.js} +10 -10
- package/dist/{AnalyticsProvider-DPXR6FSV.js.map → AnalyticsProvider-4RLYTVWO.js.map} +1 -1
- package/dist/{AnalyticsProvider-IGOD64MY.mjs → AnalyticsProvider-YU6QANW5.mjs} +6 -6
- package/dist/{AnalyticsProvider-IGOD64MY.mjs.map → AnalyticsProvider-YU6QANW5.mjs.map} +1 -1
- package/dist/ArticleFaqSection-3KZ24MFS.js +13 -0
- package/dist/ArticleFaqSection-3KZ24MFS.js.map +1 -0
- package/dist/ArticleFaqSection-XZPXJVH4.mjs +11 -0
- package/dist/ArticleFaqSection-XZPXJVH4.mjs.map +1 -0
- package/dist/{BlogViewTracker-Q7Y4MN4B.mjs → ArticleViewTracker-LI44SA4T.mjs} +13 -13
- package/dist/ArticleViewTracker-LI44SA4T.mjs.map +1 -0
- package/dist/{BlogViewTracker-S3CSRBIZ.js → ArticleViewTracker-OQB2VT73.js} +16 -16
- package/dist/ArticleViewTracker-OQB2VT73.js.map +1 -0
- package/dist/ChatWidget-56SW5ITH.mjs +15 -0
- package/dist/{ChatWidget-G3KOUDX5.mjs.map → ChatWidget-56SW5ITH.mjs.map} +1 -1
- package/dist/ChatWidget-HR3OC3WA.js +24 -0
- package/dist/{ChatWidget-76R7NOWD.js.map → ChatWidget-HR3OC3WA.js.map} +1 -1
- package/dist/EngageWidget-HXGI3ZKG.js +21 -0
- package/dist/{EngageWidget-HD4F2ZVE.js.map → EngageWidget-HXGI3ZKG.js.map} +1 -1
- package/dist/EngageWidget-L4X35N2B.mjs +12 -0
- package/dist/{EngageWidget-UJ47PQFG.mjs.map → EngageWidget-L4X35N2B.mjs.map} +1 -1
- package/dist/{FileField-WNMEA3PK.mjs → FileField-GSTLU42O.mjs} +5 -5
- package/dist/{FileField-WNMEA3PK.mjs.map → FileField-GSTLU42O.mjs.map} +1 -1
- package/dist/{FileField-FV6WSZMX.js → FileField-N2P6E2PN.js} +6 -6
- package/dist/{FileField-FV6WSZMX.js.map → FileField-N2P6E2PN.js.map} +1 -1
- package/dist/{FormSpotlight-2VRQXEFI.js → FormSpotlight-QLXOS5LN.js} +9 -9
- package/dist/{FormSpotlight-2VRQXEFI.js.map → FormSpotlight-QLXOS5LN.js.map} +1 -1
- package/dist/{FormSpotlight-NGWEPGI4.mjs → FormSpotlight-UFATQTN3.mjs} +3 -3
- package/dist/{FormSpotlight-NGWEPGI4.mjs.map → FormSpotlight-UFATQTN3.mjs.map} +1 -1
- package/dist/{FormStage-Q3KQVFVW.js → FormStage-4HYDMCYU.js} +9 -9
- package/dist/{FormStage-Q3KQVFVW.js.map → FormStage-4HYDMCYU.js.map} +1 -1
- package/dist/{FormStage-7L4BBOLC.mjs → FormStage-SYOKD5TJ.mjs} +3 -3
- package/dist/{FormStage-7L4BBOLC.mjs.map → FormStage-SYOKD5TJ.mjs.map} +1 -1
- package/dist/ManagedForm-3TDSIRCM.mjs +16 -0
- package/dist/{ManagedForm-Z7QE4KYI.mjs.map → ManagedForm-3TDSIRCM.mjs.map} +1 -1
- package/dist/ManagedForm-TUSGW5EH.js +25 -0
- package/dist/{ManagedForm-4ZGU4R3G.js.map → ManagedForm-TUSGW5EH.js.map} +1 -1
- package/dist/{ManagedNewsletterForm-4TVO2VL4.mjs → ManagedNewsletterForm-CNGCBA2N.mjs} +11 -11
- package/dist/ManagedNewsletterForm-CNGCBA2N.mjs.map +1 -0
- package/dist/{ManagedNewsletterForm-22EPZB7Z.js → ManagedNewsletterForm-XJEPVJRM.js} +13 -13
- package/dist/ManagedNewsletterForm-XJEPVJRM.js.map +1 -0
- package/dist/{SignalCore-57OK3DHA.mjs → SignalCore-ARRVP6F7.mjs} +5 -5
- package/dist/{SignalCore-57OK3DHA.mjs.map → SignalCore-ARRVP6F7.mjs.map} +1 -1
- package/dist/{SignalCore-2N7UZGF3.js → SignalCore-AXK6RCR4.js} +11 -11
- package/dist/{SignalCore-2N7UZGF3.js.map → SignalCore-AXK6RCR4.js.map} +1 -1
- package/dist/SitemapSync-42VKJUOU.mjs +9 -0
- package/dist/{SitemapSync-WIUEYOBS.mjs.map → SitemapSync-42VKJUOU.mjs.map} +1 -1
- package/dist/SitemapSync-GAGREAX6.js +18 -0
- package/dist/{SitemapSync-GF4OKN4Z.js.map → SitemapSync-GAGREAX6.js.map} +1 -1
- package/dist/analytics/index.js +9 -9
- package/dist/analytics/index.mjs +4 -4
- package/dist/{blog-styles-7AKRUMV7.mjs → article-styles-DACUAOVT.mjs} +124 -124
- package/dist/article-styles-DACUAOVT.mjs.map +1 -0
- package/dist/{blog-styles-6EY3BS5Y.js → article-styles-JHHTNHOK.js} +125 -125
- package/dist/article-styles-JHHTNHOK.js.map +1 -0
- package/dist/article-tables-EWXG4LNP.js +17 -0
- package/dist/article-tables-EWXG4LNP.js.map +1 -0
- package/dist/article-tables-OGE52LNT.mjs +4 -0
- package/dist/article-tables-OGE52LNT.mjs.map +1 -0
- package/dist/{blog/BlogPost.d.ts → articles/Article.d.ts} +18 -16
- package/dist/articles/Article.d.ts.map +1 -0
- package/dist/{blog/BlogFAQ.d.ts → articles/ArticleFAQ.d.ts} +6 -6
- package/dist/articles/ArticleFAQ.d.ts.map +1 -0
- package/dist/articles/ArticleFaqSection.d.ts +3 -0
- package/dist/articles/ArticleFaqSection.d.ts.map +1 -0
- package/dist/{blog/BlogList.d.ts → articles/ArticleList.d.ts} +16 -16
- package/dist/articles/ArticleList.d.ts.map +1 -0
- package/dist/{blog/BlogViewTracker.d.ts → articles/ArticleViewTracker.d.ts} +4 -4
- package/dist/articles/ArticleViewTracker.d.ts.map +1 -0
- package/dist/{blog → articles}/AuthorCard.d.ts +3 -3
- package/dist/articles/AuthorCard.d.ts.map +1 -0
- package/dist/{blog → articles}/AuthorPage.d.ts +1 -1
- package/dist/articles/AuthorPage.d.ts.map +1 -0
- package/dist/{blog → articles}/ClusterLandingPage.d.ts +6 -6
- package/dist/articles/ClusterLandingPage.d.ts.map +1 -0
- package/dist/{blog → articles}/ClusterNavigation.d.ts +5 -5
- package/dist/articles/ClusterNavigation.d.ts.map +1 -0
- package/dist/{blog → articles}/ManagedNewsletterForm.d.ts +1 -1
- package/dist/articles/ManagedNewsletterForm.d.ts.map +1 -0
- package/dist/{blog → articles}/NewsletterShell.d.ts +1 -1
- package/dist/articles/NewsletterShell.d.ts.map +1 -0
- package/dist/{blog → articles}/NewsletterWidget.d.ts +4 -4
- package/dist/articles/NewsletterWidget.d.ts.map +1 -0
- package/dist/{blog/BlogLayout.d.ts → articles/PublicationLayout.d.ts} +18 -18
- package/dist/articles/PublicationLayout.d.ts.map +1 -0
- package/dist/{blog/BlogSidebar.d.ts → articles/PublicationSidebar.d.ts} +8 -8
- package/dist/articles/PublicationSidebar.d.ts.map +1 -0
- package/dist/{blog → articles}/RelatedPosts.d.ts +6 -6
- package/dist/articles/RelatedPosts.d.ts.map +1 -0
- package/dist/{blog → articles}/ServiceCallout.d.ts +4 -4
- package/dist/articles/ServiceCallout.d.ts.map +1 -0
- package/dist/{blog → articles}/TableOfContents.d.ts +1 -1
- package/dist/articles/TableOfContents.d.ts.map +1 -0
- package/dist/{blog/blog-styles.d.ts → articles/article-styles.d.ts} +5 -5
- package/dist/articles/article-styles.d.ts.map +1 -0
- package/dist/{blog/blog-tables.d.ts → articles/article-tables.d.ts} +4 -4
- package/dist/articles/article-tables.d.ts.map +1 -0
- package/dist/articles/artwork.d.ts +14 -0
- package/dist/articles/artwork.d.ts.map +1 -0
- package/dist/{blog → articles}/author-schema.d.ts +6 -5
- package/dist/articles/author-schema.d.ts.map +1 -0
- package/dist/{blog → articles}/author-social.d.ts +2 -2
- package/dist/articles/author-social.d.ts.map +1 -0
- package/dist/{blog → articles}/excerpt.d.ts +2 -2
- package/dist/articles/excerpt.d.ts.map +1 -0
- package/dist/{blog → articles}/index.d.ts +26 -31
- package/dist/articles/index.d.ts.map +1 -0
- package/dist/{blog → articles}/index.js +39 -73
- package/dist/articles/index.js.map +1 -0
- package/dist/{blog → articles}/index.mjs +16 -17
- package/dist/articles/index.mjs.map +1 -0
- package/dist/articles/news-sitemap.d.ts +47 -0
- package/dist/articles/news-sitemap.d.ts.map +1 -0
- package/dist/{blog/processBlogHtml.d.ts → articles/processArticleHtml.d.ts} +4 -4
- package/dist/articles/processArticleHtml.d.ts.map +1 -0
- package/dist/articles/public-reads.d.ts +27 -0
- package/dist/articles/public-reads.d.ts.map +1 -0
- package/dist/{blog → articles}/reading-time.d.ts +2 -2
- package/dist/articles/reading-time.d.ts.map +1 -0
- package/dist/{blog → articles}/routes.d.ts +16 -12
- package/dist/articles/routes.d.ts.map +1 -0
- package/dist/{blog → articles}/server-core.d.ts +94 -81
- package/dist/articles/server-core.d.ts.map +1 -0
- package/dist/articles/server-ui.d.ts +29 -0
- package/dist/articles/server-ui.d.ts.map +1 -0
- package/dist/{chunk-W2U5SLMY.js → articles/server-ui.js} +378 -499
- package/dist/articles/server-ui.js.map +1 -0
- package/dist/{chunk-MWKI6ZIS.mjs → articles/server-ui.mjs} +328 -474
- package/dist/articles/server-ui.mjs.map +1 -0
- package/dist/{blog → articles}/server.d.ts +94 -81
- package/dist/articles/server.d.ts.map +1 -0
- package/dist/articles/server.js +236 -0
- package/dist/articles/server.mjs +11 -0
- package/dist/{blog → articles}/types.d.ts +34 -34
- package/dist/articles/types.d.ts.map +1 -0
- package/dist/articles/widget-styles.d.ts +9 -0
- package/dist/articles/widget-styles.d.ts.map +1 -0
- package/dist/brand/extract-brand-profile.d.ts +1 -1
- package/dist/{chunk-AJBOEV4I.mjs → chunk-3T2CVHFO.mjs} +3 -3
- package/dist/chunk-3T2CVHFO.mjs.map +1 -0
- package/dist/{chunk-I3ND4XYW.js → chunk-4BEGKFMN.js} +8 -8
- package/dist/{chunk-I3ND4XYW.js.map → chunk-4BEGKFMN.js.map} +1 -1
- package/dist/{chunk-YFX3Q56O.mjs → chunk-4KAMU5HD.mjs} +3 -3
- package/dist/chunk-4KAMU5HD.mjs.map +1 -0
- package/dist/{chunk-CNTDV7HM.js → chunk-4NBJDP6Y.js} +4 -4
- package/dist/{chunk-CNTDV7HM.js.map → chunk-4NBJDP6Y.js.map} +1 -1
- package/dist/{chunk-PIEHBSCN.js → chunk-4VCR6TXK.js} +9 -9
- package/dist/{chunk-PIEHBSCN.js.map → chunk-4VCR6TXK.js.map} +1 -1
- package/dist/{chunk-ZPLN537Q.mjs → chunk-4WCA2HM6.mjs} +2 -2
- package/dist/chunk-4WCA2HM6.mjs.map +1 -0
- package/dist/{chunk-I7HOMMIK.js → chunk-5ABTBPPK.js} +15 -15
- package/dist/{chunk-I7HOMMIK.js.map → chunk-5ABTBPPK.js.map} +1 -1
- package/dist/{chunk-GHECYDSZ.mjs → chunk-5F2FIM5A.mjs} +16 -15
- package/dist/chunk-5F2FIM5A.mjs.map +1 -0
- package/dist/{chunk-Y5QZPUL3.mjs → chunk-5YVQWLSQ.mjs} +5 -5
- package/dist/chunk-5YVQWLSQ.mjs.map +1 -0
- package/dist/chunk-6DCAMW62.mjs +55 -0
- package/dist/chunk-6DCAMW62.mjs.map +1 -0
- package/dist/{chunk-ROSYCNXG.mjs → chunk-6URNNS3V.mjs} +4 -4
- package/dist/{chunk-ROSYCNXG.mjs.map → chunk-6URNNS3V.mjs.map} +1 -1
- package/dist/{chunk-PI3FHABB.js → chunk-6YEPFH3Q.js} +10 -10
- package/dist/{chunk-PI3FHABB.js.map → chunk-6YEPFH3Q.js.map} +1 -1
- package/dist/{chunk-NBT4L2D7.js → chunk-6ZOMIPU5.js} +8 -8
- package/dist/{chunk-NBT4L2D7.js.map → chunk-6ZOMIPU5.js.map} +1 -1
- package/dist/chunk-7MAHP735.mjs +6 -0
- package/dist/{chunk-5FETEH3Y.mjs.map → chunk-7MAHP735.mjs.map} +1 -1
- package/dist/{chunk-Q2NBD54V.js → chunk-7THQ4UW3.js} +2 -2
- package/dist/chunk-7THQ4UW3.js.map +1 -0
- package/dist/{chunk-CY2RFEW6.js → chunk-AQMQOH7V.js} +3 -3
- package/dist/{chunk-CY2RFEW6.js.map → chunk-AQMQOH7V.js.map} +1 -1
- package/dist/{chunk-4TLFZ6NR.mjs → chunk-AS2HUIDW.mjs} +3 -3
- package/dist/chunk-AS2HUIDW.mjs.map +1 -0
- package/dist/{chunk-YN7QHLWF.js → chunk-BBBJHYPH.js} +5 -5
- package/dist/chunk-BBBJHYPH.js.map +1 -0
- package/dist/{chunk-3OO5EDKD.mjs → chunk-BIU234TJ.mjs} +9 -9
- package/dist/{chunk-3OO5EDKD.mjs.map → chunk-BIU234TJ.mjs.map} +1 -1
- package/dist/{chunk-ZVI7MBVF.mjs → chunk-BJ4T65OK.mjs} +14 -10
- package/dist/chunk-BJ4T65OK.mjs.map +1 -0
- package/dist/{chunk-HBHS5VRN.mjs → chunk-BMH2D2EP.mjs} +3 -3
- package/dist/{chunk-HBHS5VRN.mjs.map → chunk-BMH2D2EP.mjs.map} +1 -1
- package/dist/{chunk-QQQAW6WY.js → chunk-BWSYPQ5E.js} +6 -6
- package/dist/{chunk-QQQAW6WY.js.map → chunk-BWSYPQ5E.js.map} +1 -1
- package/dist/{chunk-4LYW6PMU.mjs → chunk-C2CTLLIO.mjs} +3 -3
- package/dist/chunk-C2CTLLIO.mjs.map +1 -0
- package/dist/{chunk-O237KKCX.mjs → chunk-C5VITBN7.mjs} +5 -5
- package/dist/chunk-C5VITBN7.mjs.map +1 -0
- package/dist/{chunk-75A4KY4X.mjs → chunk-CFRJ2MK5.mjs} +2 -2
- package/dist/chunk-CFRJ2MK5.mjs.map +1 -0
- package/dist/{chunk-G2WC3CXW.js → chunk-CLO3K7PF.js} +2 -2
- package/dist/chunk-CLO3K7PF.js.map +1 -0
- package/dist/{chunk-AK6JZ3OE.mjs → chunk-EDLNMGQC.mjs} +3 -3
- package/dist/{chunk-DO6ATNLN.js.map → chunk-EDLNMGQC.mjs.map} +1 -1
- package/dist/{chunk-HX6ZG3PP.js → chunk-EMHSHAVW.js} +3 -3
- package/dist/chunk-EMHSHAVW.js.map +1 -0
- package/dist/chunk-F3EAAAZ3.js +8 -0
- package/dist/{chunk-7R6H3GQ4.js.map → chunk-F3EAAAZ3.js.map} +1 -1
- package/dist/{chunk-MYMZRHTC.js → chunk-FKFVN3GT.js} +8 -8
- package/dist/{chunk-MYMZRHTC.js.map → chunk-FKFVN3GT.js.map} +1 -1
- package/dist/{chunk-7TC3GRXQ.js → chunk-G3L26XQ7.js} +27 -23
- package/dist/chunk-G3L26XQ7.js.map +1 -0
- package/dist/{chunk-VVBMWV4O.js → chunk-GCZHKHEH.js} +7 -7
- package/dist/{chunk-VVBMWV4O.js.map → chunk-GCZHKHEH.js.map} +1 -1
- package/dist/{chunk-LGOQ65JQ.mjs → chunk-GJCQVVO3.mjs} +7 -7
- package/dist/{chunk-LGOQ65JQ.mjs.map → chunk-GJCQVVO3.mjs.map} +1 -1
- package/dist/{chunk-R5IPDAMM.mjs → chunk-GKPVGVHY.mjs} +3 -3
- package/dist/{chunk-R5IPDAMM.mjs.map → chunk-GKPVGVHY.mjs.map} +1 -1
- package/dist/{chunk-XZO5I4RS.mjs → chunk-HIZJD7TU.mjs} +3 -3
- package/dist/{chunk-XZO5I4RS.mjs.map → chunk-HIZJD7TU.mjs.map} +1 -1
- package/dist/chunk-HXHRS3PX.mjs +349 -0
- package/dist/chunk-HXHRS3PX.mjs.map +1 -0
- package/dist/{chunk-XBX2K3GA.js → chunk-IBJOGXQI.js} +4 -4
- package/dist/{chunk-XBX2K3GA.js.map → chunk-IBJOGXQI.js.map} +1 -1
- package/dist/{chunk-F2KW4OJF.mjs → chunk-IDOHDP7D.mjs} +4 -4
- package/dist/{chunk-F2KW4OJF.mjs.map → chunk-IDOHDP7D.mjs.map} +1 -1
- package/dist/{chunk-R7GHP3FY.js → chunk-JONWE26J.js} +3 -3
- package/dist/chunk-JONWE26J.js.map +1 -0
- package/dist/{chunk-PQYQHZWV.mjs → chunk-JSXLTZUP.mjs} +6 -6
- package/dist/{chunk-PQYQHZWV.mjs.map → chunk-JSXLTZUP.mjs.map} +1 -1
- package/dist/{chunk-K4TCEAUX.js → chunk-KR7ATPAN.js} +5 -5
- package/dist/chunk-KR7ATPAN.js.map +1 -0
- package/dist/{chunk-UQY5KC64.mjs → chunk-KUHMHKG5.mjs} +4 -4
- package/dist/{chunk-UQY5KC64.mjs.map → chunk-KUHMHKG5.mjs.map} +1 -1
- package/dist/{chunk-JLVCWC6A.mjs → chunk-KZVSB5WE.mjs} +2 -2
- package/dist/chunk-KZVSB5WE.mjs.map +1 -0
- package/dist/{chunk-NCDF2RK4.mjs → chunk-L63DFM4R.mjs} +3 -3
- package/dist/{chunk-NCDF2RK4.mjs.map → chunk-L63DFM4R.mjs.map} +1 -1
- package/dist/{chunk-25F2EXOC.mjs → chunk-LCYODFNY.mjs} +3 -3
- package/dist/{chunk-25F2EXOC.mjs.map → chunk-LCYODFNY.mjs.map} +1 -1
- package/dist/{chunk-RFAAY3BW.mjs → chunk-LFASEDBO.mjs} +3 -3
- package/dist/{chunk-RFAAY3BW.mjs.map → chunk-LFASEDBO.mjs.map} +1 -1
- package/dist/chunk-LWCAZDY2.js +355 -0
- package/dist/chunk-LWCAZDY2.js.map +1 -0
- package/dist/{chunk-7VZYP4K5.js → chunk-LZPICBND.js} +15 -15
- package/dist/{chunk-7VZYP4K5.js.map → chunk-LZPICBND.js.map} +1 -1
- package/dist/{chunk-LMEUYRRR.js → chunk-NAA5J2JM.js} +233 -120
- package/dist/chunk-NAA5J2JM.js.map +1 -0
- package/dist/{chunk-OE7CTIOU.mjs → chunk-NE6QGHFT.mjs} +4 -4
- package/dist/{chunk-OE7CTIOU.mjs.map → chunk-NE6QGHFT.mjs.map} +1 -1
- package/dist/{chunk-UEUWC3PH.mjs → chunk-NNQG25M2.mjs} +3 -3
- package/dist/{chunk-UEUWC3PH.mjs.map → chunk-NNQG25M2.mjs.map} +1 -1
- package/dist/{chunk-S2Y7LVQ2.js → chunk-NVOYCK2S.js} +14 -14
- package/dist/{chunk-S2Y7LVQ2.js.map → chunk-NVOYCK2S.js.map} +1 -1
- package/dist/{chunk-FD72QL42.mjs → chunk-NVWUXCUQ.mjs} +3 -3
- package/dist/{chunk-FD72QL42.mjs.map → chunk-NVWUXCUQ.mjs.map} +1 -1
- package/dist/{chunk-4NVMAYMQ.mjs → chunk-NYNL6UQV.mjs} +4 -4
- package/dist/{chunk-4NVMAYMQ.mjs.map → chunk-NYNL6UQV.mjs.map} +1 -1
- package/dist/{chunk-GQF6QAQS.js → chunk-OGNX6JT4.js} +5 -5
- package/dist/chunk-OGNX6JT4.js.map +1 -0
- package/dist/{chunk-FVW6FT6L.js → chunk-OSU4QA5M.js} +8 -8
- package/dist/{chunk-FVW6FT6L.js.map → chunk-OSU4QA5M.js.map} +1 -1
- package/dist/{chunk-2TS4ALOA.js → chunk-P2HOVWJW.js} +14 -14
- package/dist/{chunk-2TS4ALOA.js.map → chunk-P2HOVWJW.js.map} +1 -1
- package/dist/{chunk-5HFD36AN.js → chunk-PKZMNDZJ.js} +5 -5
- package/dist/{chunk-5HFD36AN.js.map → chunk-PKZMNDZJ.js.map} +1 -1
- package/dist/{chunk-DO6ATNLN.js → chunk-PRAHDLKT.js} +5 -5
- package/dist/chunk-PRAHDLKT.js.map +1 -0
- package/dist/{chunk-IIHIRHSW.js → chunk-QD4BNYMM.js} +18 -18
- package/dist/{chunk-IIHIRHSW.js.map → chunk-QD4BNYMM.js.map} +1 -1
- package/dist/{chunk-HEOLGDUX.mjs → chunk-QJ3SMLND.mjs} +4 -4
- package/dist/{chunk-HEOLGDUX.mjs.map → chunk-QJ3SMLND.mjs.map} +1 -1
- package/dist/{chunk-QOOLMSBY.mjs → chunk-QP56JXMH.mjs} +3 -3
- package/dist/{chunk-QOOLMSBY.mjs.map → chunk-QP56JXMH.mjs.map} +1 -1
- package/dist/{chunk-MQS6AF5K.mjs → chunk-QXPGIOU7.mjs} +3 -3
- package/dist/{chunk-MQS6AF5K.mjs.map → chunk-QXPGIOU7.mjs.map} +1 -1
- package/dist/{chunk-TR3F3CLV.js → chunk-R6UE6MC5.js} +10 -10
- package/dist/{chunk-TR3F3CLV.js.map → chunk-R6UE6MC5.js.map} +1 -1
- package/dist/{chunk-OEW2LFOV.js → chunk-RLUNEEGM.js} +4 -4
- package/dist/{chunk-OEW2LFOV.js.map → chunk-RLUNEEGM.js.map} +1 -1
- package/dist/{chunk-SFC3OWSE.mjs → chunk-RX4TVHSN.mjs} +4 -4
- package/dist/{chunk-SFC3OWSE.mjs.map → chunk-RX4TVHSN.mjs.map} +1 -1
- package/dist/{chunk-YQTE32QK.js → chunk-SG7CWD2R.js} +17 -16
- package/dist/chunk-SG7CWD2R.js.map +1 -0
- package/dist/{chunk-4C5CZJIN.mjs → chunk-SU42KCQD.mjs} +4 -4
- package/dist/{chunk-4C5CZJIN.mjs.map → chunk-SU42KCQD.mjs.map} +1 -1
- package/dist/{chunk-XEB77DQS.js → chunk-TBXWJJGT.js} +3 -3
- package/dist/chunk-TBXWJJGT.js.map +1 -0
- package/dist/{chunk-CZEIHFLW.js → chunk-TC3JSQUS.js} +4 -4
- package/dist/{chunk-CZEIHFLW.js.map → chunk-TC3JSQUS.js.map} +1 -1
- package/dist/{chunk-LB44BNJ2.js → chunk-TST2IKYO.js} +14 -14
- package/dist/{chunk-LB44BNJ2.js.map → chunk-TST2IKYO.js.map} +1 -1
- package/dist/{chunk-POJZA67T.mjs → chunk-U6F6AN23.mjs} +4 -4
- package/dist/{chunk-POJZA67T.mjs.map → chunk-U6F6AN23.mjs.map} +1 -1
- package/dist/{chunk-FTB5LAD3.js → chunk-UCBBZXJI.js} +4 -4
- package/dist/{chunk-FTB5LAD3.js.map → chunk-UCBBZXJI.js.map} +1 -1
- package/dist/{chunk-U2V542EO.mjs → chunk-UHYRVALN.mjs} +2 -2
- package/dist/{chunk-U2V542EO.mjs.map → chunk-UHYRVALN.mjs.map} +1 -1
- package/dist/{chunk-F3KA6V2Y.js → chunk-UILVPI2R.js} +3 -3
- package/dist/{chunk-F3KA6V2Y.js.map → chunk-UILVPI2R.js.map} +1 -1
- package/dist/{chunk-UHM3CCCC.js → chunk-ULSFOC3J.js} +12 -12
- package/dist/{chunk-UHM3CCCC.js.map → chunk-ULSFOC3J.js.map} +1 -1
- package/dist/{chunk-4L7OHRWB.mjs → chunk-UO6KTHBQ.mjs} +4 -4
- package/dist/{chunk-4L7OHRWB.mjs.map → chunk-UO6KTHBQ.mjs.map} +1 -1
- package/dist/{chunk-H5NBFNND.js → chunk-UZKXOZHR.js} +2 -2
- package/dist/chunk-UZKXOZHR.js.map +1 -0
- package/dist/{chunk-QXMWNIKL.mjs → chunk-WLCPBZOS.mjs} +3 -3
- package/dist/{chunk-QXMWNIKL.mjs.map → chunk-WLCPBZOS.mjs.map} +1 -1
- package/dist/{chunk-3EY5E35M.mjs → chunk-X3MY4PL7.mjs} +210 -107
- package/dist/chunk-X3MY4PL7.mjs.map +1 -0
- package/dist/{chunk-PIPERXI7.mjs → chunk-XLFTZV34.mjs} +3 -3
- package/dist/{chunk-PIPERXI7.mjs.map → chunk-XLFTZV34.mjs.map} +1 -1
- package/dist/{chunk-6CCS2EGF.js → chunk-XWKY46NU.js} +13 -13
- package/dist/{chunk-6CCS2EGF.js.map → chunk-XWKY46NU.js.map} +1 -1
- package/dist/{chunk-SEP5D4MI.js → chunk-Y2CP5J6Q.js} +2 -2
- package/dist/{chunk-SEP5D4MI.js.map → chunk-Y2CP5J6Q.js.map} +1 -1
- package/dist/{chunk-KV7XXLJV.mjs → chunk-YPGUV6BT.mjs} +3 -3
- package/dist/{chunk-KV7XXLJV.mjs.map → chunk-YPGUV6BT.mjs.map} +1 -1
- package/dist/chunk-YRCR7WY3.js +65 -0
- package/dist/chunk-YRCR7WY3.js.map +1 -0
- package/dist/{chunk-WINDP776.mjs → chunk-YTJKVWHY.mjs} +5 -5
- package/dist/{chunk-WINDP776.mjs.map → chunk-YTJKVWHY.mjs.map} +1 -1
- package/dist/chunk-ZL35JCDA.mjs +61 -0
- package/dist/chunk-ZL35JCDA.mjs.map +1 -0
- package/dist/chunk-ZR43XFUM.js +60 -0
- package/dist/chunk-ZR43XFUM.js.map +1 -0
- package/dist/{chunk-NMM27UOF.js → chunk-ZRWIMNQF.js} +3 -3
- package/dist/{chunk-NMM27UOF.js.map → chunk-ZRWIMNQF.js.map} +1 -1
- package/dist/{chunk-NR7YZQRR.js → chunk-ZYJYBE5G.js} +4 -4
- package/dist/{chunk-NR7YZQRR.js.map → chunk-ZYJYBE5G.js.map} +1 -1
- package/dist/cli/commands/setup.d.ts +2 -2
- package/dist/cli/commands/sync.d.ts +2 -2
- package/dist/cli/commands/sync.d.ts.map +1 -1
- package/dist/cli/index.js +76 -76
- package/dist/cli/index.mjs +29 -29
- package/dist/client/index.js +5 -5
- package/dist/client/index.mjs +4 -4
- package/dist/commerce/index.js +57 -57
- package/dist/commerce/index.mjs +5 -5
- package/dist/discover-LPN55L5B.js +21 -0
- package/dist/{discover-NGEPXZOD.js.map → discover-LPN55L5B.js.map} +1 -1
- package/dist/discover-QGA6QFSR.mjs +4 -0
- package/dist/{discover-CYXYKHZ2.mjs.map → discover-QGA6QFSR.mjs.map} +1 -1
- package/dist/engage/index.js +13 -13
- package/dist/engage/index.mjs +7 -7
- package/dist/fleet/contract.d.ts +1 -1
- package/dist/fleet/contract.js +12 -12
- package/dist/fleet/contract.mjs +1 -1
- package/dist/fleet/index.js +20 -20
- package/dist/fleet/index.mjs +5 -5
- package/dist/forms/index.js +16 -16
- package/dist/forms/index.mjs +9 -9
- package/dist/forms/server.js +10 -10
- package/dist/forms/server.mjs +8 -8
- package/dist/forms/static.js +7 -7
- package/dist/forms/static.mjs +6 -6
- package/dist/images/index.js +11 -11
- package/dist/images/index.mjs +4 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +70 -70
- package/dist/index.mjs +12 -12
- package/dist/layout/client.js +10 -10
- package/dist/layout/client.mjs +9 -9
- package/dist/layout/index.js +12 -12
- package/dist/layout/index.mjs +10 -10
- package/dist/llms/SpeakableSchema.d.ts +1 -1
- package/dist/llms/SpeakableSchema.d.ts.map +1 -1
- package/dist/llms/client.js +15 -15
- package/dist/llms/client.mjs +1 -1
- package/dist/llms/generateLLMsTxt.d.ts.map +1 -1
- package/dist/llms/index.js +32 -31
- package/dist/llms/index.js.map +1 -1
- package/dist/llms/index.mjs +8 -7
- package/dist/llms/index.mjs.map +1 -1
- package/dist/llms/types.d.ts +7 -0
- package/dist/llms/types.d.ts.map +1 -1
- package/dist/llms/writeLLMsTxt.d.ts +6 -0
- package/dist/llms/writeLLMsTxt.d.ts.map +1 -1
- package/dist/maps/index.js +5 -5
- package/dist/maps/index.mjs +3 -3
- package/dist/og/index.js +7 -7
- package/dist/og/index.mjs +2 -2
- package/dist/og/route.d.ts +6 -6
- package/dist/og/route.js.map +1 -1
- package/dist/og/route.mjs.map +1 -1
- package/dist/og/wiring.d.ts +4 -4
- package/dist/og/wiring.d.ts.map +1 -1
- package/dist/proxy/index.js +5 -5
- package/dist/proxy/index.mjs +3 -3
- package/dist/redirects/index.js +10 -10
- package/dist/redirects/index.mjs +3 -3
- package/dist/redirects/not-found.js +7 -7
- package/dist/redirects/not-found.mjs +3 -3
- package/dist/robots/indexnow.d.ts +17 -0
- package/dist/robots/indexnow.d.ts.map +1 -0
- package/dist/robots/indexnow.js +39 -0
- package/dist/robots/indexnow.js.map +1 -0
- package/dist/robots/indexnow.mjs +34 -0
- package/dist/robots/indexnow.mjs.map +1 -0
- package/dist/search/contract.d.ts +1 -1
- package/dist/search/contract.js +3 -3
- package/dist/search/contract.mjs +1 -1
- package/dist/search/index.js +7 -7
- package/dist/search/index.mjs +5 -5
- package/dist/seo/client.js +6 -6
- package/dist/seo/client.mjs +5 -5
- package/dist/seo/index.js +47 -47
- package/dist/seo/index.js.map +1 -1
- package/dist/seo/index.mjs +12 -12
- package/dist/seo/index.mjs.map +1 -1
- package/dist/seo/register-sitemap-cli-impl.d.ts +2 -0
- package/dist/seo/register-sitemap-cli-impl.d.ts.map +1 -1
- package/dist/seo/register-sitemap-cli.d.ts +1 -0
- package/dist/seo/register-sitemap-cli.d.ts.map +1 -1
- package/dist/seo/register-sitemap-cli.js +18 -14
- package/dist/seo/register-sitemap-cli.mjs +11 -7
- package/dist/seo/server.js +21 -21
- package/dist/seo/server.mjs +5 -5
- package/dist/server/index.js +3 -3
- package/dist/server/index.mjs +2 -2
- package/dist/{server-api-A2EFCTZX.mjs → server-api-7F5P6CSH.mjs} +6 -6
- package/dist/{server-api-A2EFCTZX.mjs.map → server-api-7F5P6CSH.mjs.map} +1 -1
- package/dist/{server-api-IWTZ7C3O.js → server-api-OC5JNK6R.js} +24 -24
- package/dist/{server-api-IWTZ7C3O.js.map → server-api-OC5JNK6R.js.map} +1 -1
- package/dist/shared/build-entries.d.ts +9 -7
- package/dist/shared/build-entries.d.ts.map +1 -1
- package/dist/shared/version.d.ts +1 -1
- package/dist/signal/index.js +11 -11
- package/dist/signal/index.mjs +2 -2
- package/dist/sitemap/discover.d.ts +1 -1
- package/dist/sitemap/index.d.ts +13 -1
- package/dist/sitemap/index.d.ts.map +1 -1
- package/dist/sitemap/index.js +48 -30
- package/dist/sitemap/index.js.map +1 -1
- package/dist/sitemap/index.mjs +27 -9
- package/dist/sitemap/index.mjs.map +1 -1
- package/dist/sitemap/shared.d.ts +1 -1
- package/dist/sitemap/shared.d.ts.map +1 -1
- package/dist/sites/site-param.d.ts +2 -2
- package/dist/sync/index.js +17 -17
- package/dist/sync/index.mjs +4 -4
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/writeLLMsTxt-LYYC3ZSN.mjs +11 -0
- package/dist/writeLLMsTxt-XHLHJ5XY.js +20 -0
- package/package.json +20 -14
- package/dist/BlogPostFaqSection-P3GXVQPA.mjs +0 -11
- package/dist/BlogPostFaqSection-P3GXVQPA.mjs.map +0 -1
- package/dist/BlogPostFaqSection-YG5J4B4U.js +0 -13
- package/dist/BlogPostFaqSection-YG5J4B4U.js.map +0 -1
- package/dist/BlogViewTracker-Q7Y4MN4B.mjs.map +0 -1
- package/dist/BlogViewTracker-S3CSRBIZ.js.map +0 -1
- package/dist/ChatWidget-76R7NOWD.js +0 -24
- package/dist/ChatWidget-G3KOUDX5.mjs +0 -15
- package/dist/EngageWidget-HD4F2ZVE.js +0 -21
- package/dist/EngageWidget-UJ47PQFG.mjs +0 -12
- package/dist/ManagedForm-4ZGU4R3G.js +0 -25
- package/dist/ManagedForm-Z7QE4KYI.mjs +0 -16
- package/dist/ManagedNewsletterForm-22EPZB7Z.js.map +0 -1
- package/dist/ManagedNewsletterForm-4TVO2VL4.mjs.map +0 -1
- package/dist/SitemapSync-GF4OKN4Z.js +0 -18
- package/dist/SitemapSync-WIUEYOBS.mjs +0 -9
- package/dist/blog/AuthorCard.d.ts.map +0 -1
- package/dist/blog/AuthorPage.d.ts.map +0 -1
- package/dist/blog/BlogFAQ.d.ts.map +0 -1
- package/dist/blog/BlogLayout.d.ts.map +0 -1
- package/dist/blog/BlogList.d.ts.map +0 -1
- package/dist/blog/BlogPost.d.ts.map +0 -1
- package/dist/blog/BlogPostFaqSection.d.ts +0 -3
- package/dist/blog/BlogPostFaqSection.d.ts.map +0 -1
- package/dist/blog/BlogSidebar.d.ts.map +0 -1
- package/dist/blog/BlogViewTracker.d.ts.map +0 -1
- package/dist/blog/ClusterLandingPage.d.ts.map +0 -1
- package/dist/blog/ClusterNavigation.d.ts.map +0 -1
- package/dist/blog/ManagedNewsletterForm.d.ts.map +0 -1
- package/dist/blog/NewsletterShell.d.ts.map +0 -1
- package/dist/blog/NewsletterWidget.d.ts.map +0 -1
- package/dist/blog/RelatedPosts.d.ts.map +0 -1
- package/dist/blog/ServiceCallout.d.ts.map +0 -1
- package/dist/blog/TableOfContents.d.ts.map +0 -1
- package/dist/blog/artwork.d.ts +0 -14
- package/dist/blog/artwork.d.ts.map +0 -1
- package/dist/blog/author-schema.d.ts.map +0 -1
- package/dist/blog/author-social.d.ts.map +0 -1
- package/dist/blog/blog-styles.d.ts.map +0 -1
- package/dist/blog/blog-tables.d.ts.map +0 -1
- package/dist/blog/excerpt.d.ts.map +0 -1
- package/dist/blog/index.d.ts.map +0 -1
- package/dist/blog/index.js.map +0 -1
- package/dist/blog/index.mjs.map +0 -1
- package/dist/blog/processBlogHtml.d.ts.map +0 -1
- package/dist/blog/public-reads.d.ts +0 -27
- package/dist/blog/public-reads.d.ts.map +0 -1
- package/dist/blog/reading-time.d.ts.map +0 -1
- package/dist/blog/routes.d.ts.map +0 -1
- package/dist/blog/server-core.d.ts.map +0 -1
- package/dist/blog/server-ui.d.ts +0 -29
- package/dist/blog/server-ui.d.ts.map +0 -1
- package/dist/blog/server-ui.js +0 -267
- package/dist/blog/server-ui.js.map +0 -1
- package/dist/blog/server-ui.mjs +0 -203
- package/dist/blog/server-ui.mjs.map +0 -1
- package/dist/blog/server.d.ts.map +0 -1
- package/dist/blog/server.js +0 -207
- package/dist/blog/server.mjs +0 -10
- package/dist/blog/types.d.ts.map +0 -1
- package/dist/blog/widget-styles.d.ts +0 -9
- package/dist/blog/widget-styles.d.ts.map +0 -1
- package/dist/blog-styles-6EY3BS5Y.js.map +0 -1
- package/dist/blog-styles-7AKRUMV7.mjs.map +0 -1
- package/dist/blog-tables-DWDEWA3S.js +0 -17
- package/dist/blog-tables-DWDEWA3S.js.map +0 -1
- package/dist/blog-tables-QGIHOESZ.mjs +0 -4
- package/dist/blog-tables-QGIHOESZ.mjs.map +0 -1
- package/dist/chunk-3EY5E35M.mjs.map +0 -1
- package/dist/chunk-4LYW6PMU.mjs.map +0 -1
- package/dist/chunk-4TLFZ6NR.mjs.map +0 -1
- package/dist/chunk-5B4J3IBX.mjs +0 -164
- package/dist/chunk-5B4J3IBX.mjs.map +0 -1
- package/dist/chunk-5FETEH3Y.mjs +0 -6
- package/dist/chunk-75A4KY4X.mjs.map +0 -1
- package/dist/chunk-7R6H3GQ4.js +0 -8
- package/dist/chunk-7TC3GRXQ.js.map +0 -1
- package/dist/chunk-AJBOEV4I.mjs.map +0 -1
- package/dist/chunk-AK6JZ3OE.mjs.map +0 -1
- package/dist/chunk-FHPW7XVH.js +0 -175
- package/dist/chunk-FHPW7XVH.js.map +0 -1
- package/dist/chunk-G2WC3CXW.js.map +0 -1
- package/dist/chunk-GHECYDSZ.mjs.map +0 -1
- package/dist/chunk-GQF6QAQS.js.map +0 -1
- package/dist/chunk-H5NBFNND.js.map +0 -1
- package/dist/chunk-HX6ZG3PP.js.map +0 -1
- package/dist/chunk-JLVCWC6A.mjs.map +0 -1
- package/dist/chunk-K4TCEAUX.js.map +0 -1
- package/dist/chunk-LMEUYRRR.js.map +0 -1
- package/dist/chunk-MWKI6ZIS.mjs.map +0 -1
- package/dist/chunk-O237KKCX.mjs.map +0 -1
- package/dist/chunk-Q2NBD54V.js.map +0 -1
- package/dist/chunk-R7GHP3FY.js.map +0 -1
- package/dist/chunk-W2U5SLMY.js.map +0 -1
- package/dist/chunk-XEB77DQS.js.map +0 -1
- package/dist/chunk-Y5QZPUL3.mjs.map +0 -1
- package/dist/chunk-YFX3Q56O.mjs.map +0 -1
- package/dist/chunk-YN7QHLWF.js.map +0 -1
- package/dist/chunk-YQTE32QK.js.map +0 -1
- package/dist/chunk-ZPLN537Q.mjs.map +0 -1
- package/dist/chunk-ZVI7MBVF.mjs.map +0 -1
- package/dist/discover-CYXYKHZ2.mjs +0 -4
- package/dist/discover-NGEPXZOD.js +0 -21
- package/dist/writeLLMsTxt-CQ7A4AAL.js +0 -19
- package/dist/writeLLMsTxt-NX5MSPYX.mjs +0 -10
- /package/dist/{blog → articles}/server.js.map +0 -0
- /package/dist/{blog → articles}/server.mjs.map +0 -0
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
var react = require('react');
|
|
5
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
6
|
|
|
7
|
-
// src/
|
|
7
|
+
// src/articles/ArticleFAQ.tsx
|
|
8
8
|
var defaultStyles = {
|
|
9
9
|
section: {
|
|
10
10
|
margin: "3rem 0",
|
|
@@ -159,7 +159,7 @@ function FAQItem({
|
|
|
159
159
|
}
|
|
160
160
|
);
|
|
161
161
|
}
|
|
162
|
-
function
|
|
162
|
+
function ArticleFAQ({
|
|
163
163
|
items,
|
|
164
164
|
title = "Frequently Asked Questions",
|
|
165
165
|
allowMultiple = false,
|
|
@@ -217,6 +217,6 @@ function BlogFAQ({
|
|
|
217
217
|
);
|
|
218
218
|
}
|
|
219
219
|
|
|
220
|
-
exports.
|
|
221
|
-
//# sourceMappingURL=chunk-
|
|
222
|
-
//# sourceMappingURL=chunk-
|
|
220
|
+
exports.ArticleFAQ = ArticleFAQ;
|
|
221
|
+
//# sourceMappingURL=chunk-OGNX6JT4.js.map
|
|
222
|
+
//# sourceMappingURL=chunk-OGNX6JT4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/articles/ArticleFAQ.tsx"],"names":["jsxs","jsx","useRef","useState","useCallback"],"mappings":"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","file":"chunk-OGNX6JT4.js","sourcesContent":["/**\n * @sonordev/site-kit/articles - Article FAQ Component\n *\n * Renders FAQ items with collapsible accordion behavior.\n * Content is always in the DOM (not display:none) for SEO crawlability.\n * Uses CSS max-height transitions — no JS animation library required.\n *\n * Pairs with FAQPage schema (generated by Signal AI in the publication pipeline)\n * for Google's \"People Also Ask\" featured snippets.\n *\n * @example\n * ```tsx\n * <ArticleFAQ items={post.faqItems} />\n * ```\n */\n\n'use client'\n\nimport React, { useState, useRef, useCallback } from 'react'\n\nexport interface FaqItem {\n question: string\n answer: string\n}\n\nexport interface ArticleFAQProps {\n items: FaqItem[]\n /** Section title */\n title?: string\n /** Allow multiple items open simultaneously */\n allowMultiple?: boolean\n /** Override styles with Tailwind classes */\n styles?: {\n section?: string\n title?: string\n list?: string\n item?: string\n question?: string\n questionText?: string\n icon?: string\n answer?: string\n answerInner?: string\n }\n unstyled?: boolean\n}\n\n// CSS custom property defaults\nconst defaultStyles = {\n section: {\n margin: '3rem 0',\n padding: 0,\n },\n title: {\n fontSize: '1.5rem',\n fontWeight: 700,\n color: 'var(--sk-text-primary, #0f172a)',\n marginBottom: '1.5rem',\n display: 'flex',\n alignItems: 'center',\n gap: '0.5rem',\n },\n list: {\n listStyle: 'none',\n margin: 0,\n padding: 0,\n display: 'flex',\n flexDirection: 'column' as const,\n gap: '0.5rem',\n },\n item: {\n borderRadius: '0.75rem',\n border: '1px solid var(--sk-surface-border, #e2e8f0)',\n background: 'var(--sk-bg-elevated, #f8fafc)',\n overflow: 'hidden',\n transition: 'border-color 0.2s, box-shadow 0.2s',\n },\n itemOpen: {\n borderColor: 'color-mix(in srgb, var(--sk-primary, #2563eb) 40%, var(--sk-surface-border, #e2e8f0))',\n boxShadow: '0 1px 3px rgba(0,0,0,0.06)',\n },\n question: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n width: '100%',\n padding: '1rem 1.25rem',\n background: 'none',\n border: 'none',\n cursor: 'pointer',\n textAlign: 'left' as const,\n },\n questionText: {\n fontSize: '1rem',\n fontWeight: 600,\n color: 'var(--sk-text-primary, #0f172a)',\n paddingRight: '1rem',\n },\n icon: {\n flexShrink: 0,\n width: '1.25rem',\n height: '1.25rem',\n color: 'var(--sk-primary, #2563eb)',\n transition: 'transform 0.2s',\n },\n answer: {\n overflow: 'hidden',\n transition: 'max-height 0.3s ease, opacity 0.2s ease',\n },\n answerInner: {\n padding: '0 1.25rem 1.25rem',\n fontSize: '0.9375rem',\n lineHeight: 1.7,\n color: 'var(--sk-text-secondary, #475569)',\n },\n}\n\nfunction PlusMinusIcon({ isOpen }: { isOpen: boolean }) {\n return (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n style={{\n ...defaultStyles.icon,\n transform: isOpen ? 'rotate(45deg)' : 'rotate(0deg)',\n }}\n >\n <line x1=\"10\" y1=\"4\" x2=\"10\" y2=\"16\" />\n <line x1=\"4\" y1=\"10\" x2=\"16\" y2=\"10\" />\n </svg>\n )\n}\n\nfunction FAQItem({\n item,\n isOpen,\n onToggle,\n styles,\n unstyled,\n}: {\n item: FaqItem\n isOpen: boolean\n onToggle: () => void\n styles?: ArticleFAQProps['styles']\n unstyled?: boolean\n}) {\n const answerRef = useRef<HTMLDivElement>(null)\n\n return (\n <li\n className={styles?.item}\n style={unstyled ? undefined : {\n ...defaultStyles.item,\n ...(isOpen ? defaultStyles.itemOpen : {}),\n }}\n >\n <button\n className={styles?.question}\n style={unstyled ? undefined : defaultStyles.question}\n onClick={onToggle}\n aria-expanded={isOpen}\n type=\"button\"\n >\n <span\n className={styles?.questionText}\n style={unstyled ? undefined : defaultStyles.questionText}\n >\n {item.question}\n </span>\n <span className={styles?.icon}>\n <PlusMinusIcon isOpen={isOpen} />\n </span>\n </button>\n <div\n ref={answerRef}\n className={styles?.answer}\n style={unstyled ? undefined : {\n ...defaultStyles.answer,\n maxHeight: isOpen ? `${(answerRef.current?.scrollHeight || 500) + 40}px` : '0',\n opacity: isOpen ? 1 : 0,\n }}\n role=\"region\"\n aria-hidden={!isOpen}\n >\n <div\n className={styles?.answerInner}\n style={unstyled ? undefined : defaultStyles.answerInner}\n dangerouslySetInnerHTML={{ __html: item.answer }}\n />\n </div>\n </li>\n )\n}\n\nexport function ArticleFAQ({\n items,\n title = 'Frequently Asked Questions',\n allowMultiple = false,\n styles,\n unstyled = false,\n}: ArticleFAQProps) {\n const [openIndices, setOpenIndices] = useState<Set<number>>(new Set())\n\n const toggle = useCallback((index: number) => {\n setOpenIndices(prev => {\n const next = new Set(allowMultiple ? prev : [])\n if (prev.has(index)) {\n next.delete(index)\n } else {\n next.add(index)\n }\n return next\n })\n }, [allowMultiple])\n\n if (!items || items.length === 0) return null\n\n return (\n <section\n className={styles?.section}\n style={unstyled ? undefined : defaultStyles.section}\n aria-label=\"Frequently Asked Questions\"\n >\n <h2\n className={styles?.title}\n style={unstyled ? undefined : defaultStyles.title}\n >\n {title}\n </h2>\n <ul\n className={styles?.list}\n style={unstyled ? undefined : defaultStyles.list}\n >\n {items.map((item, index) => (\n <FAQItem\n key={index}\n item={item}\n isOpen={openIndices.has(index)}\n onToggle={() => toggle(index)}\n styles={styles}\n unstyled={unstyled}\n />\n ))}\n </ul>\n </section>\n )\n}\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkBBBJHYPH_js = require('./chunk-BBBJHYPH.js');
|
|
4
4
|
var chunkO5GHP7UO_js = require('./chunk-O5GHP7UO.js');
|
|
5
|
-
var
|
|
5
|
+
var chunkIBJOGXQI_js = require('./chunk-IBJOGXQI.js');
|
|
6
6
|
var react = require('react');
|
|
7
7
|
require('server-only');
|
|
8
8
|
|
|
@@ -99,13 +99,13 @@ var getSchemaMarkups = react.cache(async (path, options) => {
|
|
|
99
99
|
return filterSchemaRows(ctx?.schemas ?? [], options);
|
|
100
100
|
});
|
|
101
101
|
var getFAQData = react.cache(async (path, site) => {
|
|
102
|
-
const result = await secureApiPost("/api/public/seo/faq",
|
|
102
|
+
const result = await secureApiPost("/api/public/seo/faq", chunkBBBJHYPH_js.withSiteBody({ path }, site));
|
|
103
103
|
return result?.faq || null;
|
|
104
104
|
});
|
|
105
105
|
var getInternalLinks = react.cache(async (sourcePath, options) => {
|
|
106
106
|
const result = await secureApiPost(
|
|
107
107
|
"/api/public/seo/internal-links",
|
|
108
|
-
|
|
108
|
+
chunkBBBJHYPH_js.withSiteBody(
|
|
109
109
|
{
|
|
110
110
|
sourcePath,
|
|
111
111
|
position: options?.position,
|
|
@@ -117,7 +117,7 @@ var getInternalLinks = react.cache(async (sourcePath, options) => {
|
|
|
117
117
|
return result?.links || [];
|
|
118
118
|
});
|
|
119
119
|
var getContentBlock = react.cache(async (path, section, site) => {
|
|
120
|
-
const result = await secureApiPost("/api/public/seo/content",
|
|
120
|
+
const result = await secureApiPost("/api/public/seo/content", chunkBBBJHYPH_js.withSiteBody({ path, section }, site));
|
|
121
121
|
return result?.content || null;
|
|
122
122
|
});
|
|
123
123
|
var getABTest = react.cache(async (path, field) => {
|
|
@@ -152,7 +152,7 @@ async function registerSitemap(entries, options) {
|
|
|
152
152
|
const { apiUrl, apiKey } = getSecureApiConfig();
|
|
153
153
|
const mode = options?.mode ?? "full-replace";
|
|
154
154
|
try {
|
|
155
|
-
const response = await
|
|
155
|
+
const response = await chunkIBJOGXQI_js.postRegisterSitemap({ apiUrl, apiKey, entries, mode, site: chunkIBJOGXQI_js.resolveSyncSite(options?.site) });
|
|
156
156
|
if (!response.ok) {
|
|
157
157
|
console.error(`@sonordev/seo: Sitemap registration failed: ${response.statusText}`);
|
|
158
158
|
return { success: false, created: 0, updated: 0 };
|
|
@@ -256,5 +256,5 @@ exports.getVisibilitySummary = getVisibilitySummary;
|
|
|
256
256
|
exports.pruneSchemaTypes = pruneSchemaTypes;
|
|
257
257
|
exports.recordABImpression = recordABImpression;
|
|
258
258
|
exports.registerSitemap = registerSitemap;
|
|
259
|
-
//# sourceMappingURL=chunk-
|
|
260
|
-
//# sourceMappingURL=chunk-
|
|
259
|
+
//# sourceMappingURL=chunk-OSU4QA5M.js.map
|
|
260
|
+
//# sourceMappingURL=chunk-OSU4QA5M.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/seo/schema-filter.ts","../src/seo/server-api.ts"],"names":["requireServerApiConfig","serverApiFetch","cache","withSiteBody","postRegisterSitemap","resolveSyncSite"],"mappings":"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","file":"chunk-FVW6FT6L.js","sourcesContent":["/**\n * @sonordev/site-kit/seo — `includeTypes` / `excludeTypes` for JSON-LD.\n *\n * SINGLE SOURCE OF TRUTH for the ManagedSchema type filter, used for Sonor's\n * schema-markup rows (`getSchemaMarkups`) and for the page's\n * `managed_schema` and entity-graph nodes (`ManagedSchema`).\n *\n * `excludeTypes` used to drop a row only when its `schema_type` matched\n * exactly, so a node of that type nested INSIDE a row got through. Found\n * 2026-09-15 on the MDG Green Bay site: the Georgetown and Westbrooke pages\n * carry a page-level row whose JSON-LD embeds a FAQPage for questions the\n * page doesn't show, and structured data has to describe visible content.\n * `excludeTypes: ['FAQPage']` couldn't touch it; the site template dropped\n * FAQPage nodes by hand and re-added the rows. Now an excluded type goes\n * wherever it sits: a whole row, an `@graph` member, or a nested value\n * (`mainEntity`, `hasPart`). A row left with nothing in it is dropped.\n *\n * `includeTypes` stays a row-level allow list on `schema_type`.\n *\n * Pure: no I/O.\n */\n\ntype Json = unknown\n\n/** A node's `@type`, as a list (`@type` may be a string or an array). */\nfunction typesOf(node: Record<string, unknown>): string[] {\n const t = node['@type']\n return Array.isArray(t) ? t.filter((x): x is string => typeof x === 'string') : typeof t === 'string' ? [t] : []\n}\n\nfunction isPlainObject(value: Json): value is Record<string, unknown> {\n return !!value && typeof value === 'object' && !Array.isArray(value)\n}\n\n/** Nothing left worth emitting: no keys but `@context`, and an empty or missing `@graph`. */\nfunction isEmptyNode(node: Record<string, unknown>): boolean {\n const keys = Object.keys(node).filter(k => k !== '@context')\n if (!keys.length) return true\n return keys.length === 1 && keys[0] === '@graph' && Array.isArray(node['@graph']) && node['@graph'].length === 0\n}\n\n/**\n * The same JSON-LD with every node whose `@type` is in `deny` removed, at any\n * depth. Returns null when the value itself is removed or nothing is left.\n * Doesn't mutate its input.\n */\nexport function pruneSchemaTypes(value: Json, deny: ReadonlySet<string>): Json | null {\n if (!deny.size) return value\n if (Array.isArray(value)) {\n const kept = value.map(v => pruneSchemaTypes(v, deny)).filter(v => v !== null)\n return kept\n }\n if (!isPlainObject(value)) return value\n if (typesOf(value).some(t => deny.has(t))) return null\n\n const out: Record<string, unknown> = {}\n for (const [key, child] of Object.entries(value)) {\n const next = pruneSchemaTypes(child, deny)\n if (next === null) continue\n // A property whose every node was excluded goes, rather than shipping [].\n if (Array.isArray(next) && next.length === 0 && Array.isArray(child) && child.length > 0 && key !== '@graph') {\n continue\n }\n out[key] = next\n }\n return isEmptyNode(out) && !isEmptyNode(value) ? null : out\n}\n\nexport interface SchemaTypeFilter {\n includeTypes?: string[]\n excludeTypes?: string[]\n}\n\n/**\n * Apply the filter to Sonor's schema-markup rows: `includeTypes` keeps rows\n * whose `schema_type` it names; `excludeTypes` drops matching rows and prunes\n * matching nodes out of the rest.\n */\nexport function filterSchemaRows<T extends { schema_type?: string; schema_json?: unknown }>(\n rows: T[],\n { includeTypes, excludeTypes }: SchemaTypeFilter = {},\n): T[] {\n let out = rows\n if (includeTypes?.length) {\n const allow = new Set(includeTypes)\n out = out.filter(r => r?.schema_type && allow.has(r.schema_type))\n }\n if (excludeTypes?.length) {\n const deny = new Set(excludeTypes)\n out = out.flatMap(r => {\n if (r?.schema_type && deny.has(r.schema_type)) return []\n if (r?.schema_json === undefined) return [r]\n const json = pruneSchemaTypes(r.schema_json, deny)\n return json === null ? [] : [{ ...r, schema_json: json }]\n })\n }\n return out\n}\n","/**\n * @sonordev/site-kit/seo - Server-Only API Functions\n * \n * SECURITY: These functions use private environment variables\n * and should ONLY be imported in server-side code (RSC, API routes, server actions).\n * \n * DO NOT import this file in client components or it will expose API keys.\n */\n\nimport { cache } from 'react'\nimport 'server-only' // This ensures the module can only be imported server-side\nimport { requireServerApiConfig, serverApiFetch } from '../server/server-fetch'\nimport { withSiteBody } from '../sites/site-param'\nimport { filterSchemaRows } from './schema-filter'\nimport { postRegisterSitemap, resolveSyncSite } from './register-sitemap-request'\n\n// ============================================\n// Server-Only API Config\n// ============================================\n\nconst SEO_LOG_PREFIX = '@sonordev/seo'\n\n/**\n * Config for portal API calls. Project is resolved by the portal from the API key;\n * sites never send or read project ID.\n *\n * Delegates to the shared `requireServerApiConfig` (single source of truth for\n * server API config — see `../server/server-fetch`) with an SEO-specific message.\n */\nfunction getSecureApiConfig() {\n return requireServerApiConfig(\n {},\n '@sonordev/seo: SONOR_API_KEY environment variable is required for server-side SEO functions',\n )\n}\n\n/** Derive project ID from API key for Signal API only (format: sonor_{uuid}_{secret}). Not used for portal. */\nfunction getProjectIdFromKey(apiKey: string): string | null {\n const match = apiKey.match(/^sonor_([0-9a-f-]{36})_/)\n return match ? match[1] : null\n}\n\n/**\n * POST to the Portal public API. Retries transient 429/502/503 with backoff\n * (parallel SSG workers behind one egress IP). 24h default revalidate — SEO data\n * rarely changes; Portal can on-demand revalidate. Throws if no API key is set.\n *\n * Thin wrapper over the shared `serverApiFetch` so the retry/backoff lives in one\n * place (see `../server/server-fetch`).\n */\nfunction secureApiPost<T>(endpoint: string, body: Record<string, any> = {}, revalidate = 86400): Promise<T | null> {\n return serverApiFetch<T>(endpoint, {\n method: 'POST',\n body,\n revalidate,\n requireKey: true,\n retry: true,\n logPrefix: SEO_LOG_PREFIX,\n })\n}\n\n/** GET from the Portal public API (single attempt, 24h revalidate). Throws if no API key is set. */\nfunction secureApiGet<T>(endpoint: string): Promise<T | null> {\n return serverApiFetch<T>(endpoint, {\n method: 'GET',\n revalidate: 86400,\n requireKey: true,\n retry: false,\n logPrefix: SEO_LOG_PREFIX,\n })\n}\n\n// ============================================\n// Secure Cached Data Fetchers\n// ============================================\n\n/** Response shape for POST /api/public/seo/page-context */\nexport type PageSeoContext = {\n page: any | null\n schemas: any[]\n project: {\n id: string\n title?: string | null\n /** Resolved site brand (settings.business_name → title/org name). Grounds the managed-title quality gate. */\n brand?: string | null\n domain?: string | null\n logo_url?: string | null\n site_url?: string | null\n } | null\n}\n\n/**\n * One Portal round-trip per path (page row + schemas + project).\n * React cache() dedupes when getSEOPageData + getSchemaMarkups run in the same render (e.g. metadata + ManagedSchema).\n * @server-only\n */\nconst loadPageSeoContext = cache(async (path: string): Promise<PageSeoContext | null> => {\n const result = await secureApiPost<PageSeoContext>('/api/public/seo/page-context', { path })\n if (!result) return null\n return {\n page: result.page ?? null,\n schemas: Array.isArray(result.schemas) ? result.schemas : [],\n project: result.project ?? null,\n }\n})\n\n/**\n * Fetch SEO page data - cached per request\n * @server-only\n */\nexport const getSEOPageData = cache(async (path: string) => {\n const ctx = await loadPageSeoContext(path)\n return {\n page: ctx?.page ?? null,\n project: ctx?.project ?? null,\n }\n})\n\n/**\n * Fetch schema markups for a page - cached per request (shares loadPageSeoContext with getSEOPageData)\n * @server-only\n */\nexport const getSchemaMarkups = cache(async (\n path: string,\n options?: { includeTypes?: string[]; excludeTypes?: string[] }\n) => {\n const ctx = await loadPageSeoContext(path)\n // Single source of truth for the type filter (also applied to\n // managed_schema in ManagedSchema): an excluded type is pruned wherever it\n // sits in a row, not only when it's the row's schema_type.\n return filterSchemaRows(ctx?.schemas ?? [], options)\n})\n\n// Managed FAQs, internal links and content blocks are site-scoped on\n// multi-site projects: a row with no site applies to every host, a row tagged\n// with a host applies only there. So these three reads send `site` in the body\n// via the shared `withSiteBody` (explicit → NEXT_PUBLIC_SITE_URL host →\n// window.location.host, omitted when nothing resolves). The API treats a\n// request with no site as the project's primary domain.\n\n/**\n * Fetch FAQ data for a page - cached per request\n * @param site Sub-site host override; resolves from NEXT_PUBLIC_SITE_URL when omitted\n * @server-only\n */\nexport const getFAQData = cache(async (path: string, site?: string) => {\n const result = await secureApiPost<{ faq: any }>('/api/public/seo/faq', withSiteBody({ path }, site))\n return result?.faq || null\n})\n\n/**\n * Fetch internal links for a page - cached per request\n * `options.site`: sub-site host override; resolves from NEXT_PUBLIC_SITE_URL when omitted\n * @server-only\n */\nexport const getInternalLinks = cache(async (\n sourcePath: string,\n options?: { position?: string; limit?: number; site?: string }\n) => {\n const result = await secureApiPost<{ links: any[] }>(\n '/api/public/seo/internal-links',\n withSiteBody(\n {\n sourcePath,\n position: options?.position,\n limit: options?.limit,\n },\n options?.site,\n ),\n )\n return result?.links || []\n})\n\n/**\n * Fetch content block - cached per request\n * @param site Sub-site host override; resolves from NEXT_PUBLIC_SITE_URL when omitted\n * @server-only\n */\nexport const getContentBlock = cache(async (path: string, section: string, site?: string) => {\n const result = await secureApiPost<{ content: any }>('/api/public/seo/content', withSiteBody({ path, section }, site))\n return result?.content || null\n})\n\n/**\n * Fetch A/B test and determine variant - cached per request\n * @server-only\n */\nexport const getABTest = cache(async (path: string, field: string) => {\n const result = await secureApiPost<{ test: any }>('/api/public/seo/ab-test', { path, field })\n return result?.test || null\n})\n\n/**\n * Record A/B test impression\n * @server-only\n */\nexport async function recordABImpression(\n testId: string,\n variant: 'a' | 'b',\n sessionId?: string\n): Promise<void> {\n await secureApiPost('/api/public/seo/ab-impression', { testId, variant, sessionId })\n}\n\n/**\n * Fetch redirect for a path - cached per request\n * @server-only\n */\nexport const getRedirectData = cache(async (path: string) => {\n const result = await secureApiPost<{ redirect: any }>('/api/public/seo/redirect', { path })\n return result?.redirect || null\n})\n\n/**\n * Fetch managed scripts - cached per request\n * @server-only\n */\nexport const getManagedScripts = cache(async (position: string, currentPath?: string) => {\n const result = await secureApiPost<{ scripts: any[] }>('/api/public/seo/scripts', {\n position,\n currentPath,\n })\n return result?.scripts || []\n})\n\n/**\n * Fetch robots directive for a page - cached per request\n * @server-only\n */\nexport const getRobotsData = cache(async (path: string) => {\n const { page } = await getSEOPageData(path)\n return page?.managed_robots || null\n})\n\n/**\n * Fetch sitemap entries - cached per request\n * @server-only\n */\nexport const getSitemapEntries = cache(async (options?: { publishedOnly?: boolean }) => {\n const result = await secureApiPost<{ entries: any[] }>('/api/public/seo/sitemap', {\n publishedOnly: options?.publishedOnly,\n })\n return result?.entries || []\n})\n\n/**\n * Register/sync sitemap entries from the client site\n * Call this at build time to populate seo_pages from your sitemap.xml\n * @server-only\n *\n * Defaults to mode 'full-replace', which PRUNES every page missing from\n * `entries`. Pass `{ mode: 'additive' }` unless the list is the whole site.\n *\n * @example\n * ```ts\n * // scripts/register-sitemap.ts (run at build time)\n * import { registerSitemap } from '@sonordev/site-kit/seo/server'\n *\n * await registerSitemap(\n * [\n * { path: '/', priority: 1.0, changefreq: 'daily' },\n * { path: '/about', priority: 0.8, changefreq: 'weekly' },\n * ],\n * { mode: 'additive' },\n * )\n * ```\n */\nexport async function registerSitemap(\n entries: Array<{\n path: string\n title?: string\n priority?: number\n changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never'\n }>,\n options?: {\n /**\n * Sync mode:\n * - 'full-replace': replaces the entire page set (default for build-time sync)\n * - 'additive': adds/updates pages but never deletes existing ones\n */\n mode?: 'additive' | 'full-replace'\n /**\n * Sub-site host these pages belong to, on a multi-site project. Defaults\n * to NEXT_PUBLIC_SITE_URL's host; left off when nothing resolves.\n */\n site?: string\n }\n): Promise<{ success: boolean; created: number; updated: number }> {\n const { apiUrl, apiKey } = getSecureApiConfig()\n const mode = options?.mode ?? 'full-replace'\n\n try {\n const response = await postRegisterSitemap({ apiUrl, apiKey, entries, mode, site: resolveSyncSite(options?.site) })\n \n if (!response.ok) {\n console.error(`@sonordev/seo: Sitemap registration failed: ${response.statusText}`)\n return { success: false, created: 0, updated: 0 }\n }\n \n return await response.json()\n } catch (error) {\n console.error('@sonordev/seo: Sitemap registration error:', error)\n return { success: false, created: 0, updated: 0 }\n }\n}\n\n// ============================================\n// Signal-Powered Metadata Fallback\n// ============================================\n\n/**\n * Ensure metadata exists for a page by triggering Signal AI optimization.\n * If the page has no managed_title or managed_meta_description, Signal will\n * generate them and save to the database via Portal proxy.\n *\n * Idempotent — returns existing metadata if already populated.\n * @server-only\n */\nexport const ensureMetadata = cache(async (path: string): Promise<{\n managed_title?: string\n managed_meta_description?: string\n managed_keywords?: string[]\n managed_schema?: Record<string, unknown>\n} | null> => {\n return secureApiPost('/api/public/seo/ensure-metadata', { path })\n})\n\n// ============================================\n// AI Visibility & Entity Graph API (Signal)\n// ============================================\n\nfunction getSignalApiConfig() {\n const apiUrl = process.env.SONOR_SIGNAL_URL || process.env.SIGNAL_API_URL || process.env.NEXT_PUBLIC_SIGNAL_API_URL || 'https://signal.sonor.io'\n const apiKey = process.env.SONOR_API_KEY || ''\n return { apiUrl, apiKey }\n}\n\nasync function signalApiGet<T>(endpoint: string): Promise<T | null> {\n const { apiUrl, apiKey } = getSignalApiConfig()\n \n if (!apiKey) {\n return null\n }\n \n try {\n const response = await fetch(`${apiUrl}${endpoint}`, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n next: { revalidate: 300 }, // Cache for 5 minutes\n })\n \n if (!response.ok) {\n return null\n }\n \n const result = await response.json()\n return result?.data || result\n } catch (error) {\n console.error('@sonordev/seo: Signal API error:', error)\n return null\n }\n}\n\n/**\n * Entity types for the knowledge graph\n */\nexport type EntityType = \n | 'organization'\n | 'person'\n | 'service'\n | 'product'\n | 'location'\n | 'concept'\n | 'credential'\n\n/**\n * Entity from the knowledge graph\n */\nexport interface SEOEntity {\n id: string\n project_id: string\n entity_type: EntityType\n name: string\n slug: string\n properties: Record<string, unknown>\n knows_about: string[]\n same_as: string[]\n schema_type?: string\n is_primary: boolean\n}\n\n/**\n * Fetch entities for a project - cached per request\n * Returns the entity graph for enhanced schema markup\n * @server-only\n */\nexport const getEntities = cache(async (\n options?: { type?: EntityType }\n): Promise<SEOEntity[]> => {\n const { apiKey } = getSecureApiConfig()\n const projectId = getProjectIdFromKey(apiKey)\n if (!projectId) return []\n let endpoint = `/skills/seo/entities/${projectId}`\n if (options?.type) {\n endpoint += `?type=${options.type}`\n }\n const result = await signalApiGet<SEOEntity[]>(endpoint)\n return result || []\n})\n\n/**\n * Fetch primary entity (the business) - cached per request\n * @server-only\n */\nexport const getPrimaryEntity = cache(async (): Promise<SEOEntity | null> => {\n const { apiKey } = getSecureApiConfig()\n const projectId = getProjectIdFromKey(apiKey)\n if (!projectId) return null\n return signalApiGet<SEOEntity>(`/skills/seo/entities/${projectId}/primary`)\n})\n\n/**\n * Fetch entity-enhanced schema for a page\n * Returns Organization schema with knowsAbout, areaServed, employee, etc.\n * @server-only\n */\nexport const getEntityEnhancedSchema = cache(async (pagePath: string): Promise<object[]> => {\n const { apiKey } = getSecureApiConfig()\n const projectId = getProjectIdFromKey(apiKey)\n if (!projectId) return []\n const result = await signalApiGet<{ schemas: object[] }>(\n `/skills/seo/schema/${projectId}/entity-enhanced?pagePath=${encodeURIComponent(pagePath)}`\n )\n return result?.schemas || []\n})\n\n/**\n * Get AI visibility score for a page\n * @server-only\n */\nexport const getVisibilityScore = cache(async (\n pagePath: string\n): Promise<{\n overall_score: number\n entity_coverage: number\n answer_density: number\n chunk_readability: number\n authority_signals: number\n schema_completeness: number\n} | null> => {\n const { apiKey } = getSecureApiConfig()\n const projectId = getProjectIdFromKey(apiKey)\n if (!projectId) return null\n const result = await signalApiGet<any[]>(`/skills/seo/visibility/${projectId}`)\n if (!result) return null\n return result.find(s => s.page_path === pagePath) || null\n})\n\n/**\n * Get AI visibility summary for project\n * @server-only\n */\nexport const getVisibilitySummary = cache(async (): Promise<{\n overall_score: number\n total_entities: number\n pages_analyzed: number\n top_recommendations: Array<{ priority: string; type: string; message: string }>\n} | null> => {\n const { apiKey } = getSecureApiConfig()\n const projectId = getProjectIdFromKey(apiKey)\n if (!projectId) return null\n return signalApiGet(`/skills/seo/visibility/${projectId}/summary`)\n})\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/seo/schema-filter.ts","../src/seo/server-api.ts"],"names":["requireServerApiConfig","serverApiFetch","cache","withSiteBody","postRegisterSitemap","resolveSyncSite"],"mappings":"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","file":"chunk-OSU4QA5M.js","sourcesContent":["/**\n * @sonordev/site-kit/seo — `includeTypes` / `excludeTypes` for JSON-LD.\n *\n * SINGLE SOURCE OF TRUTH for the ManagedSchema type filter, used for Sonor's\n * schema-markup rows (`getSchemaMarkups`) and for the page's\n * `managed_schema` and entity-graph nodes (`ManagedSchema`).\n *\n * `excludeTypes` used to drop a row only when its `schema_type` matched\n * exactly, so a node of that type nested INSIDE a row got through. Found\n * 2026-09-15 on the MDG Green Bay site: the Georgetown and Westbrooke pages\n * carry a page-level row whose JSON-LD embeds a FAQPage for questions the\n * page doesn't show, and structured data has to describe visible content.\n * `excludeTypes: ['FAQPage']` couldn't touch it; the site template dropped\n * FAQPage nodes by hand and re-added the rows. Now an excluded type goes\n * wherever it sits: a whole row, an `@graph` member, or a nested value\n * (`mainEntity`, `hasPart`). A row left with nothing in it is dropped.\n *\n * `includeTypes` stays a row-level allow list on `schema_type`.\n *\n * Pure: no I/O.\n */\n\ntype Json = unknown\n\n/** A node's `@type`, as a list (`@type` may be a string or an array). */\nfunction typesOf(node: Record<string, unknown>): string[] {\n const t = node['@type']\n return Array.isArray(t) ? t.filter((x): x is string => typeof x === 'string') : typeof t === 'string' ? [t] : []\n}\n\nfunction isPlainObject(value: Json): value is Record<string, unknown> {\n return !!value && typeof value === 'object' && !Array.isArray(value)\n}\n\n/** Nothing left worth emitting: no keys but `@context`, and an empty or missing `@graph`. */\nfunction isEmptyNode(node: Record<string, unknown>): boolean {\n const keys = Object.keys(node).filter(k => k !== '@context')\n if (!keys.length) return true\n return keys.length === 1 && keys[0] === '@graph' && Array.isArray(node['@graph']) && node['@graph'].length === 0\n}\n\n/**\n * The same JSON-LD with every node whose `@type` is in `deny` removed, at any\n * depth. Returns null when the value itself is removed or nothing is left.\n * Doesn't mutate its input.\n */\nexport function pruneSchemaTypes(value: Json, deny: ReadonlySet<string>): Json | null {\n if (!deny.size) return value\n if (Array.isArray(value)) {\n const kept = value.map(v => pruneSchemaTypes(v, deny)).filter(v => v !== null)\n return kept\n }\n if (!isPlainObject(value)) return value\n if (typesOf(value).some(t => deny.has(t))) return null\n\n const out: Record<string, unknown> = {}\n for (const [key, child] of Object.entries(value)) {\n const next = pruneSchemaTypes(child, deny)\n if (next === null) continue\n // A property whose every node was excluded goes, rather than shipping [].\n if (Array.isArray(next) && next.length === 0 && Array.isArray(child) && child.length > 0 && key !== '@graph') {\n continue\n }\n out[key] = next\n }\n return isEmptyNode(out) && !isEmptyNode(value) ? null : out\n}\n\nexport interface SchemaTypeFilter {\n includeTypes?: string[]\n excludeTypes?: string[]\n}\n\n/**\n * Apply the filter to Sonor's schema-markup rows: `includeTypes` keeps rows\n * whose `schema_type` it names; `excludeTypes` drops matching rows and prunes\n * matching nodes out of the rest.\n */\nexport function filterSchemaRows<T extends { schema_type?: string; schema_json?: unknown }>(\n rows: T[],\n { includeTypes, excludeTypes }: SchemaTypeFilter = {},\n): T[] {\n let out = rows\n if (includeTypes?.length) {\n const allow = new Set(includeTypes)\n out = out.filter(r => r?.schema_type && allow.has(r.schema_type))\n }\n if (excludeTypes?.length) {\n const deny = new Set(excludeTypes)\n out = out.flatMap(r => {\n if (r?.schema_type && deny.has(r.schema_type)) return []\n if (r?.schema_json === undefined) return [r]\n const json = pruneSchemaTypes(r.schema_json, deny)\n return json === null ? [] : [{ ...r, schema_json: json }]\n })\n }\n return out\n}\n","/**\n * @sonordev/site-kit/seo - Server-Only API Functions\n * \n * SECURITY: These functions use private environment variables\n * and should ONLY be imported in server-side code (RSC, API routes, server actions).\n * \n * DO NOT import this file in client components or it will expose API keys.\n */\n\nimport { cache } from 'react'\nimport 'server-only' // This ensures the module can only be imported server-side\nimport { requireServerApiConfig, serverApiFetch } from '../server/server-fetch'\nimport { withSiteBody } from '../sites/site-param'\nimport { filterSchemaRows } from './schema-filter'\nimport { postRegisterSitemap, resolveSyncSite } from './register-sitemap-request'\n\n// ============================================\n// Server-Only API Config\n// ============================================\n\nconst SEO_LOG_PREFIX = '@sonordev/seo'\n\n/**\n * Config for portal API calls. Project is resolved by the portal from the API key;\n * sites never send or read project ID.\n *\n * Delegates to the shared `requireServerApiConfig` (single source of truth for\n * server API config — see `../server/server-fetch`) with an SEO-specific message.\n */\nfunction getSecureApiConfig() {\n return requireServerApiConfig(\n {},\n '@sonordev/seo: SONOR_API_KEY environment variable is required for server-side SEO functions',\n )\n}\n\n/** Derive project ID from API key for Signal API only (format: sonor_{uuid}_{secret}). Not used for portal. */\nfunction getProjectIdFromKey(apiKey: string): string | null {\n const match = apiKey.match(/^sonor_([0-9a-f-]{36})_/)\n return match ? match[1] : null\n}\n\n/**\n * POST to the Portal public API. Retries transient 429/502/503 with backoff\n * (parallel SSG workers behind one egress IP). 24h default revalidate — SEO data\n * rarely changes; Portal can on-demand revalidate. Throws if no API key is set.\n *\n * Thin wrapper over the shared `serverApiFetch` so the retry/backoff lives in one\n * place (see `../server/server-fetch`).\n */\nfunction secureApiPost<T>(endpoint: string, body: Record<string, any> = {}, revalidate = 86400): Promise<T | null> {\n return serverApiFetch<T>(endpoint, {\n method: 'POST',\n body,\n revalidate,\n requireKey: true,\n retry: true,\n logPrefix: SEO_LOG_PREFIX,\n })\n}\n\n/** GET from the Portal public API (single attempt, 24h revalidate). Throws if no API key is set. */\nfunction secureApiGet<T>(endpoint: string): Promise<T | null> {\n return serverApiFetch<T>(endpoint, {\n method: 'GET',\n revalidate: 86400,\n requireKey: true,\n retry: false,\n logPrefix: SEO_LOG_PREFIX,\n })\n}\n\n// ============================================\n// Secure Cached Data Fetchers\n// ============================================\n\n/** Response shape for POST /api/public/seo/page-context */\nexport type PageSeoContext = {\n page: any | null\n schemas: any[]\n project: {\n id: string\n title?: string | null\n /** Resolved site brand (settings.business_name → title/org name). Grounds the managed-title quality gate. */\n brand?: string | null\n domain?: string | null\n logo_url?: string | null\n site_url?: string | null\n } | null\n}\n\n/**\n * One Portal round-trip per path (page row + schemas + project).\n * React cache() dedupes when getSEOPageData + getSchemaMarkups run in the same render (e.g. metadata + ManagedSchema).\n * @server-only\n */\nconst loadPageSeoContext = cache(async (path: string): Promise<PageSeoContext | null> => {\n const result = await secureApiPost<PageSeoContext>('/api/public/seo/page-context', { path })\n if (!result) return null\n return {\n page: result.page ?? null,\n schemas: Array.isArray(result.schemas) ? result.schemas : [],\n project: result.project ?? null,\n }\n})\n\n/**\n * Fetch SEO page data - cached per request\n * @server-only\n */\nexport const getSEOPageData = cache(async (path: string) => {\n const ctx = await loadPageSeoContext(path)\n return {\n page: ctx?.page ?? null,\n project: ctx?.project ?? null,\n }\n})\n\n/**\n * Fetch schema markups for a page - cached per request (shares loadPageSeoContext with getSEOPageData)\n * @server-only\n */\nexport const getSchemaMarkups = cache(async (\n path: string,\n options?: { includeTypes?: string[]; excludeTypes?: string[] }\n) => {\n const ctx = await loadPageSeoContext(path)\n // Single source of truth for the type filter (also applied to\n // managed_schema in ManagedSchema): an excluded type is pruned wherever it\n // sits in a row, not only when it's the row's schema_type.\n return filterSchemaRows(ctx?.schemas ?? [], options)\n})\n\n// Managed FAQs, internal links and content blocks are site-scoped on\n// multi-site projects: a row with no site applies to every host, a row tagged\n// with a host applies only there. So these three reads send `site` in the body\n// via the shared `withSiteBody` (explicit → NEXT_PUBLIC_SITE_URL host →\n// window.location.host, omitted when nothing resolves). The API treats a\n// request with no site as the project's primary domain.\n\n/**\n * Fetch FAQ data for a page - cached per request\n * @param site Sub-site host override; resolves from NEXT_PUBLIC_SITE_URL when omitted\n * @server-only\n */\nexport const getFAQData = cache(async (path: string, site?: string) => {\n const result = await secureApiPost<{ faq: any }>('/api/public/seo/faq', withSiteBody({ path }, site))\n return result?.faq || null\n})\n\n/**\n * Fetch internal links for a page - cached per request\n * `options.site`: sub-site host override; resolves from NEXT_PUBLIC_SITE_URL when omitted\n * @server-only\n */\nexport const getInternalLinks = cache(async (\n sourcePath: string,\n options?: { position?: string; limit?: number; site?: string }\n) => {\n const result = await secureApiPost<{ links: any[] }>(\n '/api/public/seo/internal-links',\n withSiteBody(\n {\n sourcePath,\n position: options?.position,\n limit: options?.limit,\n },\n options?.site,\n ),\n )\n return result?.links || []\n})\n\n/**\n * Fetch content block - cached per request\n * @param site Sub-site host override; resolves from NEXT_PUBLIC_SITE_URL when omitted\n * @server-only\n */\nexport const getContentBlock = cache(async (path: string, section: string, site?: string) => {\n const result = await secureApiPost<{ content: any }>('/api/public/seo/content', withSiteBody({ path, section }, site))\n return result?.content || null\n})\n\n/**\n * Fetch A/B test and determine variant - cached per request\n * @server-only\n */\nexport const getABTest = cache(async (path: string, field: string) => {\n const result = await secureApiPost<{ test: any }>('/api/public/seo/ab-test', { path, field })\n return result?.test || null\n})\n\n/**\n * Record A/B test impression\n * @server-only\n */\nexport async function recordABImpression(\n testId: string,\n variant: 'a' | 'b',\n sessionId?: string\n): Promise<void> {\n await secureApiPost('/api/public/seo/ab-impression', { testId, variant, sessionId })\n}\n\n/**\n * Fetch redirect for a path - cached per request\n * @server-only\n */\nexport const getRedirectData = cache(async (path: string) => {\n const result = await secureApiPost<{ redirect: any }>('/api/public/seo/redirect', { path })\n return result?.redirect || null\n})\n\n/**\n * Fetch managed scripts - cached per request\n * @server-only\n */\nexport const getManagedScripts = cache(async (position: string, currentPath?: string) => {\n const result = await secureApiPost<{ scripts: any[] }>('/api/public/seo/scripts', {\n position,\n currentPath,\n })\n return result?.scripts || []\n})\n\n/**\n * Fetch robots directive for a page - cached per request\n * @server-only\n */\nexport const getRobotsData = cache(async (path: string) => {\n const { page } = await getSEOPageData(path)\n return page?.managed_robots || null\n})\n\n/**\n * Fetch sitemap entries - cached per request\n * @server-only\n */\nexport const getSitemapEntries = cache(async (options?: { publishedOnly?: boolean }) => {\n const result = await secureApiPost<{ entries: any[] }>('/api/public/seo/sitemap', {\n publishedOnly: options?.publishedOnly,\n })\n return result?.entries || []\n})\n\n/**\n * Register/sync sitemap entries from the client site\n * Call this at build time to populate seo_pages from your sitemap.xml\n * @server-only\n *\n * Defaults to mode 'full-replace', which PRUNES every page missing from\n * `entries`. Pass `{ mode: 'additive' }` unless the list is the whole site.\n *\n * @example\n * ```ts\n * // scripts/register-sitemap.ts (run at build time)\n * import { registerSitemap } from '@sonordev/site-kit/seo/server'\n *\n * await registerSitemap(\n * [\n * { path: '/', priority: 1.0, changefreq: 'daily' },\n * { path: '/about', priority: 0.8, changefreq: 'weekly' },\n * ],\n * { mode: 'additive' },\n * )\n * ```\n */\nexport async function registerSitemap(\n entries: Array<{\n path: string\n title?: string\n priority?: number\n changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never'\n }>,\n options?: {\n /**\n * Sync mode:\n * - 'full-replace': replaces the entire page set (default for build-time sync)\n * - 'additive': adds/updates pages but never deletes existing ones\n */\n mode?: 'additive' | 'full-replace'\n /**\n * Sub-site host these pages belong to, on a multi-site project. Defaults\n * to NEXT_PUBLIC_SITE_URL's host; left off when nothing resolves.\n */\n site?: string\n }\n): Promise<{ success: boolean; created: number; updated: number }> {\n const { apiUrl, apiKey } = getSecureApiConfig()\n const mode = options?.mode ?? 'full-replace'\n\n try {\n const response = await postRegisterSitemap({ apiUrl, apiKey, entries, mode, site: resolveSyncSite(options?.site) })\n \n if (!response.ok) {\n console.error(`@sonordev/seo: Sitemap registration failed: ${response.statusText}`)\n return { success: false, created: 0, updated: 0 }\n }\n \n return await response.json()\n } catch (error) {\n console.error('@sonordev/seo: Sitemap registration error:', error)\n return { success: false, created: 0, updated: 0 }\n }\n}\n\n// ============================================\n// Signal-Powered Metadata Fallback\n// ============================================\n\n/**\n * Ensure metadata exists for a page by triggering Signal AI optimization.\n * If the page has no managed_title or managed_meta_description, Signal will\n * generate them and save to the database via Portal proxy.\n *\n * Idempotent — returns existing metadata if already populated.\n * @server-only\n */\nexport const ensureMetadata = cache(async (path: string): Promise<{\n managed_title?: string\n managed_meta_description?: string\n managed_keywords?: string[]\n managed_schema?: Record<string, unknown>\n} | null> => {\n return secureApiPost('/api/public/seo/ensure-metadata', { path })\n})\n\n// ============================================\n// AI Visibility & Entity Graph API (Signal)\n// ============================================\n\nfunction getSignalApiConfig() {\n const apiUrl = process.env.SONOR_SIGNAL_URL || process.env.SIGNAL_API_URL || process.env.NEXT_PUBLIC_SIGNAL_API_URL || 'https://signal.sonor.io'\n const apiKey = process.env.SONOR_API_KEY || ''\n return { apiUrl, apiKey }\n}\n\nasync function signalApiGet<T>(endpoint: string): Promise<T | null> {\n const { apiUrl, apiKey } = getSignalApiConfig()\n \n if (!apiKey) {\n return null\n }\n \n try {\n const response = await fetch(`${apiUrl}${endpoint}`, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n next: { revalidate: 300 }, // Cache for 5 minutes\n })\n \n if (!response.ok) {\n return null\n }\n \n const result = await response.json()\n return result?.data || result\n } catch (error) {\n console.error('@sonordev/seo: Signal API error:', error)\n return null\n }\n}\n\n/**\n * Entity types for the knowledge graph\n */\nexport type EntityType = \n | 'organization'\n | 'person'\n | 'service'\n | 'product'\n | 'location'\n | 'concept'\n | 'credential'\n\n/**\n * Entity from the knowledge graph\n */\nexport interface SEOEntity {\n id: string\n project_id: string\n entity_type: EntityType\n name: string\n slug: string\n properties: Record<string, unknown>\n knows_about: string[]\n same_as: string[]\n schema_type?: string\n is_primary: boolean\n}\n\n/**\n * Fetch entities for a project - cached per request\n * Returns the entity graph for enhanced schema markup\n * @server-only\n */\nexport const getEntities = cache(async (\n options?: { type?: EntityType }\n): Promise<SEOEntity[]> => {\n const { apiKey } = getSecureApiConfig()\n const projectId = getProjectIdFromKey(apiKey)\n if (!projectId) return []\n let endpoint = `/skills/seo/entities/${projectId}`\n if (options?.type) {\n endpoint += `?type=${options.type}`\n }\n const result = await signalApiGet<SEOEntity[]>(endpoint)\n return result || []\n})\n\n/**\n * Fetch primary entity (the business) - cached per request\n * @server-only\n */\nexport const getPrimaryEntity = cache(async (): Promise<SEOEntity | null> => {\n const { apiKey } = getSecureApiConfig()\n const projectId = getProjectIdFromKey(apiKey)\n if (!projectId) return null\n return signalApiGet<SEOEntity>(`/skills/seo/entities/${projectId}/primary`)\n})\n\n/**\n * Fetch entity-enhanced schema for a page\n * Returns Organization schema with knowsAbout, areaServed, employee, etc.\n * @server-only\n */\nexport const getEntityEnhancedSchema = cache(async (pagePath: string): Promise<object[]> => {\n const { apiKey } = getSecureApiConfig()\n const projectId = getProjectIdFromKey(apiKey)\n if (!projectId) return []\n const result = await signalApiGet<{ schemas: object[] }>(\n `/skills/seo/schema/${projectId}/entity-enhanced?pagePath=${encodeURIComponent(pagePath)}`\n )\n return result?.schemas || []\n})\n\n/**\n * Get AI visibility score for a page\n * @server-only\n */\nexport const getVisibilityScore = cache(async (\n pagePath: string\n): Promise<{\n overall_score: number\n entity_coverage: number\n answer_density: number\n chunk_readability: number\n authority_signals: number\n schema_completeness: number\n} | null> => {\n const { apiKey } = getSecureApiConfig()\n const projectId = getProjectIdFromKey(apiKey)\n if (!projectId) return null\n const result = await signalApiGet<any[]>(`/skills/seo/visibility/${projectId}`)\n if (!result) return null\n return result.find(s => s.page_path === pagePath) || null\n})\n\n/**\n * Get AI visibility summary for project\n * @server-only\n */\nexport const getVisibilitySummary = cache(async (): Promise<{\n overall_score: number\n total_entities: number\n pages_analyzed: number\n top_recommendations: Array<{ priority: string; type: string; message: string }>\n} | null> => {\n const { apiKey } = getSecureApiConfig()\n const projectId = getProjectIdFromKey(apiKey)\n if (!projectId) return null\n return signalApiGet(`/skills/seo/visibility/${projectId}/summary`)\n})\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var chunk5ABTBPPK_js = require('./chunk-5ABTBPPK.js');
|
|
5
5
|
var react = require('react');
|
|
6
6
|
var jsxRuntime = require('react/jsx-runtime');
|
|
7
7
|
|
|
@@ -40,7 +40,7 @@ function ManagedImage({
|
|
|
40
40
|
}
|
|
41
41
|
try {
|
|
42
42
|
const params = new URLSearchParams({ page_path: currentPath });
|
|
43
|
-
const res = await
|
|
43
|
+
const res = await chunk5ABTBPPK_js.sonorFetch(
|
|
44
44
|
`${apiUrl}/public/images/slot/${encodeURIComponent(slotId)}?${params}`,
|
|
45
45
|
{ headers: { "Content-Type": "application/json" } },
|
|
46
46
|
{ apiKey }
|
|
@@ -214,7 +214,7 @@ function ImagePickerModal({
|
|
|
214
214
|
const params = new URLSearchParams();
|
|
215
215
|
if (currentFolder) params.set("folder", currentFolder);
|
|
216
216
|
if (search) params.set("search", search);
|
|
217
|
-
const res = await
|
|
217
|
+
const res = await chunk5ABTBPPK_js.sonorFetch(
|
|
218
218
|
`${config.apiUrl}/public/images/files?${params}`,
|
|
219
219
|
{ headers: { "Content-Type": "application/json" } },
|
|
220
220
|
{ apiKey: config.apiKey }
|
|
@@ -236,7 +236,7 @@ function ImagePickerModal({
|
|
|
236
236
|
const handleSelectFile = async (file) => {
|
|
237
237
|
if (!config?.apiKey || !config?.apiUrl) return;
|
|
238
238
|
try {
|
|
239
|
-
const res = await
|
|
239
|
+
const res = await chunk5ABTBPPK_js.sonorFetch(
|
|
240
240
|
`${config.apiUrl}/public/images/slot/${encodeURIComponent(slotId)}`,
|
|
241
241
|
{
|
|
242
242
|
method: "POST",
|
|
@@ -267,7 +267,7 @@ function ImagePickerModal({
|
|
|
267
267
|
formData.append("page_path", pagePath);
|
|
268
268
|
formData.append("folder", currentFolder || "Website/Images");
|
|
269
269
|
if (altText) formData.append("alt_text", altText);
|
|
270
|
-
const res = await
|
|
270
|
+
const res = await chunk5ABTBPPK_js.sonorFetch(`${config.apiUrl}/public/images/upload`, {
|
|
271
271
|
method: "POST",
|
|
272
272
|
body: formData
|
|
273
273
|
}, { apiKey: config.apiKey, retries: 0, timeoutMs: 6e4 });
|
|
@@ -284,7 +284,7 @@ function ImagePickerModal({
|
|
|
284
284
|
if (!config?.apiKey || !config?.apiUrl) return;
|
|
285
285
|
try {
|
|
286
286
|
const params = new URLSearchParams({ page_path: pagePath });
|
|
287
|
-
await
|
|
287
|
+
await chunk5ABTBPPK_js.sonorFetch(
|
|
288
288
|
`${config.apiUrl}/public/images/slot/${encodeURIComponent(slotId)}?${params}`,
|
|
289
289
|
{ method: "DELETE" },
|
|
290
290
|
{ apiKey: config.apiKey, retries: 0 }
|
|
@@ -428,7 +428,7 @@ function ImagePickerModal({
|
|
|
428
428
|
async function fetchManagedImage(config, slotId, pagePath) {
|
|
429
429
|
const params = new URLSearchParams();
|
|
430
430
|
if (pagePath) params.set("page_path", pagePath);
|
|
431
|
-
const res = await
|
|
431
|
+
const res = await chunk5ABTBPPK_js.sonorFetch(
|
|
432
432
|
`${config.apiUrl}/public/images/slot/${encodeURIComponent(slotId)}?${params}`,
|
|
433
433
|
{ headers: { "Content-Type": "application/json" } },
|
|
434
434
|
{ apiKey: config.apiKey }
|
|
@@ -443,7 +443,7 @@ async function fetchManagedImages(config, options) {
|
|
|
443
443
|
if (options?.pagePath) params.set("page_path", options.pagePath);
|
|
444
444
|
if (options?.category) params.set("category", options.category);
|
|
445
445
|
if (options?.includePlaceholders) params.set("include_placeholders", "true");
|
|
446
|
-
const res = await
|
|
446
|
+
const res = await chunk5ABTBPPK_js.sonorFetch(
|
|
447
447
|
`${config.apiUrl}/public/images?${params}`,
|
|
448
448
|
{ headers: { "Content-Type": "application/json" } },
|
|
449
449
|
{ apiKey: config.apiKey }
|
|
@@ -457,7 +457,7 @@ async function listImageFiles(config, options) {
|
|
|
457
457
|
const params = new URLSearchParams();
|
|
458
458
|
if (options?.folder) params.set("folder", options.folder);
|
|
459
459
|
if (options?.search) params.set("search", options.search);
|
|
460
|
-
const res = await
|
|
460
|
+
const res = await chunk5ABTBPPK_js.sonorFetch(
|
|
461
461
|
`${config.apiUrl}/public/images/files?${params}`,
|
|
462
462
|
{ headers: { "Content-Type": "application/json" } },
|
|
463
463
|
{ apiKey: config.apiKey }
|
|
@@ -474,7 +474,7 @@ async function uploadImage(config, file, options) {
|
|
|
474
474
|
if (options?.pagePath) formData.append("page_path", options.pagePath);
|
|
475
475
|
if (options?.folder) formData.append("folder", options.folder);
|
|
476
476
|
if (options?.altText) formData.append("alt_text", options.altText);
|
|
477
|
-
const res = await
|
|
477
|
+
const res = await chunk5ABTBPPK_js.sonorFetch(`${config.apiUrl}/public/images/upload`, {
|
|
478
478
|
method: "POST",
|
|
479
479
|
body: formData
|
|
480
480
|
}, { apiKey: config.apiKey, retries: 0, timeoutMs: 6e4 });
|
|
@@ -484,7 +484,7 @@ async function uploadImage(config, file, options) {
|
|
|
484
484
|
return res.json();
|
|
485
485
|
}
|
|
486
486
|
async function assignImageToSlot(config, slotId, options) {
|
|
487
|
-
const res = await
|
|
487
|
+
const res = await chunk5ABTBPPK_js.sonorFetch(
|
|
488
488
|
`${config.apiUrl}/public/images/slot/${encodeURIComponent(slotId)}`,
|
|
489
489
|
{
|
|
490
490
|
method: "POST",
|
|
@@ -511,7 +511,7 @@ async function assignImageToSlot(config, slotId, options) {
|
|
|
511
511
|
async function clearImageSlot(config, slotId, pagePath) {
|
|
512
512
|
const params = new URLSearchParams();
|
|
513
513
|
if (pagePath) params.set("page_path", pagePath);
|
|
514
|
-
const res = await
|
|
514
|
+
const res = await chunk5ABTBPPK_js.sonorFetch(
|
|
515
515
|
`${config.apiUrl}/public/images/slot/${encodeURIComponent(slotId)}?${params}`,
|
|
516
516
|
{ method: "DELETE" },
|
|
517
517
|
{ apiKey: config.apiKey, retries: 0 }
|
|
@@ -529,5 +529,5 @@ exports.fetchManagedImage = fetchManagedImage;
|
|
|
529
529
|
exports.fetchManagedImages = fetchManagedImages;
|
|
530
530
|
exports.listImageFiles = listImageFiles;
|
|
531
531
|
exports.uploadImage = uploadImage;
|
|
532
|
-
//# sourceMappingURL=chunk-
|
|
533
|
-
//# sourceMappingURL=chunk-
|
|
532
|
+
//# sourceMappingURL=chunk-P2HOVWJW.js.map
|
|
533
|
+
//# sourceMappingURL=chunk-P2HOVWJW.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/images/ManagedImage.tsx","../src/images/api.ts"],"names":["useState","useCallback","sonorFetch","useEffect","jsx","jsxs"],"mappings":"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","file":"chunk-2TS4ALOA.js","sourcesContent":["/**\n * ManagedImage - Portal-managed image component\n * \n * Features:\n * - Fetches images from Portal API via API key (never direct Supabase)\n * - Dev mode: Click to open image picker modal\n * - Supports responsive variants\n * - Automatic focal point handling\n * - Placeholder state for empty slots\n * \n * @example\n * ```tsx\n * <ManagedImage \n * slotId=\"hero-background\"\n * alt=\"Hero background image\"\n * className=\"w-full h-96 object-cover\"\n * />\n * ```\n */\n\n'use client'\n\nimport React, { useState, useEffect, useCallback } from 'react'\nimport { sonorFetch } from '../shared/sonorFetch'\n\nexport interface ManagedImageData {\n id: string\n slot_id: string\n page_path: string | null\n file_id: string | null\n external_url: string | null\n alt_text: string | null\n title: string | null\n caption: string | null\n focal_point_x: number\n focal_point_y: number\n aspect_ratio: string | null\n public_url?: string\n is_placeholder: boolean\n}\n\nexport interface ImageFile {\n id: string\n filename: string\n storage_path: string\n mime_type: string\n file_size: number\n folder_path: string | null\n public_url?: string\n}\n\nexport interface ManagedImageProps {\n /** API key for Portal API */\n apiKey?: string\n /** API URL (defaults to https://api.sonor.io) */\n apiUrl?: string\n /** Unique slot identifier (e.g., 'hero-background', 'about-team-1') */\n slotId: string\n /** Page path for page-specific slots (defaults to current path) */\n pagePath?: string\n /** Fallback alt text if not set in Portal */\n alt?: string\n /** CSS class names */\n className?: string\n /** Image width */\n width?: number | string\n /** Image height */\n height?: number | string\n /** CSS object-fit property */\n objectFit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'\n /** Fallback image URL when no image assigned */\n fallback?: string\n /** Custom placeholder component */\n placeholder?: React.ReactNode\n /** Called when image loads */\n onLoad?: () => void\n /** Called on error */\n onError?: (error: Error) => void\n /** Priority loading (Next.js Image optimization) */\n priority?: boolean\n /** Additional styles */\n style?: React.CSSProperties\n /** Enable dev picker even outside dev mode */\n forceDevMode?: boolean\n}\n\n// Check if we're in dev mode. `?sonor_dev=true` opens the picker on any host.\n// (The Uptrade-era `uptrade_dev` param is gone: nothing in the workspace sent it.)\nconst isDevMode = (): boolean => {\n if (typeof window === 'undefined') return false\n return (\n process.env.NODE_ENV === 'development' ||\n window.location.hostname === 'localhost' ||\n window.location.hostname === '127.0.0.1' ||\n new URLSearchParams(window.location.search).get('sonor_dev') === 'true'\n )\n}\n\nexport function ManagedImage({\n apiKey = process.env.SONOR_API_KEY,\n apiUrl = process.env.SONOR_API_URL || 'https://api.sonor.io',\n slotId,\n pagePath,\n alt,\n className = '',\n width,\n height,\n objectFit = 'cover',\n fallback,\n placeholder,\n onLoad,\n onError,\n priority,\n style,\n forceDevMode,\n}: ManagedImageProps) {\n const [imageData, setImageData] = useState<ManagedImageData | null>(null)\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<Error | null>(null)\n const [showPicker, setShowPicker] = useState(false)\n const [devMode] = useState(() => forceDevMode || isDevMode())\n\n // Get current page path if not provided\n const currentPath = pagePath ?? (typeof window !== 'undefined' ? window.location.pathname : '/')\n\n // Fetch image data from Portal API\n const fetchImage = useCallback(async () => {\n if (!apiKey || !apiUrl) {\n setLoading(false)\n return\n }\n\n try {\n const params = new URLSearchParams({ page_path: currentPath })\n const res = await sonorFetch(\n `${apiUrl}/public/images/slot/${encodeURIComponent(slotId)}?${params}`,\n { headers: { 'Content-Type': 'application/json' } },\n { apiKey },\n )\n\n if (!res.ok) {\n throw new Error(`Failed to fetch image: ${res.status}`)\n }\n\n const data = await res.json()\n setImageData(data.image)\n setError(null)\n } catch (err) {\n // warn, not error: a failed slot fetch must not fail the Lighthouse\n // best-practices errors-in-console audit on every page using this slot.\n console.warn('[ManagedImage] Fetch error:', err)\n setError(err instanceof Error ? err : new Error(String(err)))\n onError?.(err instanceof Error ? err : new Error(String(err)))\n } finally {\n setLoading(false)\n }\n }, [apiKey, apiUrl, slotId, currentPath, onError])\n\n useEffect(() => {\n fetchImage()\n }, [fetchImage])\n\n // Calculate object-position from focal point\n const objectPosition = imageData\n ? `${imageData.focal_point_x}% ${imageData.focal_point_y}%`\n : '50% 50%'\n\n // Get the image URL\n const imageUrl = imageData?.public_url || imageData?.external_url || fallback\n\n // Handle click in dev mode\n const handleClick = (e: React.MouseEvent) => {\n if (devMode) {\n e.preventDefault()\n e.stopPropagation()\n setShowPicker(true)\n }\n }\n\n // Render placeholder state\n if (loading) {\n return (\n <div\n className={`bg-gray-200 animate-pulse ${className}`}\n style={{\n width: width ?? '100%',\n height: height ?? 200,\n ...style,\n }}\n />\n )\n }\n\n // No image assigned - show placeholder or dev picker hint\n if (!imageUrl) {\n if (placeholder) {\n return <>{placeholder}</>\n }\n\n return (\n <div\n onClick={handleClick}\n className={`\n bg-gray-100 border-2 border-dashed border-gray-300 \n flex items-center justify-center text-gray-400\n ${devMode ? 'cursor-pointer hover:border-blue-400 hover:text-blue-500 hover:bg-blue-50' : ''}\n ${className}\n `}\n style={{\n width: width ?? '100%',\n height: height ?? 200,\n ...style,\n }}\n title={devMode ? `Click to add image for slot: ${slotId}` : undefined}\n >\n <div className=\"text-center p-4\">\n <svg\n className=\"w-12 h-12 mx-auto mb-2\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.5}\n d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\"\n />\n </svg>\n {devMode && (\n <p className=\"text-sm font-medium\">Click to add image</p>\n )}\n <p className=\"text-xs mt-1\">{slotId}</p>\n </div>\n\n {showPicker && (\n <ImagePickerModal\n slotId={slotId}\n pagePath={currentPath}\n config={{ apiKey, apiUrl }}\n onClose={() => setShowPicker(false)}\n onSelect={() => {\n setShowPicker(false)\n fetchImage()\n }}\n />\n )}\n </div>\n )\n }\n\n // Render the image\n return (\n <div className=\"relative\" style={{ width, height }}>\n <img\n src={imageUrl}\n alt={imageData?.alt_text || alt || ''}\n title={imageData?.title || undefined}\n data-managed-image=\"true\"\n data-slot-id={slotId}\n data-page-path={currentPath}\n className={className}\n style={{\n objectFit,\n objectPosition,\n width: width ?? '100%',\n height: height ?? 'auto',\n ...style,\n }}\n onLoad={onLoad}\n onError={() => onError?.(new Error('Image failed to load'))}\n loading={priority ? 'eager' : 'lazy'}\n onClick={handleClick}\n />\n\n {/* Dev mode overlay */}\n {devMode && (\n <div\n className=\"absolute inset-0 bg-black/0 hover:bg-black/30 transition-colors cursor-pointer flex items-center justify-center opacity-0 hover:opacity-100\"\n onClick={handleClick}\n >\n <div className=\"bg-white/90 px-3 py-1.5 rounded-lg shadow-lg text-sm font-medium text-gray-700\">\n Edit Image\n </div>\n </div>\n )}\n\n {showPicker && (\n <ImagePickerModal\n slotId={slotId}\n pagePath={currentPath}\n config={{ apiKey, apiUrl }}\n currentImage={imageData}\n onClose={() => setShowPicker(false)}\n onSelect={() => {\n setShowPicker(false)\n fetchImage()\n }}\n />\n )}\n </div>\n )\n}\n\n// ============================================================================\n// IMAGE PICKER MODAL\n// ============================================================================\n\ninterface ImagePickerModalProps {\n slotId: string\n pagePath: string\n config: any\n currentImage?: ManagedImageData | null\n onClose: () => void\n onSelect: () => void\n}\n\nfunction ImagePickerModal({\n slotId,\n pagePath,\n config,\n currentImage,\n onClose,\n onSelect,\n}: ImagePickerModalProps) {\n const [files, setFiles] = useState<ImageFile[]>([])\n const [folders, setFolders] = useState<string[]>([])\n const [currentFolder, setCurrentFolder] = useState<string>('')\n const [search, setSearch] = useState('')\n const [loading, setLoading] = useState(true)\n const [uploading, setUploading] = useState(false)\n const [altText, setAltText] = useState(currentImage?.alt_text || '')\n\n // Fetch available files\n const fetchFiles = useCallback(async () => {\n if (!config?.apiKey || !config?.apiUrl) return\n\n setLoading(true)\n try {\n const params = new URLSearchParams()\n if (currentFolder) params.set('folder', currentFolder)\n if (search) params.set('search', search)\n\n const res = await sonorFetch(\n `${config.apiUrl}/public/images/files?${params}`,\n { headers: { 'Content-Type': 'application/json' } },\n { apiKey: config.apiKey },\n )\n\n if (res.ok) {\n const data = await res.json()\n setFiles(data.files || [])\n setFolders(data.folders || [])\n }\n } catch (err) {\n console.warn('[ImagePicker] Fetch error:', err)\n } finally {\n setLoading(false)\n }\n }, [config?.apiKey, config?.apiUrl, currentFolder, search])\n\n useEffect(() => {\n fetchFiles()\n }, [fetchFiles])\n\n // Select an existing file\n const handleSelectFile = async (file: ImageFile) => {\n if (!config?.apiKey || !config?.apiUrl) return\n\n try {\n const res = await sonorFetch(\n `${config.apiUrl}/public/images/slot/${encodeURIComponent(slotId)}`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n page_path: pagePath,\n file_id: file.id,\n alt_text: altText || file.filename,\n }),\n },\n { apiKey: config.apiKey, retries: 0 },\n )\n\n if (res.ok) {\n onSelect()\n }\n } catch (err) {\n console.warn('[ImagePicker] Select error:', err)\n }\n }\n\n // Upload new file\n const handleUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0]\n if (!file || !config?.apiKey || !config?.apiUrl) return\n\n setUploading(true)\n try {\n const formData = new FormData()\n formData.append('file', file)\n formData.append('slot_id', slotId)\n formData.append('page_path', pagePath)\n formData.append('folder', currentFolder || 'Website/Images')\n if (altText) formData.append('alt_text', altText)\n\n // No Content-Type — the browser sets the multipart boundary. Long\n // timeout, no retry: a retried upload would duplicate the file.\n const res = await sonorFetch(`${config.apiUrl}/public/images/upload`, {\n method: 'POST',\n body: formData,\n }, { apiKey: config.apiKey, retries: 0, timeoutMs: 60000 })\n\n if (res.ok) {\n onSelect()\n }\n } catch (err) {\n console.warn('[ImagePicker] Upload error:', err)\n } finally {\n setUploading(false)\n }\n }\n\n // Clear the slot\n const handleClear = async () => {\n if (!config?.apiKey || !config?.apiUrl) return\n\n try {\n const params = new URLSearchParams({ page_path: pagePath })\n await sonorFetch(\n `${config.apiUrl}/public/images/slot/${encodeURIComponent(slotId)}?${params}`,\n { method: 'DELETE' },\n { apiKey: config.apiKey, retries: 0 },\n )\n onSelect()\n } catch (err) {\n console.warn('[ImagePicker] Clear error:', err)\n }\n }\n\n return (\n <div\n className=\"fixed inset-0 z-[99999] bg-black/50 flex items-center justify-center p-4\"\n onClick={onClose}\n >\n <div\n className=\"bg-white rounded-xl shadow-2xl max-w-4xl w-full max-h-[90vh] overflow-hidden\"\n onClick={(e) => e.stopPropagation()}\n >\n {/* Header */}\n <div className=\"flex items-center justify-between p-4 border-b\">\n <div>\n <h2 className=\"text-lg font-semibold\">Select Image</h2>\n <p className=\"text-sm text-gray-500\">Slot: {slotId}</p>\n </div>\n <button\n onClick={onClose}\n className=\"text-gray-400 hover:text-gray-600 p-2\"\n >\n <svg className=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n\n {/* Body */}\n <div className=\"p-4 overflow-y-auto\" style={{ maxHeight: 'calc(90vh - 180px)' }}>\n {/* Upload & Search */}\n <div className=\"flex gap-4 mb-4\">\n <div className=\"flex-1\">\n <input\n type=\"text\"\n placeholder=\"Search images...\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n className=\"w-full px-3 py-2 border rounded-lg text-sm\"\n />\n </div>\n <label className=\"px-4 py-2 bg-blue-600 text-white rounded-lg cursor-pointer hover:bg-blue-700 text-sm font-medium flex items-center gap-2\">\n {uploading ? 'Uploading...' : 'Upload New'}\n <input\n type=\"file\"\n accept=\"image/*\"\n onChange={handleUpload}\n disabled={uploading}\n className=\"hidden\"\n />\n </label>\n {currentImage?.file_id && (\n <button\n onClick={handleClear}\n className=\"px-4 py-2 border border-red-200 text-red-600 rounded-lg hover:bg-red-50 text-sm\"\n >\n Remove\n </button>\n )}\n </div>\n\n {/* Alt text input */}\n <div className=\"mb-4\">\n <input\n type=\"text\"\n placeholder=\"Alt text for image...\"\n value={altText}\n onChange={(e) => setAltText(e.target.value)}\n className=\"w-full px-3 py-2 border rounded-lg text-sm\"\n />\n </div>\n\n {/* Folder navigation */}\n {folders.length > 0 && (\n <div className=\"flex gap-2 mb-4 flex-wrap\">\n <button\n onClick={() => setCurrentFolder('')}\n className={`px-3 py-1 text-sm rounded-full ${\n !currentFolder ? 'bg-blue-100 text-blue-700' : 'bg-gray-100 hover:bg-gray-200'\n }`}\n >\n All\n </button>\n {folders.map((folder) => (\n <button\n key={folder}\n onClick={() => setCurrentFolder(folder)}\n className={`px-3 py-1 text-sm rounded-full ${\n currentFolder === folder ? 'bg-blue-100 text-blue-700' : 'bg-gray-100 hover:bg-gray-200'\n }`}\n >\n {folder}\n </button>\n ))}\n </div>\n )}\n\n {/* File grid */}\n {loading ? (\n <div className=\"grid grid-cols-4 gap-4\">\n {[...Array(8)].map((_, i) => (\n <div key={i} className=\"aspect-square bg-gray-200 rounded-lg animate-pulse\" />\n ))}\n </div>\n ) : files.length === 0 ? (\n <div className=\"text-center py-12 text-gray-500\">\n <p>No images found</p>\n <p className=\"text-sm mt-1\">Upload a new image to get started</p>\n </div>\n ) : (\n <div className=\"grid grid-cols-4 gap-4\">\n {files.map((file) => (\n <button\n key={file.id}\n onClick={() => handleSelectFile(file)}\n className={`\n aspect-square rounded-lg overflow-hidden border-2 transition-all\n hover:border-blue-400 hover:shadow-lg\n ${currentImage?.file_id === file.id ? 'border-blue-500 ring-2 ring-blue-200' : 'border-gray-200'}\n `}\n >\n <img\n src={file.public_url}\n alt={file.filename}\n className=\"w-full h-full object-cover\"\n />\n </button>\n ))}\n </div>\n )}\n </div>\n\n {/* Footer */}\n <div className=\"p-4 border-t bg-gray-50 flex justify-end\">\n <button\n onClick={onClose}\n className=\"px-4 py-2 text-gray-700 hover:bg-gray-100 rounded-lg text-sm\"\n >\n Cancel\n </button>\n </div>\n </div>\n </div>\n )\n}\n\nexport default ManagedImage\n","/**\n * Images API functions\n * \n * All functions use Portal API with API key authentication.\n * Never makes direct Supabase calls.\n */\n\nimport type { ManagedImageData, ImageFile } from './ManagedImage'\nimport { sonorFetch } from '../shared/sonorFetch'\n\nexport interface ImageApiConfig {\n apiUrl: string\n apiKey: string\n}\n\n/**\n * Fetch a managed image for a specific slot\n */\nexport async function fetchManagedImage(\n config: ImageApiConfig,\n slotId: string,\n pagePath?: string,\n): Promise<{ image: ManagedImageData | null; is_placeholder: boolean }> {\n const params = new URLSearchParams()\n if (pagePath) params.set('page_path', pagePath)\n\n const res = await sonorFetch(\n `${config.apiUrl}/public/images/slot/${encodeURIComponent(slotId)}?${params}`,\n { headers: { 'Content-Type': 'application/json' } },\n { apiKey: config.apiKey },\n )\n\n if (!res.ok) {\n throw new Error(`Failed to fetch image: ${res.status}`)\n }\n\n return res.json()\n}\n\n/**\n * Fetch all managed images for the project\n */\nexport async function fetchManagedImages(\n config: ImageApiConfig,\n options?: {\n pagePath?: string\n category?: string\n includePlaceholders?: boolean\n },\n): Promise<{ images: ManagedImageData[] }> {\n const params = new URLSearchParams()\n if (options?.pagePath) params.set('page_path', options.pagePath)\n if (options?.category) params.set('category', options.category)\n if (options?.includePlaceholders) params.set('include_placeholders', 'true')\n\n const res = await sonorFetch(\n `${config.apiUrl}/public/images?${params}`,\n { headers: { 'Content-Type': 'application/json' } },\n { apiKey: config.apiKey },\n )\n\n if (!res.ok) {\n throw new Error(`Failed to fetch images: ${res.status}`)\n }\n\n return res.json()\n}\n\n/**\n * List available image files in the project\n */\nexport async function listImageFiles(\n config: ImageApiConfig,\n options?: {\n folder?: string\n search?: string\n },\n): Promise<{ files: ImageFile[]; folders: string[] }> {\n const params = new URLSearchParams()\n if (options?.folder) params.set('folder', options.folder)\n if (options?.search) params.set('search', options.search)\n\n const res = await sonorFetch(\n `${config.apiUrl}/public/images/files?${params}`,\n { headers: { 'Content-Type': 'application/json' } },\n { apiKey: config.apiKey },\n )\n\n if (!res.ok) {\n throw new Error(`Failed to list files: ${res.status}`)\n }\n\n return res.json()\n}\n\n/**\n * Upload a new image\n */\nexport async function uploadImage(\n config: ImageApiConfig,\n file: File,\n options?: {\n slotId?: string\n pagePath?: string\n folder?: string\n altText?: string\n },\n): Promise<{ file: ImageFile; image?: ManagedImageData }> {\n const formData = new FormData()\n formData.append('file', file)\n if (options?.slotId) formData.append('slot_id', options.slotId)\n if (options?.pagePath) formData.append('page_path', options.pagePath)\n if (options?.folder) formData.append('folder', options.folder)\n if (options?.altText) formData.append('alt_text', options.altText)\n\n // No Content-Type — the browser sets the multipart boundary. Long timeout,\n // no retry: a retried upload would duplicate the file.\n const res = await sonorFetch(`${config.apiUrl}/public/images/upload`, {\n method: 'POST',\n body: formData,\n }, { apiKey: config.apiKey, retries: 0, timeoutMs: 60000 })\n\n if (!res.ok) {\n throw new Error(`Failed to upload image: ${res.status}`)\n }\n\n return res.json()\n}\n\n/**\n * Assign an existing file to an image slot\n */\nexport async function assignImageToSlot(\n config: ImageApiConfig,\n slotId: string,\n options: {\n fileId?: string\n externalUrl?: string\n pagePath?: string\n altText?: string\n title?: string\n caption?: string\n focalPointX?: number\n focalPointY?: number\n aspectRatio?: string\n },\n): Promise<{ image: ManagedImageData }> {\n const res = await sonorFetch(\n `${config.apiUrl}/public/images/slot/${encodeURIComponent(slotId)}`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n page_path: options.pagePath,\n file_id: options.fileId,\n external_url: options.externalUrl,\n alt_text: options.altText,\n title: options.title,\n caption: options.caption,\n focal_point_x: options.focalPointX,\n focal_point_y: options.focalPointY,\n aspect_ratio: options.aspectRatio,\n }),\n },\n { apiKey: config.apiKey, retries: 0 },\n )\n\n if (!res.ok) {\n throw new Error(`Failed to assign image: ${res.status}`)\n }\n\n return res.json()\n}\n\n/**\n * Clear an image from a slot (keeps the file)\n */\nexport async function clearImageSlot(\n config: ImageApiConfig,\n slotId: string,\n pagePath?: string,\n): Promise<{ success: boolean }> {\n const params = new URLSearchParams()\n if (pagePath) params.set('page_path', pagePath)\n\n const res = await sonorFetch(\n `${config.apiUrl}/public/images/slot/${encodeURIComponent(slotId)}?${params}`,\n { method: 'DELETE' },\n { apiKey: config.apiKey, retries: 0 },\n )\n\n if (!res.ok) {\n throw new Error(`Failed to clear slot: ${res.status}`)\n }\n\n return res.json()\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/images/ManagedImage.tsx","../src/images/api.ts"],"names":["useState","useCallback","sonorFetch","useEffect","jsx","jsxs"],"mappings":"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","file":"chunk-P2HOVWJW.js","sourcesContent":["/**\n * ManagedImage - Portal-managed image component\n * \n * Features:\n * - Fetches images from Portal API via API key (never direct Supabase)\n * - Dev mode: Click to open image picker modal\n * - Supports responsive variants\n * - Automatic focal point handling\n * - Placeholder state for empty slots\n * \n * @example\n * ```tsx\n * <ManagedImage \n * slotId=\"hero-background\"\n * alt=\"Hero background image\"\n * className=\"w-full h-96 object-cover\"\n * />\n * ```\n */\n\n'use client'\n\nimport React, { useState, useEffect, useCallback } from 'react'\nimport { sonorFetch } from '../shared/sonorFetch'\n\nexport interface ManagedImageData {\n id: string\n slot_id: string\n page_path: string | null\n file_id: string | null\n external_url: string | null\n alt_text: string | null\n title: string | null\n caption: string | null\n focal_point_x: number\n focal_point_y: number\n aspect_ratio: string | null\n public_url?: string\n is_placeholder: boolean\n}\n\nexport interface ImageFile {\n id: string\n filename: string\n storage_path: string\n mime_type: string\n file_size: number\n folder_path: string | null\n public_url?: string\n}\n\nexport interface ManagedImageProps {\n /** API key for Portal API */\n apiKey?: string\n /** API URL (defaults to https://api.sonor.io) */\n apiUrl?: string\n /** Unique slot identifier (e.g., 'hero-background', 'about-team-1') */\n slotId: string\n /** Page path for page-specific slots (defaults to current path) */\n pagePath?: string\n /** Fallback alt text if not set in Portal */\n alt?: string\n /** CSS class names */\n className?: string\n /** Image width */\n width?: number | string\n /** Image height */\n height?: number | string\n /** CSS object-fit property */\n objectFit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'\n /** Fallback image URL when no image assigned */\n fallback?: string\n /** Custom placeholder component */\n placeholder?: React.ReactNode\n /** Called when image loads */\n onLoad?: () => void\n /** Called on error */\n onError?: (error: Error) => void\n /** Priority loading (Next.js Image optimization) */\n priority?: boolean\n /** Additional styles */\n style?: React.CSSProperties\n /** Enable dev picker even outside dev mode */\n forceDevMode?: boolean\n}\n\n// Check if we're in dev mode. `?sonor_dev=true` opens the picker on any host.\n// (The Uptrade-era `uptrade_dev` param is gone: nothing in the workspace sent it.)\nconst isDevMode = (): boolean => {\n if (typeof window === 'undefined') return false\n return (\n process.env.NODE_ENV === 'development' ||\n window.location.hostname === 'localhost' ||\n window.location.hostname === '127.0.0.1' ||\n new URLSearchParams(window.location.search).get('sonor_dev') === 'true'\n )\n}\n\nexport function ManagedImage({\n apiKey = process.env.SONOR_API_KEY,\n apiUrl = process.env.SONOR_API_URL || 'https://api.sonor.io',\n slotId,\n pagePath,\n alt,\n className = '',\n width,\n height,\n objectFit = 'cover',\n fallback,\n placeholder,\n onLoad,\n onError,\n priority,\n style,\n forceDevMode,\n}: ManagedImageProps) {\n const [imageData, setImageData] = useState<ManagedImageData | null>(null)\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<Error | null>(null)\n const [showPicker, setShowPicker] = useState(false)\n const [devMode] = useState(() => forceDevMode || isDevMode())\n\n // Get current page path if not provided\n const currentPath = pagePath ?? (typeof window !== 'undefined' ? window.location.pathname : '/')\n\n // Fetch image data from Portal API\n const fetchImage = useCallback(async () => {\n if (!apiKey || !apiUrl) {\n setLoading(false)\n return\n }\n\n try {\n const params = new URLSearchParams({ page_path: currentPath })\n const res = await sonorFetch(\n `${apiUrl}/public/images/slot/${encodeURIComponent(slotId)}?${params}`,\n { headers: { 'Content-Type': 'application/json' } },\n { apiKey },\n )\n\n if (!res.ok) {\n throw new Error(`Failed to fetch image: ${res.status}`)\n }\n\n const data = await res.json()\n setImageData(data.image)\n setError(null)\n } catch (err) {\n // warn, not error: a failed slot fetch must not fail the Lighthouse\n // best-practices errors-in-console audit on every page using this slot.\n console.warn('[ManagedImage] Fetch error:', err)\n setError(err instanceof Error ? err : new Error(String(err)))\n onError?.(err instanceof Error ? err : new Error(String(err)))\n } finally {\n setLoading(false)\n }\n }, [apiKey, apiUrl, slotId, currentPath, onError])\n\n useEffect(() => {\n fetchImage()\n }, [fetchImage])\n\n // Calculate object-position from focal point\n const objectPosition = imageData\n ? `${imageData.focal_point_x}% ${imageData.focal_point_y}%`\n : '50% 50%'\n\n // Get the image URL\n const imageUrl = imageData?.public_url || imageData?.external_url || fallback\n\n // Handle click in dev mode\n const handleClick = (e: React.MouseEvent) => {\n if (devMode) {\n e.preventDefault()\n e.stopPropagation()\n setShowPicker(true)\n }\n }\n\n // Render placeholder state\n if (loading) {\n return (\n <div\n className={`bg-gray-200 animate-pulse ${className}`}\n style={{\n width: width ?? '100%',\n height: height ?? 200,\n ...style,\n }}\n />\n )\n }\n\n // No image assigned - show placeholder or dev picker hint\n if (!imageUrl) {\n if (placeholder) {\n return <>{placeholder}</>\n }\n\n return (\n <div\n onClick={handleClick}\n className={`\n bg-gray-100 border-2 border-dashed border-gray-300 \n flex items-center justify-center text-gray-400\n ${devMode ? 'cursor-pointer hover:border-blue-400 hover:text-blue-500 hover:bg-blue-50' : ''}\n ${className}\n `}\n style={{\n width: width ?? '100%',\n height: height ?? 200,\n ...style,\n }}\n title={devMode ? `Click to add image for slot: ${slotId}` : undefined}\n >\n <div className=\"text-center p-4\">\n <svg\n className=\"w-12 h-12 mx-auto mb-2\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.5}\n d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\"\n />\n </svg>\n {devMode && (\n <p className=\"text-sm font-medium\">Click to add image</p>\n )}\n <p className=\"text-xs mt-1\">{slotId}</p>\n </div>\n\n {showPicker && (\n <ImagePickerModal\n slotId={slotId}\n pagePath={currentPath}\n config={{ apiKey, apiUrl }}\n onClose={() => setShowPicker(false)}\n onSelect={() => {\n setShowPicker(false)\n fetchImage()\n }}\n />\n )}\n </div>\n )\n }\n\n // Render the image\n return (\n <div className=\"relative\" style={{ width, height }}>\n <img\n src={imageUrl}\n alt={imageData?.alt_text || alt || ''}\n title={imageData?.title || undefined}\n data-managed-image=\"true\"\n data-slot-id={slotId}\n data-page-path={currentPath}\n className={className}\n style={{\n objectFit,\n objectPosition,\n width: width ?? '100%',\n height: height ?? 'auto',\n ...style,\n }}\n onLoad={onLoad}\n onError={() => onError?.(new Error('Image failed to load'))}\n loading={priority ? 'eager' : 'lazy'}\n onClick={handleClick}\n />\n\n {/* Dev mode overlay */}\n {devMode && (\n <div\n className=\"absolute inset-0 bg-black/0 hover:bg-black/30 transition-colors cursor-pointer flex items-center justify-center opacity-0 hover:opacity-100\"\n onClick={handleClick}\n >\n <div className=\"bg-white/90 px-3 py-1.5 rounded-lg shadow-lg text-sm font-medium text-gray-700\">\n Edit Image\n </div>\n </div>\n )}\n\n {showPicker && (\n <ImagePickerModal\n slotId={slotId}\n pagePath={currentPath}\n config={{ apiKey, apiUrl }}\n currentImage={imageData}\n onClose={() => setShowPicker(false)}\n onSelect={() => {\n setShowPicker(false)\n fetchImage()\n }}\n />\n )}\n </div>\n )\n}\n\n// ============================================================================\n// IMAGE PICKER MODAL\n// ============================================================================\n\ninterface ImagePickerModalProps {\n slotId: string\n pagePath: string\n config: any\n currentImage?: ManagedImageData | null\n onClose: () => void\n onSelect: () => void\n}\n\nfunction ImagePickerModal({\n slotId,\n pagePath,\n config,\n currentImage,\n onClose,\n onSelect,\n}: ImagePickerModalProps) {\n const [files, setFiles] = useState<ImageFile[]>([])\n const [folders, setFolders] = useState<string[]>([])\n const [currentFolder, setCurrentFolder] = useState<string>('')\n const [search, setSearch] = useState('')\n const [loading, setLoading] = useState(true)\n const [uploading, setUploading] = useState(false)\n const [altText, setAltText] = useState(currentImage?.alt_text || '')\n\n // Fetch available files\n const fetchFiles = useCallback(async () => {\n if (!config?.apiKey || !config?.apiUrl) return\n\n setLoading(true)\n try {\n const params = new URLSearchParams()\n if (currentFolder) params.set('folder', currentFolder)\n if (search) params.set('search', search)\n\n const res = await sonorFetch(\n `${config.apiUrl}/public/images/files?${params}`,\n { headers: { 'Content-Type': 'application/json' } },\n { apiKey: config.apiKey },\n )\n\n if (res.ok) {\n const data = await res.json()\n setFiles(data.files || [])\n setFolders(data.folders || [])\n }\n } catch (err) {\n console.warn('[ImagePicker] Fetch error:', err)\n } finally {\n setLoading(false)\n }\n }, [config?.apiKey, config?.apiUrl, currentFolder, search])\n\n useEffect(() => {\n fetchFiles()\n }, [fetchFiles])\n\n // Select an existing file\n const handleSelectFile = async (file: ImageFile) => {\n if (!config?.apiKey || !config?.apiUrl) return\n\n try {\n const res = await sonorFetch(\n `${config.apiUrl}/public/images/slot/${encodeURIComponent(slotId)}`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n page_path: pagePath,\n file_id: file.id,\n alt_text: altText || file.filename,\n }),\n },\n { apiKey: config.apiKey, retries: 0 },\n )\n\n if (res.ok) {\n onSelect()\n }\n } catch (err) {\n console.warn('[ImagePicker] Select error:', err)\n }\n }\n\n // Upload new file\n const handleUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0]\n if (!file || !config?.apiKey || !config?.apiUrl) return\n\n setUploading(true)\n try {\n const formData = new FormData()\n formData.append('file', file)\n formData.append('slot_id', slotId)\n formData.append('page_path', pagePath)\n formData.append('folder', currentFolder || 'Website/Images')\n if (altText) formData.append('alt_text', altText)\n\n // No Content-Type — the browser sets the multipart boundary. Long\n // timeout, no retry: a retried upload would duplicate the file.\n const res = await sonorFetch(`${config.apiUrl}/public/images/upload`, {\n method: 'POST',\n body: formData,\n }, { apiKey: config.apiKey, retries: 0, timeoutMs: 60000 })\n\n if (res.ok) {\n onSelect()\n }\n } catch (err) {\n console.warn('[ImagePicker] Upload error:', err)\n } finally {\n setUploading(false)\n }\n }\n\n // Clear the slot\n const handleClear = async () => {\n if (!config?.apiKey || !config?.apiUrl) return\n\n try {\n const params = new URLSearchParams({ page_path: pagePath })\n await sonorFetch(\n `${config.apiUrl}/public/images/slot/${encodeURIComponent(slotId)}?${params}`,\n { method: 'DELETE' },\n { apiKey: config.apiKey, retries: 0 },\n )\n onSelect()\n } catch (err) {\n console.warn('[ImagePicker] Clear error:', err)\n }\n }\n\n return (\n <div\n className=\"fixed inset-0 z-[99999] bg-black/50 flex items-center justify-center p-4\"\n onClick={onClose}\n >\n <div\n className=\"bg-white rounded-xl shadow-2xl max-w-4xl w-full max-h-[90vh] overflow-hidden\"\n onClick={(e) => e.stopPropagation()}\n >\n {/* Header */}\n <div className=\"flex items-center justify-between p-4 border-b\">\n <div>\n <h2 className=\"text-lg font-semibold\">Select Image</h2>\n <p className=\"text-sm text-gray-500\">Slot: {slotId}</p>\n </div>\n <button\n onClick={onClose}\n className=\"text-gray-400 hover:text-gray-600 p-2\"\n >\n <svg className=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n\n {/* Body */}\n <div className=\"p-4 overflow-y-auto\" style={{ maxHeight: 'calc(90vh - 180px)' }}>\n {/* Upload & Search */}\n <div className=\"flex gap-4 mb-4\">\n <div className=\"flex-1\">\n <input\n type=\"text\"\n placeholder=\"Search images...\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n className=\"w-full px-3 py-2 border rounded-lg text-sm\"\n />\n </div>\n <label className=\"px-4 py-2 bg-blue-600 text-white rounded-lg cursor-pointer hover:bg-blue-700 text-sm font-medium flex items-center gap-2\">\n {uploading ? 'Uploading...' : 'Upload New'}\n <input\n type=\"file\"\n accept=\"image/*\"\n onChange={handleUpload}\n disabled={uploading}\n className=\"hidden\"\n />\n </label>\n {currentImage?.file_id && (\n <button\n onClick={handleClear}\n className=\"px-4 py-2 border border-red-200 text-red-600 rounded-lg hover:bg-red-50 text-sm\"\n >\n Remove\n </button>\n )}\n </div>\n\n {/* Alt text input */}\n <div className=\"mb-4\">\n <input\n type=\"text\"\n placeholder=\"Alt text for image...\"\n value={altText}\n onChange={(e) => setAltText(e.target.value)}\n className=\"w-full px-3 py-2 border rounded-lg text-sm\"\n />\n </div>\n\n {/* Folder navigation */}\n {folders.length > 0 && (\n <div className=\"flex gap-2 mb-4 flex-wrap\">\n <button\n onClick={() => setCurrentFolder('')}\n className={`px-3 py-1 text-sm rounded-full ${\n !currentFolder ? 'bg-blue-100 text-blue-700' : 'bg-gray-100 hover:bg-gray-200'\n }`}\n >\n All\n </button>\n {folders.map((folder) => (\n <button\n key={folder}\n onClick={() => setCurrentFolder(folder)}\n className={`px-3 py-1 text-sm rounded-full ${\n currentFolder === folder ? 'bg-blue-100 text-blue-700' : 'bg-gray-100 hover:bg-gray-200'\n }`}\n >\n {folder}\n </button>\n ))}\n </div>\n )}\n\n {/* File grid */}\n {loading ? (\n <div className=\"grid grid-cols-4 gap-4\">\n {[...Array(8)].map((_, i) => (\n <div key={i} className=\"aspect-square bg-gray-200 rounded-lg animate-pulse\" />\n ))}\n </div>\n ) : files.length === 0 ? (\n <div className=\"text-center py-12 text-gray-500\">\n <p>No images found</p>\n <p className=\"text-sm mt-1\">Upload a new image to get started</p>\n </div>\n ) : (\n <div className=\"grid grid-cols-4 gap-4\">\n {files.map((file) => (\n <button\n key={file.id}\n onClick={() => handleSelectFile(file)}\n className={`\n aspect-square rounded-lg overflow-hidden border-2 transition-all\n hover:border-blue-400 hover:shadow-lg\n ${currentImage?.file_id === file.id ? 'border-blue-500 ring-2 ring-blue-200' : 'border-gray-200'}\n `}\n >\n <img\n src={file.public_url}\n alt={file.filename}\n className=\"w-full h-full object-cover\"\n />\n </button>\n ))}\n </div>\n )}\n </div>\n\n {/* Footer */}\n <div className=\"p-4 border-t bg-gray-50 flex justify-end\">\n <button\n onClick={onClose}\n className=\"px-4 py-2 text-gray-700 hover:bg-gray-100 rounded-lg text-sm\"\n >\n Cancel\n </button>\n </div>\n </div>\n </div>\n )\n}\n\nexport default ManagedImage\n","/**\n * Images API functions\n * \n * All functions use Portal API with API key authentication.\n * Never makes direct Supabase calls.\n */\n\nimport type { ManagedImageData, ImageFile } from './ManagedImage'\nimport { sonorFetch } from '../shared/sonorFetch'\n\nexport interface ImageApiConfig {\n apiUrl: string\n apiKey: string\n}\n\n/**\n * Fetch a managed image for a specific slot\n */\nexport async function fetchManagedImage(\n config: ImageApiConfig,\n slotId: string,\n pagePath?: string,\n): Promise<{ image: ManagedImageData | null; is_placeholder: boolean }> {\n const params = new URLSearchParams()\n if (pagePath) params.set('page_path', pagePath)\n\n const res = await sonorFetch(\n `${config.apiUrl}/public/images/slot/${encodeURIComponent(slotId)}?${params}`,\n { headers: { 'Content-Type': 'application/json' } },\n { apiKey: config.apiKey },\n )\n\n if (!res.ok) {\n throw new Error(`Failed to fetch image: ${res.status}`)\n }\n\n return res.json()\n}\n\n/**\n * Fetch all managed images for the project\n */\nexport async function fetchManagedImages(\n config: ImageApiConfig,\n options?: {\n pagePath?: string\n category?: string\n includePlaceholders?: boolean\n },\n): Promise<{ images: ManagedImageData[] }> {\n const params = new URLSearchParams()\n if (options?.pagePath) params.set('page_path', options.pagePath)\n if (options?.category) params.set('category', options.category)\n if (options?.includePlaceholders) params.set('include_placeholders', 'true')\n\n const res = await sonorFetch(\n `${config.apiUrl}/public/images?${params}`,\n { headers: { 'Content-Type': 'application/json' } },\n { apiKey: config.apiKey },\n )\n\n if (!res.ok) {\n throw new Error(`Failed to fetch images: ${res.status}`)\n }\n\n return res.json()\n}\n\n/**\n * List available image files in the project\n */\nexport async function listImageFiles(\n config: ImageApiConfig,\n options?: {\n folder?: string\n search?: string\n },\n): Promise<{ files: ImageFile[]; folders: string[] }> {\n const params = new URLSearchParams()\n if (options?.folder) params.set('folder', options.folder)\n if (options?.search) params.set('search', options.search)\n\n const res = await sonorFetch(\n `${config.apiUrl}/public/images/files?${params}`,\n { headers: { 'Content-Type': 'application/json' } },\n { apiKey: config.apiKey },\n )\n\n if (!res.ok) {\n throw new Error(`Failed to list files: ${res.status}`)\n }\n\n return res.json()\n}\n\n/**\n * Upload a new image\n */\nexport async function uploadImage(\n config: ImageApiConfig,\n file: File,\n options?: {\n slotId?: string\n pagePath?: string\n folder?: string\n altText?: string\n },\n): Promise<{ file: ImageFile; image?: ManagedImageData }> {\n const formData = new FormData()\n formData.append('file', file)\n if (options?.slotId) formData.append('slot_id', options.slotId)\n if (options?.pagePath) formData.append('page_path', options.pagePath)\n if (options?.folder) formData.append('folder', options.folder)\n if (options?.altText) formData.append('alt_text', options.altText)\n\n // No Content-Type — the browser sets the multipart boundary. Long timeout,\n // no retry: a retried upload would duplicate the file.\n const res = await sonorFetch(`${config.apiUrl}/public/images/upload`, {\n method: 'POST',\n body: formData,\n }, { apiKey: config.apiKey, retries: 0, timeoutMs: 60000 })\n\n if (!res.ok) {\n throw new Error(`Failed to upload image: ${res.status}`)\n }\n\n return res.json()\n}\n\n/**\n * Assign an existing file to an image slot\n */\nexport async function assignImageToSlot(\n config: ImageApiConfig,\n slotId: string,\n options: {\n fileId?: string\n externalUrl?: string\n pagePath?: string\n altText?: string\n title?: string\n caption?: string\n focalPointX?: number\n focalPointY?: number\n aspectRatio?: string\n },\n): Promise<{ image: ManagedImageData }> {\n const res = await sonorFetch(\n `${config.apiUrl}/public/images/slot/${encodeURIComponent(slotId)}`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n page_path: options.pagePath,\n file_id: options.fileId,\n external_url: options.externalUrl,\n alt_text: options.altText,\n title: options.title,\n caption: options.caption,\n focal_point_x: options.focalPointX,\n focal_point_y: options.focalPointY,\n aspect_ratio: options.aspectRatio,\n }),\n },\n { apiKey: config.apiKey, retries: 0 },\n )\n\n if (!res.ok) {\n throw new Error(`Failed to assign image: ${res.status}`)\n }\n\n return res.json()\n}\n\n/**\n * Clear an image from a slot (keeps the file)\n */\nexport async function clearImageSlot(\n config: ImageApiConfig,\n slotId: string,\n pagePath?: string,\n): Promise<{ success: boolean }> {\n const params = new URLSearchParams()\n if (pagePath) params.set('page_path', pagePath)\n\n const res = await sonorFetch(\n `${config.apiUrl}/public/images/slot/${encodeURIComponent(slotId)}?${params}`,\n { method: 'DELETE' },\n { apiKey: config.apiKey, retries: 0 },\n )\n\n if (!res.ok) {\n throw new Error(`Failed to clear slot: ${res.status}`)\n }\n\n return res.json()\n}\n"]}
|
|
@@ -5,7 +5,7 @@ var chunk3DWIYCQX_js = require('./chunk-3DWIYCQX.js');
|
|
|
5
5
|
var chunkRC4WWQXR_js = require('./chunk-RC4WWQXR.js');
|
|
6
6
|
var chunkP4Y75QSU_js = require('./chunk-P4Y75QSU.js');
|
|
7
7
|
var chunk5RNAUYWE_js = require('./chunk-5RNAUYWE.js');
|
|
8
|
-
var
|
|
8
|
+
var chunk5ABTBPPK_js = require('./chunk-5ABTBPPK.js');
|
|
9
9
|
var react = require('react');
|
|
10
10
|
var navigation = require('next/navigation');
|
|
11
11
|
var jsxRuntime = require('react/jsx-runtime');
|
|
@@ -15,7 +15,7 @@ async function analyticsSend(path, body, options = {}) {
|
|
|
15
15
|
const target = chunk5RNAUYWE_js.resolveAnalyticsTarget(options);
|
|
16
16
|
if (!target) return null;
|
|
17
17
|
try {
|
|
18
|
-
return await
|
|
18
|
+
return await chunk5ABTBPPK_js.sonorFetch(
|
|
19
19
|
`${target.apiUrl}${path}`,
|
|
20
20
|
{
|
|
21
21
|
method: options.method || "POST",
|
|
@@ -32,7 +32,7 @@ async function analyticsSend(path, body, options = {}) {
|
|
|
32
32
|
function analyticsBeacon(path, body, options = {}) {
|
|
33
33
|
const target = chunk5RNAUYWE_js.resolveAnalyticsTarget(options);
|
|
34
34
|
if (!target) return;
|
|
35
|
-
|
|
35
|
+
chunk5ABTBPPK_js.sonorBeacon(`${target.apiUrl}${path}`, body, target.apiKey);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
// src/analytics/WebVitals.tsx
|
|
@@ -1018,5 +1018,5 @@ exports.WebVitals = WebVitals;
|
|
|
1018
1018
|
exports.useAnalytics = useAnalytics;
|
|
1019
1019
|
exports.useAnalyticsOptional = useAnalyticsOptional;
|
|
1020
1020
|
exports.useTrackEvent = useTrackEvent;
|
|
1021
|
-
//# sourceMappingURL=chunk-
|
|
1022
|
-
//# sourceMappingURL=chunk-
|
|
1021
|
+
//# sourceMappingURL=chunk-PKZMNDZJ.js.map
|
|
1022
|
+
//# sourceMappingURL=chunk-PKZMNDZJ.js.map
|