@frontlit/page-builder 0.1.0-alpha.1 → 0.1.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/README.md +38 -2
  2. package/dist/blocks/index.d.ts +35 -21
  3. package/dist/blocks/index.js +4 -3
  4. package/dist/builder/index.d.ts +8 -11
  5. package/dist/builder/index.js +7 -5
  6. package/dist/{button-C3VrMJkr.d.ts → button-OLKN3wPf.d.ts} +3 -3
  7. package/dist/{chunk-7W6Q4WA7.js → chunk-36QHCIPM.js} +252 -282
  8. package/dist/chunk-36QHCIPM.js.map +1 -0
  9. package/dist/{chunk-GTY75HW2.js → chunk-ATNM5JHI.js} +2 -2
  10. package/dist/chunk-ATNM5JHI.js.map +1 -0
  11. package/dist/chunk-BBI7UHOA.js +56 -0
  12. package/dist/chunk-BBI7UHOA.js.map +1 -0
  13. package/dist/{chunk-MO76KZY2.js → chunk-GIKTOAQS.js} +661 -423
  14. package/dist/chunk-GIKTOAQS.js.map +1 -0
  15. package/dist/chunk-HWOVSHIW.js +4 -0
  16. package/dist/{chunk-RUYOL7JZ.js.map → chunk-HWOVSHIW.js.map} +1 -1
  17. package/dist/{chunk-SSQWYMQR.js → chunk-IU4KATI2.js} +74 -129
  18. package/dist/chunk-IU4KATI2.js.map +1 -0
  19. package/dist/chunk-J7Z4UW45.js +3418 -0
  20. package/dist/chunk-J7Z4UW45.js.map +1 -0
  21. package/dist/{chunk-7KIX4WAO.js → chunk-K4WCLHMS.js} +1435 -1382
  22. package/dist/chunk-K4WCLHMS.js.map +1 -0
  23. package/dist/chunk-XU7ALPGQ.js +22 -0
  24. package/dist/chunk-XU7ALPGQ.js.map +1 -0
  25. package/dist/components/index.d.ts +33 -8
  26. package/dist/components/index.js +43 -2
  27. package/dist/components/index.js.map +1 -1
  28. package/dist/data-slots.d.ts +3 -3
  29. package/dist/data-slots.js +1 -1
  30. package/dist/fonts/archivo/archivo-latin-variable.woff2 +0 -0
  31. package/dist/fonts/hanken-grotesk/hanken-grotesk-latin-variable.woff2 +0 -0
  32. package/dist/fonts/jetbrains-mono/jetbrains-mono-latin-variable.woff2 +0 -0
  33. package/dist/fonts/spline-sans-mono/spline-sans-mono-latin-variable.woff2 +0 -0
  34. package/dist/heading-DQCxQt38.d.ts +20 -0
  35. package/dist/image-Bk8kPXwP.d.ts +52 -0
  36. package/dist/index.d.ts +18 -11
  37. package/dist/index.js +9 -7
  38. package/dist/media-CnLImjVC.d.ts +21 -0
  39. package/dist/models/index.d.ts +6 -6
  40. package/dist/models/index.js +2 -1
  41. package/dist/{page-DfVl_aHX.d.ts → page-B5Gmm-Ys.d.ts} +2 -3
  42. package/dist/primitives/index.d.ts +287 -61
  43. package/dist/primitives/index.js +2 -1
  44. package/dist/renderer/index.d.ts +12 -8
  45. package/dist/renderer/index.js +6 -4
  46. package/dist/{section-background-BgOCp5l3.d.ts → section-background-6V_LCi5e.d.ts} +1 -1
  47. package/dist/server/index.d.ts +103 -0
  48. package/dist/server/index.js +2649 -0
  49. package/dist/server/index.js.map +1 -0
  50. package/dist/server/islands/code-snippet.d.ts +17 -0
  51. package/dist/server/islands/code-snippet.js +72 -0
  52. package/dist/server/islands/code-snippet.js.map +1 -0
  53. package/dist/server/islands/email-form.d.ts +50 -0
  54. package/dist/server/islands/email-form.js +406 -0
  55. package/dist/server/islands/email-form.js.map +1 -0
  56. package/dist/server/islands/header-mobile-menu.d.ts +22 -0
  57. package/dist/server/islands/header-mobile-menu.js +422 -0
  58. package/dist/server/islands/header-mobile-menu.js.map +1 -0
  59. package/dist/server/islands/inline-embed.d.ts +28 -0
  60. package/dist/server/islands/inline-embed.js +84 -0
  61. package/dist/server/islands/inline-embed.js.map +1 -0
  62. package/dist/server/islands/marquee-track.d.ts +18 -0
  63. package/dist/server/islands/marquee-track.js +67 -0
  64. package/dist/server/islands/marquee-track.js.map +1 -0
  65. package/dist/server/islands/nav-link.d.ts +37 -0
  66. package/dist/server/islands/nav-link.js +67 -0
  67. package/dist/server/islands/nav-link.js.map +1 -0
  68. package/dist/server/islands/support-form.d.ts +17 -0
  69. package/dist/server/islands/support-form.js +469 -0
  70. package/dist/server/islands/support-form.js.map +1 -0
  71. package/dist/server/islands/theme-mode-switcher.d.ts +38 -0
  72. package/dist/server/islands/theme-mode-switcher.js +169 -0
  73. package/dist/server/islands/theme-mode-switcher.js.map +1 -0
  74. package/dist/server/islands/video-with-preview.d.ts +13 -0
  75. package/dist/server/islands/video-with-preview.js +269 -0
  76. package/dist/server/islands/video-with-preview.js.map +1 -0
  77. package/dist/server/primitives.d.ts +200 -0
  78. package/dist/server/primitives.js +888 -0
  79. package/dist/server/primitives.js.map +1 -0
  80. package/dist/server/schema.d.ts +11308 -0
  81. package/dist/server/schema.js +6179 -0
  82. package/dist/server/schema.js.map +1 -0
  83. package/dist/server/theme-CF3fIKvw.d.ts +9 -0
  84. package/dist/{theme-style-39nxXQy0.d.ts → server/theme-style-5_AGy-4V.d.ts} +43 -1
  85. package/dist/server/theme-style-BPaMwk88.d.ts +183 -0
  86. package/dist/server/theme.d.ts +28 -0
  87. package/dist/{chunk-RBJBODQP.js → server/theme.js} +903 -1243
  88. package/dist/server/theme.js.map +1 -0
  89. package/dist/server/widget-YH9BrOwY.d.ts +77 -0
  90. package/dist/styles.css +4016 -8317
  91. package/dist/theme-style-BVd5tOsc.d.ts +183 -0
  92. package/dist/theme.css +186 -191
  93. package/dist/{widget--uEOpdq3.d.ts → widget-CpE2HdgU.d.ts} +25 -18
  94. package/package.json +71 -11
  95. package/schema/page.v1.json +3855 -0
  96. package/schema/site.v1.json +3811 -0
  97. package/dist/alignment-dZDzN96G.d.ts +0 -5
  98. package/dist/chunk-7KIX4WAO.js.map +0 -1
  99. package/dist/chunk-7W6Q4WA7.js.map +0 -1
  100. package/dist/chunk-GTY75HW2.js.map +0 -1
  101. package/dist/chunk-MO76KZY2.js.map +0 -1
  102. package/dist/chunk-RBJBODQP.js.map +0 -1
  103. package/dist/chunk-RUYOL7JZ.js +0 -4
  104. package/dist/chunk-SSQWYMQR.js.map +0 -1
  105. package/dist/fonts/montserrat/montserrat-latin-100-normal.woff2 +0 -0
  106. package/dist/fonts/montserrat/montserrat-latin-200-normal.woff2 +0 -0
  107. package/dist/fonts/montserrat/montserrat-latin-300-normal.woff2 +0 -0
  108. package/dist/fonts/montserrat/montserrat-latin-400-normal.woff2 +0 -0
  109. package/dist/fonts/montserrat/montserrat-latin-500-normal.woff2 +0 -0
  110. package/dist/fonts/montserrat/montserrat-latin-600-normal.woff2 +0 -0
  111. package/dist/fonts/montserrat/montserrat-latin-700-normal.woff2 +0 -0
  112. package/dist/fonts/montserrat/montserrat-latin-800-normal.woff2 +0 -0
  113. package/dist/fonts/montserrat/montserrat-latin-900-normal.woff2 +0 -0
  114. package/dist/fonts/source-sans-3/source-sans-3-latin-400-normal.woff2 +0 -0
  115. package/dist/image-D7GlnOio.d.ts +0 -30
  116. package/dist/media-Njv378j7.d.ts +0 -13
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/image.tsx","../src/components/nav-link.tsx","../src/utils/extract-video-id.ts","../src/components/video-with-preview.tsx","../src/components/inline-embed.tsx"],"names":["jsx","useEffect"],"mappings":";;;;;;;AAoBA,IAAI,uBAAA,GAA0D,IAAA;AAMvD,SAAS,2BAA2B,QAAA,EAA0C;AACnF,EAAA,uBAAA,GAA0B,QAAA;AAC5B;AAIO,IAAM,UAAA,GAAqC;AAAA,EAChD,CAAA,EAAG,cAAA;AAAA,EACH,CAAA,EAAG,YAAA;AAAA,EACH,CAAA,EAAG,SAAA;AAAA,EACH,CAAA,EAAG,YAAA;AAAA,EACH,CAAA,EAAG,YAAA;AAAA,EACH,CAAA,EAAG,YAAA;AAAA,EACH,CAAA,EAAG,aAAA;AAAA,EACH,CAAA,EAAG,aAAA;AAAA,EACH,CAAA,EAAG;AACL;AAmBA,IAAM,cAAA,GAAiD;AAAA,EACrD,KAAA,EAAO,cAAA;AAAA,EACP,OAAA,EAAS,gBAAA;AAAA,EACT,IAAA,EAAM,aAAA;AAAA,EACN,IAAA,EAAM,aAAA;AAAA,EACN,YAAA,EAAc;AAChB,CAAA;AAEO,IAAM,KAAA,GAAQ,CAAC,KAAA,KAAoB;AACxC,EAAA,MAAM;AAAA,IACJ,GAAA;AAAA,IACA,GAAA,GAAM,EAAA;AAAA,IACN,YAAA;AAAA,IACA,QAAA,GAAW,KAAA;AAAA,IACX,OAAA,GAAU,WAAW,OAAA,GAAU,MAAA;AAAA,IAC/B,KAAA;AAAA,IACA,cAAA,GAAiB,KAAA;AAAA,IACjB,SAAA,GAAY,EAAA;AAAA,IACZ,OAAA,GAAU,EAAA;AAAA,IACV,KAAA,GAAQ,QAAA;AAAA,IACR,MAAA,GAAS,QAAA;AAAA,IACT,SAAA,GAAY,OAAA;AAAA,IACZ;AAAA,GACF,GAAI,KAAA;AACJ,EAAA,MAAM,SAAS,GAAA,IAAO,YAAA;AAEtB,EAAA,MAAM,cACJ,OAAO,YAAA,KAAiB,WACnB,UAAA,CAAW,YAAY,KAAK,SAAA,GAC7B,YAAA;AAEN,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,IAAI,gBAAgB,OAAO,IAAA;AAC3B,IAAA,uBACE,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,EAAA;AAAA,UACT,gDAAA;AAAA,UACA,KAAA;AAAA,UACA,MAAA;AAAA,UACA,WAAA;AAAA,UACA,OAAA;AAAA,UACA;AAAA;AACF;AAAA,KACF;AAAA,EAEJ;AAEA,EAAA,MAAM,SAAA,GAAY,0BAA0B,EAAE,GAAA,EAAK,QAAQ,GAAA,EAAK,KAAA,EAAO,UAAU,CAAA;AAEjF,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA;AAAA,QACT,uCAAA;AAAA,QACA,KAAA;AAAA,QACA,MAAA;AAAA,QACA,WAAA;AAAA,QACA,OAAA;AAAA,QACA;AAAA,OACF;AAAA,MAEA,QAAA,kBAAA,GAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,GAAA,EAAK,MAAA;AAAA,UACL,GAAA;AAAA,UACA,KAAA;AAAA,UACA,OAAA;AAAA,UACA,QAAA,EAAS,OAAA;AAAA,UACT,aAAA,EAAe,WAAW,MAAA,GAAS,MAAA;AAAA,UAClC,GAAG,SAAA;AAAA,UACJ,SAAA,EAAW,EAAA;AAAA,YACT,gCAAA;AAAA,YACA,WAAA;AAAA,YACA,eAAe,SAAS;AAAA;AAC1B;AAAA;AACF;AAAA,GACF;AAEJ;ACjHA,IAAM,gBAAA,mBAAmB,MAAA,CAAO,GAAA,CAAI,qCAAqC,CAAA;AACzE,IAAM,cAAA,GAAiB,UAAA;AAGvB,IAAM,sBAAA,GAA0B,cAAA,CAAA,gBAAA,CAAA,KAAA,cAAA,CAAA,gBAAA,CAAA,GACxB,KAAA,CAAA,aAAA,CAA+C,IAAI,CAAA,CAAA;AAEpD,SAAS,uBAAA,CAAwB;AAAA,EACtC,SAAA;AAAA,EACA;AACF,CAAA,EAGG;AACD,EAAA,uBACEA,IAAC,sBAAA,CAAuB,QAAA,EAAvB,EAAgC,KAAA,EAAO,SAAA,IAAa,MAClD,QAAA,EACH,CAAA;AAEJ;AAEO,SAAS,2BAAA,GAA8B;AAC5C,EAAA,OAAa,iBAAW,sBAAsB,CAAA;AAChD;AAgBO,SAAS,OAAA,CAAQ;AAAA,EACtB,IAAA;AAAA,EACA,QAAA;AAAA,EACA,aAAA,GAAgB,IAAA;AAAA,EAChB,KAAA;AAAA,EACA,SAAA,GAAY,EAAA;AAAA,EACZ;AACF,CAAA,EAAiB;AACf,EAAA,MAAM,gBAAgB,2BAAA,EAA4B;AAClD,EAAA,MAAM,aAAa,OAAA,CAAQ,IAAA,IAAQ,IAAA,CAAK,UAAA,CAAW,GAAG,CAAC,CAAA;AACvD,EAAA,MAAM,qBAAqB,OAAA,CAAQ,IAAA,IAAQ,IAAA,CAAK,UAAA,CAAW,GAAG,CAAC,CAAA;AAC/D,EAAA,MAAM,MAAA,GAAS,gBAAgB,MAAA,GAAY,QAAA;AAC3C,EAAA,MAAM,GAAA,GAAM,MAAA,KAAW,QAAA,GAAW,qBAAA,GAAwB,MAAA;AAC1D,EAAA,MAAM,cAA0D,MAAM;AACpE,IAAA,OAAA,IAAU;AAAA,EACZ,CAAA;AAEA,EAAA,IAAI,CAAC,kBAAA,IAAsB,UAAA,IAAc,aAAA,EAAe;AACtD,IAAA,uBACEA,GAAAA;AAAA,MAAC,aAAA;AAAA,MAAA;AAAA,QACC,IAAA;AAAA,QACA,KAAA;AAAA,QACA,SAAA;AAAA,QACA,OAAA,EAAS,WAAA;AAAA,QACT,MAAA;AAAA,QACA,GAAA;AAAA,QAEC;AAAA;AAAA,KACH;AAAA,EAEJ;AAEA,EAAA,uBACEA,GAAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MACC,IAAA;AAAA,MACA,KAAA;AAAA,MACA,SAAA;AAAA,MACA,MAAA;AAAA,MACA,GAAA;AAAA,MACA,OAAA,EAAS,WAAA;AAAA,MAER;AAAA;AAAA,GACH;AAEJ;;;ACzGA,IAAM,iBAAA,uBAAwB,GAAA,CAAI;AAAA,EAChC,aAAA;AAAA,EACA,iBAAA;AAAA,EACA,eAAA;AAAA,EACA,mBAAA;AAAA,EACA,sBAAA;AAAA,EACA,0BAAA;AAAA,EACA;AACF,CAAC,CAAA;AAED,IAAM,kCAAkB,IAAI,GAAA,CAAI,CAAC,WAAA,EAAa,eAAA,EAAiB,kBAAkB,CAAC,CAAA;AAElF,IAAM,SAAA,GAAY,CAAC,KAAA,KAAkB,OAAA,CAAQ,KAAK,KAAK,CAAA;AAEvD,IAAM,qBAAA,GAAwB,CAAC,SAAA,KAAmB;AAChD,EAAA,MAAM,QAAA,GAAW,SAAA,CAAU,QAAA,CAAS,WAAA,EAAY;AAEhD,EAAA,IAAI,CAAC,iBAAA,CAAkB,GAAA,CAAI,QAAQ,CAAA,EAAG;AACpC,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI,aAAa,UAAA,EAAY;AAC3B,IAAA,OAAO,SAAA,CAAU,SAAS,KAAA,CAAM,GAAG,EAAE,MAAA,CAAO,OAAO,CAAA,CAAE,CAAC,CAAA,IAAK,IAAA;AAAA,EAC7D;AAEA,EAAA,IAAI,SAAA,CAAU,aAAa,QAAA,EAAU;AACnC,IAAA,OAAO,SAAA,CAAU,YAAA,CAAa,GAAA,CAAI,GAAG,CAAA;AAAA,EACvC;AAEA,EAAA,MAAM,YAAY,SAAA,CAAU,QAAA,CAAS,MAAM,GAAG,CAAA,CAAE,OAAO,OAAO,CAAA;AAC9D,EAAA,MAAM,SAAA,GAAY,UAAU,CAAC,CAAA;AAC7B,EAAA,MAAM,UAAA,GAAa,UAAU,CAAC,CAAA;AAE9B,EAAA,IAAA,CACG,SAAA,KAAc,WACb,SAAA,KAAc,GAAA,IACd,cAAc,QAAA,IACd,SAAA,KAAc,WAChB,UAAA,EACA;AACA,IAAA,OAAO,UAAA;AAAA,EACT;AAEA,EAAA,OAAO,IAAA;AACT,CAAA;AAEA,IAAM,mBAAA,GAAsB,CAAC,SAAA,KAAmB;AAC9C,EAAA,MAAM,QAAA,GAAW,SAAA,CAAU,QAAA,CAAS,WAAA,EAAY;AAEhD,EAAA,IAAI,CAAC,eAAA,CAAgB,GAAA,CAAI,QAAQ,CAAA,EAAG;AAClC,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,YAAY,SAAA,CAAU,QAAA,CAAS,MAAM,GAAG,CAAA,CAAE,OAAO,OAAO,CAAA;AAE9D,EAAA,KAAA,IAAS,QAAQ,SAAA,CAAU,MAAA,GAAS,CAAA,EAAG,KAAA,IAAS,GAAG,KAAA,EAAA,EAAS;AAC1D,IAAA,IAAI,SAAA,CAAU,SAAA,CAAU,KAAK,CAAC,CAAA,EAAG;AAC/B,MAAA,OAAO,UAAU,KAAK,CAAA;AAAA,IACxB;AAAA,EACF;AAEA,EAAA,OAAO,IAAA;AACT,CAAA;AAEO,SAAS,cAAA,CAAe,KAAc,QAAA,EAAmC;AAC9E,EAAA,IAAI,CAAC,GAAA,EAAK;AACR,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,gBAAgB,0BAAA,CAA2B,IAAA,CAAK,GAAG,CAAA,GAAI,GAAA,GAAM,WAAW,GAAG,CAAA,CAAA;AAEjF,EAAA,IAAI;AACF,IAAA,MAAM,SAAA,GAAY,IAAI,GAAA,CAAI,aAAa,CAAA;AAEvC,IAAA,IAAI,aAAa,SAAA,EAAW;AAC1B,MAAA,OAAO,sBAAsB,SAAS,CAAA;AAAA,IACxC;AAEA,IAAA,IAAI,aAAa,OAAA,EAAS;AACxB,MAAA,OAAO,oBAAoB,SAAS,CAAA;AAAA,IACtC;AAEA,IAAA,OAAO,qBAAA,CAAsB,SAAS,CAAA,IAAK,mBAAA,CAAoB,SAAS,CAAA;AAAA,EAC1E,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AChEO,SAAS,gBAAA,CAAiB;AAAA,EAC/B,KAAA,GAAQ,OAAA;AAAA,EACR,YAAA;AAAA,EACA,QAAA,GAAW,6CAAA;AAAA,EACX,WAAA,GAAc,MAAA;AAAA,EACd,KAAA,GAAQ;AACV,CAAA,EAAwB;AACtB,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAAS,KAAK,CAAA;AACpD,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAS,KAAK,CAAA;AAChD,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAI,SAAwB,IAAI,CAAA;AAExE,EAAA,MAAM,kBAAkB,MAAiB;AACvC,IAAA,IAAI,cAAA,CAAe,QAAA,EAAU,SAAS,CAAA,EAAG;AACvC,MAAA,OAAO,SAAA;AAAA,IACT;AAEA,IAAA,IAAI,cAAA,CAAe,QAAA,EAAU,OAAO,CAAA,EAAG;AACrC,MAAA,OAAO,OAAA;AAAA,IACT;AAEA,IAAA,OAAO,aAAA;AAAA,EACT,CAAA;AAEA,EAAA,MAAM,YAAY,eAAA,EAAgB;AAElC,EAAA,MAAM,aAAa,MAAM;AACvB,IAAA,IAAI,cAAc,SAAA,EAAW;AAC3B,MAAA,OAAO,cAAA,CAAe,UAAU,SAAS,CAAA;AAAA,IAC3C;AAEA,IAAA,IAAI,cAAc,OAAA,EAAS;AACzB,MAAA,OAAO,cAAA,CAAe,UAAU,OAAO,CAAA;AAAA,IACzC;AAEA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA;AAGA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,sBAAsB,YAAY;AAEtC,MAAA,IAAI,YAAA,IAAgB,cAAc,OAAA,EAAS;AAE3C,MAAA,MAAM,UAAU,UAAA,EAAW;AAC3B,MAAA,IAAI,CAAC,OAAA,EAAS;AAEd,MAAA,IAAI;AAEF,QAAA,MAAM,WAAW,MAAM,KAAA;AAAA,UACrB,2DAA2D,OAAO,CAAA;AAAA,SACpE;AAEA,QAAA,IAAI,SAAS,EAAA,EAAI;AACf,UAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,UAAA,iBAAA,CAAkB,KAAK,aAAa,CAAA;AAAA,QACtC;AAAA,MACF,SAAS,KAAA,EAAO;AACd,QAAA,OAAA,CAAQ,KAAA,CAAM,mCAAmC,KAAK,CAAA;AAAA,MACxD;AAAA,IACF,CAAA;AAEA,IAAA,mBAAA,EAAoB;AAAA,EACtB,CAAA,EAAG,CAAC,QAAA,EAAU,SAAA,EAAW,YAAY,CAAC,CAAA;AAGtC,EAAA,MAAM,kBAAkB,MAAM;AAE5B,IAAA,IAAI,cAAc,OAAO,YAAA;AAGzB,IAAA,IAAI,cAAc,SAAA,EAAW;AAC3B,MAAA,MAAM,UAAU,UAAA,EAAW;AAC3B,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,OAAO,8BAA8B,OAAO,CAAA,cAAA,CAAA;AAAA,MAC9C;AAAA,IACF;AAGA,IAAA,IAAI,SAAA,KAAc,WAAW,cAAA,EAAgB;AAC3C,MAAA,OAAO,cAAA;AAAA,IACT;AAGA,IAAA,OAAO,uCAAA;AAAA,EACT,CAAA;AAGA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,QAAA,CAAS,IAAA,CAAK,MAAM,QAAA,GAAW,QAAA;AAAA,IACjC,CAAA,MAAO;AACL,MAAA,QAAA,CAAS,IAAA,CAAK,MAAM,QAAA,GAAW,EAAA;AAAA,IACjC;AAEA,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,CAAS,IAAA,CAAK,MAAM,QAAA,GAAW,EAAA;AAAA,IACjC,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,WAAW,CAAC,CAAA;AAGhB,EAAA,MAAM,cAAc,MAAM;AACxB,IAAA,MAAM,UAAU,UAAA,EAAW;AAE3B,IAAA,MAAM,cAAA,GAAiB,SAAA;AAEvB,IAAA,IAAI,cAAc,SAAA,EAAW;AAC3B,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,OAAO,CAAA,8BAAA,EAAiC,OAAO,CAAA,EAAG,cAAA,GAAiB,gBAAgB,EAAE,CAAA,CAAA;AAAA,MACvF;AAGA,MAAA,MAAM,SAAA,GAAY,QAAA,CAAS,QAAA,CAAS,GAAG,CAAA;AACvC,MAAA,OACE,YACC,cAAA,IAAkB,CAAC,YAChB,aAAA,GACA,cAAA,IAAkB,YAChB,aAAA,GACA,EAAA,CAAA;AAAA,IAEV;AAEA,IAAA,IAAI,SAAA,KAAc,WAAW,OAAA,EAAS;AACpC,MAAA,OAAO,CAAA,+BAAA,EAAkC,OAAO,CAAA,EAAG,cAAA,GAAiB,gBAAgB,EAAE,CAAA,CAAA;AAAA,IACxF;AAGA,IAAA,OAAO,QAAA;AAAA,EACT,CAAA;AAGA,EAAA,MAAM,mBAAmB,MAAM;AAC7B,IAAA,IAAI,CAAC,WAAA,CAAY,QAAA,CAAS,GAAG,CAAA,SAAU,EAAC;AAExC,IAAA,MAAM,CAAC,OAAO,MAAM,CAAA,GAAI,YAAY,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,CAAI,MAAM,CAAA;AACzD,IAAA,IAAI,CAAC,KAAA,IAAS,CAAC,MAAA,SAAe,EAAC;AAE/B,IAAA,OAAO;AAAA,MACL,WAAA,EAAa,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,MAAM,CAAA;AAAA,KACjC;AAAA,EACF,CAAA;AAGA,EAAA,MAAM,uBAAuB,MAAM;AACjC,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,cAAA,CAAe,IAAI,CAAA;AAAA,IACrB,CAAA,MAAO;AACL,MAAA,YAAA,CAAa,IAAI,CAAA;AAAA,IACnB;AAAA,EACF,CAAA;AAEA,EAAA,4BACG,KAAA,EAAA,EAAI,SAAA,EAAW,WAAA,KAAgB,MAAA,GAAS,qBAAqB,EAAA,EAE5D,QAAA,EAAA;AAAA,oBAAAA,GAAAA,CAAC,SAAI,SAAA,EAAU,0BAAA,EAA2B,OAAO,gBAAA,EAAiB,EAC/D,WAAC,KAAA,IAAS,SAAA;AAAA;AAAA,sBAETA,GAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,eAAA,EACZ,QAAA,EAAA,SAAA,KAAc,gCACbA,GAAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,KAAK,WAAA,EAAY;AAAA,UACjB,SAAA,EAAU,eAAA;AAAA,UACV,KAAA,EAAM,0FAAA;AAAA,UACN,eAAA,EAAe;AAAA;AAAA,0BAGjBA,GAAAA;AAAA,QAAC,OAAA;AAAA,QAAA;AAAA,UACC,GAAA,EAAK,QAAA;AAAA,UACL,QAAA,EAAQ,IAAA;AAAA,UACR,YAAA,EAAa,YAAA;AAAA,UACb,aAAA,EAAe,CAAC,CAAA,KAAM,CAAA,CAAE,cAAA,EAAe;AAAA,UACvC,QAAA,EAAQ,IAAA;AAAA,UACR,SAAA,EAAU,eAAA;AAAA,UACX,QAAA,EAAA;AAAA;AAAA,OAED,EAEJ;AAAA;AAAA;AAAA,sBAGA,IAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAU,oCAAA;AAAA,UACV,OAAA,EAAS,oBAAA;AAAA,UAET,QAAA,EAAA;AAAA,4BAAAA,GAAAA;AAAA,cAAC,KAAA;AAAA,cAAA;AAAA,gBACC,GAAA,EAAK,iBAAgB,IAAK,kBAAA;AAAA,gBAC1B,GAAA,EAAK,iBAAiB,KAAK,CAAA,CAAA;AAAA,gBAC3B,SAAA,EAAU;AAAA;AAAA,aACZ;AAAA,4BACAA,IAAC,KAAA,EAAA,EAAI,SAAA,EAAU,iEACb,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,UAAA,EAEb,QAAA,EAAA;AAAA,8BAAAA,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,iFAAA,EAAkF,CAAA;AAAA,8BAGlGA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,kEAAA,EACb,QAAA,kBAAAA,GAAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAU,SAAA,EAAU,IAAA,EAAK,cAAA,EAAe,CAAA,EAChD;AAAA,aAAA,EACF,CAAA,EACF;AAAA;AAAA;AAAA;AACF,KAAA,EAEJ,CAAA;AAAA,IAGC,KAAA,IAAS,WAAA,oBACR,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,oFAAA,EACb,QAAA,EAAA;AAAA,sBAAAA,GAAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,OAAA,EAAS,MAAM,cAAA,CAAe,KAAK,CAAA;AAAA,UACnC,SAAA,EAAU,mGAAA;AAAA,UACV,YAAA,EAAW,OAAA;AAAA,UAEX,QAAA,kBAAAA,GAAAA,CAAC,CAAA,EAAA,EAAE,SAAA,EAAU,uBAAA,EAAwB;AAAA;AAAA,OACvC;AAAA,sBAEAA,GAAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAU,2CAAA;AAAA,UACV,OAAO,gBAAA,EAAiB;AAAA,UAEvB,QAAA,EAAA,SAAA,KAAc,aAAA;AAAA;AAAA,4BAEbA,GAAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBACC,KAAK,WAAA,EAAY;AAAA,gBACjB,SAAA,EAAU,eAAA;AAAA,gBACV,KAAA,EAAM,0FAAA;AAAA,gBACN,eAAA,EAAe;AAAA;AAAA;AAChB;AAAA;AAAA,4BAGDA,GAAAA;AAAA,cAAC,OAAA;AAAA,cAAA;AAAA,gBACC,GAAA,EAAK,QAAA;AAAA,gBACL,QAAA,EAAQ,IAAA;AAAA,gBACR,YAAA,EAAa,YAAA;AAAA,gBACb,aAAA,EAAe,CAAC,CAAA,KAAM,CAAA,CAAE,cAAA,EAAe;AAAA,gBACvC,QAAA,EAAQ,IAAA;AAAA,gBACR,SAAA,EAAU,eAAA;AAAA,gBACX,QAAA,EAAA;AAAA;AAAA;AAED;AAAA;AAAA;AAEJ,KAAA,EACF;AAAA,GAAA,EAEJ,CAAA;AAEJ;AChQA,IAAM,YAAA,GACJ,8FAAA;AAWK,SAAS,aAAa,OAAA,EAAiB;AAC5C,EAAA,MAAM,QAAQ,OAAA,CAAQ,KAAA,CAAM,YAAY,CAAA,EAAG,IAAA,CAAK,EAAE,CAAA,IAAK,EAAA;AACvD,EAAA,MAAM,MAAA,GAAS,QACZ,OAAA,CAAQ,YAAA,EAAc,EAAE,CAAA,CACxB,OAAA,CAAQ,kDAAA,EAAoD,EAAE,CAAA,CAC9D,OAAA;AAAA,IACC,4EAAA;AAAA,IACA;AAAA,GACF,CACC,OAAA;AAAA,IACC,uCAAA;AAAA,IACA,CAAC,CAAA,EAAG,KAAA,EAAe,GAAA,KAAgB;AACjC,MAAA,MAAM,MAAA,GAAS,GAAA,CACZ,OAAA,CAAQ,UAAA,EAAY,OAAO,EAC3B,OAAA,CAAQ,0BAAA,EAA4B,gBAAgB,CAAA,CACpD,OAAA,CAAQ,kCAAA,EAAoC,SAAS,CAAA,CACrD,OAAA,CAAQ,kCAAA,EAAoC,qBAAqB,CAAA,CACjE,OAAA,CAAQ,4BAAA,EAA8B,cAAc,CAAA,CACpD,OAAA,CAAQ,mBAAA,EAAqB,OAAO,CAAA,CACpC,OAAA;AAAA,QACC,sEAAA;AAAA,QACA;AAAA,OACF;AACF,MAAA,OAAO,CAAA,MAAA,EAAS,KAAK,CAAA,CAAA,EAAI,MAAM,CAAA,QAAA,CAAA;AAAA,IACjC;AAAA,GACF;AAEF,EAAA,MAAM,IAAA,GAAO,sGAAsG,MAAM,CAAA,MAAA,CAAA;AACzH,EAAA,OAAO,EAAE,OAAO,IAAA,EAAK;AACvB;AAEA,SAAS,WAAW,IAAA,EAAkB;AACpC,EAAA,KAAA,MAAW,GAAA,IAAO,IAAA,CAAK,gBAAA,CAAiB,QAAQ,CAAA,EAAG;AACjD,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA;AAC9C,IAAA,KAAA,MAAW,EAAE,MAAM,KAAA,EAAM,IAAK,IAAI,UAAA,EAAY,MAAA,CAAO,YAAA,CAAa,IAAA,EAAM,KAAK,CAAA;AAC7E,IAAA,MAAA,CAAO,cAAc,GAAA,CAAI,WAAA;AACzB,IAAA,GAAA,CAAI,YAAY,MAAM,CAAA;AAAA,EACxB;AACF;AAOO,IAAM,cAAc,CAAC,EAAE,OAAA,EAAS,SAAA,EAAW,OAAM,KAAwB;AAC9E,EAAA,MAAM,OAAA,GAAU,OAAuB,IAAI,CAAA;AAC3C,EAAA,MAAM,UAAA,GAAa,OAAsB,IAAI,CAAA;AAC7C,EAAA,MAAM,EAAE,KAAA,EAAO,IAAA,EAAK,GAAI,aAAa,OAAO,CAAA;AAE5C,EAAAC,UAAU,MAAM;AACd,IAAA,MAAM,OAAO,OAAA,CAAQ,OAAA;AACrB,IAAA,IAAI,CAAC,IAAA,EAAM;AAKX,IAAA,MAAM,IAAA,GAAO,KAAK,UAAA,IAAc,IAAA,CAAK,aAAa,EAAE,IAAA,EAAM,QAAQ,CAAA;AAClE,IAAA,IAAI,UAAA,CAAW,YAAY,IAAA,EAAM;AAIjC,IAAA,IAAI,WAAW,OAAA,KAAY,IAAA,IAAQ,CAAC,IAAA,CAAK,eAAc,EAAG;AACxD,MAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AACjB,MAAA,UAAA,CAAW,IAAI,CAAA;AAAA,IACjB;AACA,IAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AAAA,EACvB,CAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AAIT,EAAAA,UAAU,MAAM;AACd,IAAA,MAAM,OAAO,OAAA,CAAQ,OAAA;AACrB,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,MAAM,IAAA,GAAO,MACX,IAAA,CAAK,SAAA,CAAU,MAAA;AAAA,MACb,MAAA;AAAA,MACA,CAAC,CAAC,IAAA,CAAK,aAAA,EAAe,OAAA,CAAQ,OAAO,CAAA,IACnC,QAAA,CAAS,eAAA,CAAgB,SAAA,CAAU,QAAA,CAAS,MAAM;AAAA,KACtD;AACF,IAAA,IAAA,EAAK;AACL,IAAA,MAAM,QAAA,GAAW,IAAI,gBAAA,CAAiB,IAAI,CAAA;AAC1C,IAAA,QAAA,CAAS,OAAA,CAAQ,SAAS,eAAA,EAAiB;AAAA,MACzC,UAAA,EAAY,IAAA;AAAA,MACZ,eAAA,EAAiB,CAAC,OAAO,CAAA;AAAA,MACzB,OAAA,EAAS;AAAA,KACV,CAAA;AACD,IAAA,OAAO,MAAM,SAAS,UAAA,EAAW;AAAA,EACnC,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,uBACED,GAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,OAAA;AAAA,MACL,SAAA;AAAA,MACA,KAAA;AAAA,MACA,wBAAA,EAAwB,IAAA;AAAA,MACxB,uBAAA,EAAyB;AAAA;AAAA;AAAA,QAGvB,MAAA,EACE,OAAO,MAAA,KAAW,WAAA,GACd,GAAG,KAAK,CAAA,gCAAA,EAAmC,IAAI,CAAA,WAAA,CAAA,GAC/C;AAAA;AACR;AAAA,GACF;AAEJ","file":"chunk-36QHCIPM.js","sourcesContent":["import type React from \"react\";\nimport { cn } from \"../primitives/lib/utils\";\n\nexport interface ImageAttributesInput {\n src: string;\n alt: string;\n sizes?: string;\n /** Above-the-fold image (e.g. LCP): fetched eagerly at high priority. */\n priority: boolean;\n}\n\n/**\n * Lets a host swap an image's `src`/`srcSet` for its own optimizer's URLs\n * (e.g. Next.js's `getImageProps`) without this package depending on the\n * host framework. Return `null` to keep the original URL.\n */\nexport type ImageAttributesResolver = (\n input: ImageAttributesInput,\n) => React.ImgHTMLAttributes<HTMLImageElement> | null;\n\nlet imageAttributesResolver: ImageAttributesResolver | null = null;\n\n/**\n * Registers the host's resolver. Call once at server start-up; renders that\n * run without one emit the original URL.\n */\nexport function setImageAttributesResolver(resolver: ImageAttributesResolver | null) {\n imageAttributesResolver = resolver;\n}\n\nexport type ImageObjectFit = \"cover\" | \"contain\" | \"fill\" | \"none\" | \"scale-down\";\n\nexport const roundedMap: Record<number, string> = {\n 0: \"rounded-none\",\n 1: \"rounded-sm\",\n 2: \"rounded\",\n 3: \"rounded-md\",\n 4: \"rounded-lg\",\n 5: \"rounded-xl\",\n 6: \"rounded-2xl\",\n 7: \"rounded-3xl\",\n 8: \"rounded-full\",\n};\n\ninterface ImgProps {\n src: string;\n classes?: string;\n alt?: string;\n defaultImage?: string;\n loading?: \"eager\" | \"lazy\";\n /** Marks the image as likely LCP: eager load with high fetch priority. */\n priority?: boolean;\n height?: string;\n sizes?: string;\n width?: string;\n borderRadius?: number | string;\n noDefaultImage?: boolean;\n className?: string;\n objectFit?: ImageObjectFit;\n}\n\nconst objectFitClass: Record<ImageObjectFit, string> = {\n cover: \"object-cover\",\n contain: \"object-contain\",\n fill: \"object-fill\",\n none: \"object-none\",\n \"scale-down\": \"object-scale-down\",\n};\n\nexport const Image = (props: ImgProps) => {\n const {\n src,\n alt = \"\",\n defaultImage,\n priority = false,\n loading = priority ? \"eager\" : \"lazy\",\n sizes,\n noDefaultImage = false,\n className = \"\",\n classes = \"\",\n width = \"w-full\",\n height = \"h-auto\",\n objectFit = \"cover\",\n borderRadius,\n } = props;\n const source = src || defaultImage;\n\n const radiusClass =\n typeof borderRadius === \"number\"\n ? (roundedMap[borderRadius] ?? \"rounded\")\n : borderRadius;\n\n if (!source) {\n if (noDefaultImage) return null;\n return (\n <div\n className={cn(\n \"relative aspect-video overflow-hidden bg-muted\",\n width,\n height,\n radiusClass,\n classes,\n className,\n )}\n />\n );\n }\n\n const optimized = imageAttributesResolver?.({ src: source, alt, sizes, priority });\n\n return (\n <div\n className={cn(\n \"relative aspect-video overflow-hidden\",\n width,\n height,\n radiusClass,\n classes,\n className,\n )}\n >\n <img\n src={source}\n alt={alt}\n sizes={sizes}\n loading={loading}\n decoding=\"async\"\n fetchPriority={priority ? \"high\" : undefined}\n {...optimized}\n className={cn(\n \"absolute inset-0 h-full w-full\",\n radiusClass,\n objectFitClass[objectFit],\n )}\n />\n </div>\n );\n};\n","\"use client\";\n\nimport * as React from \"react\";\n\nexport interface PageBuilderLinkProps {\n href: string;\n children?: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n onClick?: React.MouseEventHandler<HTMLAnchorElement>;\n target?: string;\n rel?: string;\n}\n\n/**\n * Optional host-supplied link. Next.js apps can pass `next/link`; Vite / Remix\n * / plain React hosts can omit it and NavLink will render a native `<a>`.\n */\nexport type PageBuilderLinkComponent = React.ComponentType<PageBuilderLinkProps>;\n\n// Server-rendered pages load this module more than once (each client island is\n// bundled on its own), so the context is shared through the global registry\n// rather than created per copy. Otherwise a provider from one copy would be\n// invisible to a NavLink from another.\nconst LINK_CONTEXT_KEY = Symbol.for(\"@frontlit/page-builder/link-context\");\nconst globalRegistry = globalThis as typeof globalThis & {\n [LINK_CONTEXT_KEY]?: React.Context<PageBuilderLinkComponent | null>;\n};\nconst PageBuilderLinkContext = (globalRegistry[LINK_CONTEXT_KEY] ??=\n React.createContext<PageBuilderLinkComponent | null>(null));\n\nexport function PageBuilderLinkProvider({\n component,\n children,\n}: {\n component?: PageBuilderLinkComponent | null;\n children: React.ReactNode;\n}) {\n return (\n <PageBuilderLinkContext.Provider value={component ?? null}>\n {children}\n </PageBuilderLinkContext.Provider>\n );\n}\n\nexport function usePageBuilderLinkComponent() {\n return React.useContext(PageBuilderLinkContext);\n}\n\ninterface NavLinkProps {\n href: string;\n children?: React.ReactNode;\n openInSameTab?: boolean;\n style?: React.CSSProperties;\n className?: string;\n onClick?: () => void;\n}\n\n/**\n * A navigation-aware link used inside block widgets. In-page anchors scroll\n * to the target. Internal paths (`/...`) use the host `linkComponent` when\n * one is provided (e.g. Next.js `Link`); everything else is a native `<a>`.\n */\nexport function NavLink({\n href,\n children,\n openInSameTab = true,\n style,\n className = \"\",\n onClick,\n}: NavLinkProps) {\n const LinkComponent = usePageBuilderLinkComponent();\n const isInternal = Boolean(href && href.startsWith(\"/\"));\n const isInPageNavigation = Boolean(href && href.startsWith(\"#\"));\n const target = openInSameTab ? undefined : \"_blank\";\n const rel = target === \"_blank\" ? \"noopener noreferrer\" : undefined;\n const handleClick: React.MouseEventHandler<HTMLAnchorElement> = () => {\n onClick?.();\n };\n\n if (!isInPageNavigation && isInternal && LinkComponent) {\n return (\n <LinkComponent\n href={href}\n style={style}\n className={className}\n onClick={handleClick}\n target={target}\n rel={rel}\n >\n {children}\n </LinkComponent>\n );\n }\n\n return (\n <a\n href={href}\n style={style}\n className={className}\n target={target}\n rel={rel}\n onClick={handleClick}\n >\n {children}\n </a>\n );\n}\n","export type SupportedVideoPlatform = \"youtube\" | \"vimeo\";\n\nconst YOUTUBE_HOSTNAMES = new Set([\n \"youtube.com\",\n \"www.youtube.com\",\n \"m.youtube.com\",\n \"music.youtube.com\",\n \"youtube-nocookie.com\",\n \"www.youtube-nocookie.com\",\n \"youtu.be\",\n]);\n\nconst VIMEO_HOSTNAMES = new Set([\"vimeo.com\", \"www.vimeo.com\", \"player.vimeo.com\"]);\n\nconst isNumeric = (value: string) => /^\\d+$/.test(value);\n\nconst extractYouTubeVideoId = (parsedUrl: URL) => {\n const hostname = parsedUrl.hostname.toLowerCase();\n\n if (!YOUTUBE_HOSTNAMES.has(hostname)) {\n return null;\n }\n\n if (hostname === \"youtu.be\") {\n return parsedUrl.pathname.split(\"/\").filter(Boolean)[0] || null;\n }\n\n if (parsedUrl.pathname === \"/watch\") {\n return parsedUrl.searchParams.get(\"v\");\n }\n\n const pathParts = parsedUrl.pathname.split(\"/\").filter(Boolean);\n const firstPart = pathParts[0];\n const secondPart = pathParts[1];\n\n if (\n (firstPart === \"embed\" ||\n firstPart === \"v\" ||\n firstPart === \"shorts\" ||\n firstPart === \"live\") &&\n secondPart\n ) {\n return secondPart;\n }\n\n return null;\n};\n\nconst extractVimeoVideoId = (parsedUrl: URL) => {\n const hostname = parsedUrl.hostname.toLowerCase();\n\n if (!VIMEO_HOSTNAMES.has(hostname)) {\n return null;\n }\n\n const pathParts = parsedUrl.pathname.split(\"/\").filter(Boolean);\n\n for (let index = pathParts.length - 1; index >= 0; index--) {\n if (isNumeric(pathParts[index])) {\n return pathParts[index];\n }\n }\n\n return null;\n};\n\nexport function extractVideoId(url?: string, platform?: SupportedVideoPlatform) {\n if (!url) {\n return null;\n }\n\n const normalizedUrl = /^[a-z][a-z\\d+\\-.]*:\\/\\//i.test(url) ? url : `https://${url}`;\n\n try {\n const parsedUrl = new URL(normalizedUrl);\n\n if (platform === \"youtube\") {\n return extractYouTubeVideoId(parsedUrl);\n }\n\n if (platform === \"vimeo\") {\n return extractVimeoVideoId(parsedUrl);\n }\n\n return extractYouTubeVideoId(parsedUrl) || extractVimeoVideoId(parsedUrl);\n } catch {\n return null;\n }\n}\n","import { useState, useEffect } from \"react\";\nimport { Play, X } from \"lucide-react\";\nimport { extractVideoId } from \"../utils\";\n\ntype VideoType = \"youtube\" | \"vimeo\" | \"self-hosted\";\n\nexport type AspectRatio =\n | \"16/9\" // Widescreen\n | \"4/3\" // Standard\n | \"1/1\" // Square\n | \"21/9\" // Ultrawide\n | \"9/16\" // Vertical\n | \"2/1\" // Panoramic\n | \"3/2\" // Classic\n | string; // Allow custom aspect ratios\n\nexport interface VideoThumbnailProps {\n title?: string;\n thumbnailUrl?: string;\n videoUrl: string;\n aspectRatio?: AspectRatio;\n modal?: boolean;\n}\n\nexport function VideoWithPreview({\n title = \"Video\",\n thumbnailUrl,\n videoUrl = \"https://www.youtube.com/watch?v=7OP2bU9RWVE\",\n aspectRatio = \"16/9\",\n modal = false,\n}: VideoThumbnailProps) {\n const [isModalOpen, setIsModalOpen] = useState(false);\n const [isPlaying, setIsPlaying] = useState(false);\n const [vimeoThumbnail, setVimeoThumbnail] = useState<string | null>(null);\n\n const detectVideoType = (): VideoType => {\n if (extractVideoId(videoUrl, \"youtube\")) {\n return \"youtube\";\n }\n\n if (extractVideoId(videoUrl, \"vimeo\")) {\n return \"vimeo\";\n }\n\n return \"self-hosted\";\n };\n\n const videoType = detectVideoType();\n\n const getVideoId = () => {\n if (videoType === \"youtube\") {\n return extractVideoId(videoUrl, \"youtube\");\n }\n\n if (videoType === \"vimeo\") {\n return extractVideoId(videoUrl, \"vimeo\");\n }\n\n return null;\n };\n\n // Fetch Vimeo thumbnail if needed\n useEffect(() => {\n const fetchVimeoThumbnail = async () => {\n // Skip fetching if a thumbnail URL is already provided\n if (thumbnailUrl || videoType !== \"vimeo\") return;\n\n const videoId = getVideoId();\n if (!videoId) return;\n\n try {\n // Use Vimeo's oEmbed API to get thumbnail (no token required)\n const response = await fetch(\n `https://vimeo.com/api/oembed.json?url=https://vimeo.com/${videoId}`,\n );\n\n if (response.ok) {\n const data = await response.json();\n setVimeoThumbnail(data.thumbnail_url);\n }\n } catch (error) {\n console.error(\"Error fetching Vimeo thumbnail:\", error);\n }\n };\n\n fetchVimeoThumbnail();\n }, [videoUrl, videoType, thumbnailUrl]);\n\n // Get the appropriate thumbnail URL\n const getThumbnailUrl = () => {\n // If a thumbnail URL is explicitly provided, use that\n if (thumbnailUrl) return thumbnailUrl;\n\n // For YouTube videos, generate thumbnail URL\n if (videoType === \"youtube\") {\n const videoId = getVideoId();\n if (videoId) {\n return `https://img.youtube.com/vi/${videoId}/hqdefault.jpg`;\n }\n }\n\n // For Vimeo videos, use the fetched thumbnail\n if (videoType === \"vimeo\" && vimeoThumbnail) {\n return vimeoThumbnail;\n }\n\n // Fall back to placeholder\n return \"/placeholder.svg?height=480&width=854\";\n };\n\n // Lock body scroll when modal is open\n useEffect(() => {\n if (isModalOpen) {\n document.body.style.overflow = \"hidden\";\n } else {\n document.body.style.overflow = \"\";\n }\n\n return () => {\n document.body.style.overflow = \"\";\n };\n }, [isModalOpen]);\n\n // Get embed URL based on video type\n const getEmbedUrl = () => {\n const videoId = getVideoId();\n // Add autoplay parameter for in-place videos\n const shouldAutoplay = isPlaying;\n\n if (videoType === \"youtube\") {\n if (videoId) {\n return `https://www.youtube.com/embed/${videoId}${shouldAutoplay ? \"?autoplay=1\" : \"\"}`;\n }\n\n // If we couldn't extract the ID but it's a YouTube URL, try to use it directly\n const hasParams = videoUrl.includes(\"?\");\n return (\n videoUrl +\n (shouldAutoplay && !hasParams\n ? \"?autoplay=1\"\n : shouldAutoplay && hasParams\n ? \"&autoplay=1\"\n : \"\")\n );\n }\n\n if (videoType === \"vimeo\" && videoId) {\n return `https://player.vimeo.com/video/${videoId}${shouldAutoplay ? \"?autoplay=1\" : \"\"}`;\n }\n\n // For self-hosted videos, return the URL as is\n return videoUrl;\n };\n\n // Calculate aspect ratio style\n const aspectRatioStyle = () => {\n if (!aspectRatio.includes(\"/\")) return {};\n\n const [width, height] = aspectRatio.split(\"/\").map(Number);\n if (!width || !height) return {};\n\n return {\n aspectRatio: `${width}/${height}`,\n };\n };\n\n // Handle thumbnail click\n const handleThumbnailClick = () => {\n if (modal) {\n setIsModalOpen(true);\n } else {\n setIsPlaying(true);\n }\n };\n\n return (\n <div className={aspectRatio === \"9/16\" ? \"max-w-xs mx-auto\" : \"\"}>\n {/* Thumbnail with play button or in-place video */}\n <div className=\"relative overflow-hidden\" style={aspectRatioStyle()}>\n {!modal && isPlaying ? (\n // In-place video player\n <div className=\"w-full h-full\">\n {videoType !== \"self-hosted\" ? (\n <iframe\n src={getEmbedUrl()}\n className=\"w-full h-full\"\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n allowFullScreen\n ></iframe>\n ) : (\n <video\n src={videoUrl}\n controls\n controlsList=\"nodownload\" // eslint-disable-line react/no-unknown-property\n onContextMenu={(e) => e.preventDefault()}\n autoPlay\n className=\"w-full h-full\"\n >\n Your browser does not support the video tag.\n </video>\n )}\n </div>\n ) : (\n // Thumbnail with play button\n <div\n className=\"cursor-pointer group w-full h-full\"\n onClick={handleThumbnailClick}\n >\n <img\n src={getThumbnailUrl() || \"/placeholder.svg\"}\n alt={`Thumbnail for ${title}`}\n className=\"w-full h-full object-cover transition-transform duration-300 group-hover:scale-105\"\n />\n <div className=\"absolute inset-0 bg-black/30 flex items-center justify-center\">\n <div className=\"relative\">\n {/* Smaller grayish concentric wave animation */}\n <span className=\"absolute -inset-1.5 rounded-full bg-gray-200/50 animate-pulse duration-[3000ms]\"></span>\n\n {/* Play button */}\n <div className=\"relative z-1 rounded-full bg-primary p-4 text-primary-foreground\">\n <Play className=\"h-8 w-8\" fill=\"currentColor\" />\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n\n {/* Custom Video Modal (only used when modal is true) */}\n {modal && isModalOpen && (\n <div className=\"fixed inset-0 bg-black/95 z-50 flex items-center justify-center p-4 sm:p-6 md:p-10\">\n <button\n onClick={() => setIsModalOpen(false)}\n className=\"absolute top-2 right-2 sm:top-4 sm:right-4 text-white hover:text-gray-300 focus:outline-none z-10\"\n aria-label=\"Close\"\n >\n <X className=\"h-6 w-6 sm:h-8 sm:w-8\" />\n </button>\n\n <div\n className=\"w-full max-w-xl sm:max-w-2xl md:max-w-3xl\"\n style={aspectRatioStyle()}\n >\n {videoType !== \"self-hosted\" ? (\n // YouTube or Vimeo video\n <iframe\n src={getEmbedUrl()}\n className=\"w-full h-full\"\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n allowFullScreen\n ></iframe>\n ) : (\n // Self-hosted video\n <video\n src={videoUrl}\n controls\n controlsList=\"nodownload\" // eslint-disable-line react/no-unknown-property\n onContextMenu={(e) => e.preventDefault()}\n autoPlay\n className=\"w-full h-full\"\n >\n Your browser does not support the video tag.\n </video>\n )}\n </div>\n </div>\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport type React from \"react\";\nimport { useEffect, useRef } from \"react\";\n\ninterface InlineEmbedProps {\n content: string;\n className?: string;\n style?: React.CSSProperties;\n}\n\n// Font stylesheets and connection hints only work at document level (a\n// shadow root ignores @font-face), so these links are hoisted out of it.\nconst HOISTED_LINK =\n /<link\\b[^>]*(?:rel=[\"']?(?:preconnect|dns-prefetch|preload)|href=[\"'][^\"']*fonts?\\.)[^>]*>/gi;\n\n/**\n * Snippets are usually written as a standalone document (they used to live in\n * an iframe). Recreate that inside the shadow root: the host plays `html` and\n * is a size container, a wrapper plays `body`, and viewport units and width\n * media queries are rewritten to measure the embed (as they measured the\n * iframe) instead of the browser window. \"Fill the frame\" heights are dropped,\n * as are scripts that only synced state with `window.parent`, which the shadow\n * host handles itself.\n */\nexport function prepareEmbed(content: string) {\n const links = content.match(HOISTED_LINK)?.join(\"\") ?? \"\";\n const markup = content\n .replace(HOISTED_LINK, \"\")\n .replace(/<!doctype[^>]*>|<\\/?(?:html|head|body)\\b[^>]*>/gi, \"\")\n .replace(\n /<script\\b[^>]*>(?:(?!<\\/script>)[\\s\\S])*window\\.parent[\\s\\S]*?<\\/script>/gi,\n \"\",\n )\n .replace(\n /<style\\b([^>]*)>([\\s\\S]*?)<\\/style>/gi,\n (_, attrs: string, css: string) => {\n const scoped = css\n .replace(/:root\\b/g, \":host\")\n .replace(/(^|[\\s,{}])html\\.dark\\b/g, \"$1:host(.dark)\")\n .replace(/(^|[\\s,{}])html(?=[\\s,{:.[>~+])/g, \"$1:host\")\n .replace(/(^|[\\s,{}])body(?=[\\s,{:.[>~+])/g, \"$1[data-embed-body]\")\n .replace(/min-height\\s*:\\s*100d?vh/gi, \"min-height:0\")\n .replace(/(\\d*\\.?\\d+)vw\\b/gi, \"$1cqw\")\n .replace(\n /@media\\s+(?:only\\s+)?(?:screen\\s+and\\s+)?(\\([^{]*\\bwidth\\b[^{]*)\\{/gi,\n \"@container $1{\",\n );\n return `<style${attrs}>${scoped}</style>`;\n },\n );\n\n const body = `<style>:host{display:block;container-type:inline-size;overflow-x:clip}</style><div data-embed-body>${markup}</div>`;\n return { links, body };\n}\n\nfunction runScripts(root: ShadowRoot) {\n for (const old of root.querySelectorAll(\"script\")) {\n const script = document.createElement(\"script\");\n for (const { name, value } of old.attributes) script.setAttribute(name, value);\n script.textContent = old.textContent;\n old.replaceWith(script);\n }\n}\n\n/**\n * Renders a raw HTML snippet inline, inside a declarative shadow root. The\n * markup is part of the server-rendered page (so crawlers index it) while its\n * styles stay isolated from the site's in both directions.\n */\nexport const InlineEmbed = ({ content, className, style }: InlineEmbedProps) => {\n const hostRef = useRef<HTMLDivElement>(null);\n const appliedRef = useRef<string | null>(null);\n const { links, body } = prepareEmbed(content);\n\n useEffect(() => {\n const host = hostRef.current;\n if (!host) return;\n\n // A server-rendered host already has its shadow root from the HTML\n // parser; a client-rendered one (editor, client navigation) does not,\n // because innerHTML ignores declarative shadow roots.\n const root = host.shadowRoot ?? host.attachShadow({ mode: \"open\" });\n if (appliedRef.current === body) return;\n // The HTML parser already ran the scripts of a server-rendered shadow\n // root; only markup set through innerHTML (which never runs scripts)\n // needs them re-created, or they'd run twice.\n if (appliedRef.current !== null || !root.hasChildNodes()) {\n root.innerHTML = body;\n runScripts(root);\n }\n appliedRef.current = body;\n }, [body]);\n\n // Mirror the site's color mode onto the host so snippets can use\n // `:host(.dark)`.\n useEffect(() => {\n const host = hostRef.current;\n if (!host) return;\n const sync = () =>\n host.classList.toggle(\n \"dark\",\n !!host.parentElement?.closest(\".dark\") ||\n document.documentElement.classList.contains(\"dark\"),\n );\n sync();\n const observer = new MutationObserver(sync);\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\"],\n subtree: true,\n });\n return () => observer.disconnect();\n }, []);\n\n return (\n <div\n ref={hostRef}\n className={className}\n style={style}\n suppressHydrationWarning\n dangerouslySetInnerHTML={{\n // Only the HTML parser turns the template into a shadow root; on the\n // client the effect attaches it instead.\n __html:\n typeof window === \"undefined\"\n ? `${links}<template shadowrootmode=\"open\">${body}</template>`\n : links,\n }}\n />\n );\n};\n"]}
@@ -18,5 +18,5 @@ async function loadDataSlots(layout, loaders, pageData) {
18
18
  }
19
19
 
20
20
  export { loadDataSlots };
21
- //# sourceMappingURL=chunk-GTY75HW2.js.map
22
- //# sourceMappingURL=chunk-GTY75HW2.js.map
21
+ //# sourceMappingURL=chunk-ATNM5JHI.js.map
22
+ //# sourceMappingURL=chunk-ATNM5JHI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/data-slots.ts"],"names":[],"mappings":";AAyBA,eAAsB,aAAA,CACpB,MAAA,EACA,OAAA,EACA,QAAA,EACoC;AACpC,EAAA,MAAM,QAAQ,MAAA,CAAO,MAAA,CAAO,CAAC,QAAA,KAAa,QAAA,CAAS,SAAS,WAAW,CAAA;AACvE,EAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,GAAA;AAAA,IAC7B,KAAA,CAAM,GAAA,CAAI,OAAO,QAAA,KAAa;AAC5B,MAAA,MAAM,IAAA,GAAO,SAAS,QAAA,EAAU,IAAA;AAChC,MAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,CAAC,MAAM,OAAO,IAAA;AAC9C,MAAA,MAAM,MAAA,GAAS,QAAQ,IAAI,CAAA;AAC3B,MAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AACpB,MAAA,OAAO,CAAC,MAAM,MAAM,MAAA,CAAO,EAAE,IAAA,EAAM,QAAA,EAAU,QAAA,EAAU,CAAC,CAAA;AAAA,IAC1D,CAAC;AAAA,GACH;AACA,EAAA,MAAM,SAAoC,EAAC;AAC3C,EAAA,KAAA,MAAW,SAAS,QAAA,EAAU;AAC5B,IAAA,IAAI,OAAO,MAAA,CAAO,KAAA,CAAM,CAAC,CAAC,CAAA,GAAI,MAAM,CAAC,CAAA;AAAA,EACvC;AACA,EAAA,OAAO,MAAA;AACT","file":"chunk-ATNM5JHI.js","sourcesContent":["import type { ReactNode } from \"react\";\nimport type { PageData, WidgetInstance } from \"./models\";\n\n/** Context supplied to a host application's data-slot loader. */\nexport interface DataSlotLoadRequest {\n /** The slot identifier declared in `instance.settings.slot`. */\n slot: string;\n /** The full persisted block configuration. */\n instance: WidgetInstance;\n /** Page context supplied by the host renderer. */\n pageData: PageData;\n}\n\n/** A host-owned resolver for one named data slot. */\nexport type DataSlotLoader = (\n request: DataSlotLoadRequest,\n) => ReactNode | Promise<ReactNode>;\n\nexport type DataSlotLoaders = Readonly<Record<string, DataSlotLoader>>;\n\n/**\n * Resolves generic data-slot blocks before passing their output to\n * `PageRenderer`. The page-builder package deliberately does not fetch data\n * or understand a host application's domain model.\n */\nexport async function loadDataSlots(\n layout: readonly WidgetInstance[],\n loaders: DataSlotLoaders,\n pageData: PageData,\n): Promise<Record<string, ReactNode>> {\n const slots = layout.filter((instance) => instance.name === \"data-slot\");\n const resolved = await Promise.all(\n slots.map(async (instance) => {\n const slot = instance.settings?.slot;\n if (typeof slot !== \"string\" || !slot) return null;\n const loader = loaders[slot];\n if (!loader) return null;\n return [slot, await loader({ slot, instance, pageData })] as const;\n }),\n );\n const output: Record<string, ReactNode> = {};\n for (const entry of resolved) {\n if (entry) output[entry[0]] = entry[1];\n }\n return output;\n}\n"]}
@@ -0,0 +1,56 @@
1
+ "use client";
2
+ import { Button2, Button } from './chunk-J7Z4UW45.js';
3
+ import { useState, useEffect } from 'react';
4
+ import { Sun, Moon } from 'lucide-react';
5
+ import { jsx } from 'react/jsx-runtime';
6
+
7
+ function ThemeModeSwitcher({
8
+ resolved,
9
+ onToggle,
10
+ theme,
11
+ className,
12
+ size,
13
+ variant
14
+ }) {
15
+ const [mounted, setMounted] = useState(false);
16
+ useEffect(() => {
17
+ setMounted(true);
18
+ }, []);
19
+ const painted = mounted ? resolved : "light";
20
+ const next = painted === "dark" ? "light" : "dark";
21
+ const label = next === "dark" ? "Switch to dark mode" : "Switch to light mode";
22
+ const Icon = painted === "dark" ? Sun : Moon;
23
+ if (theme) {
24
+ return /* @__PURE__ */ jsx(
25
+ Button2,
26
+ {
27
+ type: "button",
28
+ variant: variant ?? "outline",
29
+ size: size ?? "sm",
30
+ theme,
31
+ title: label,
32
+ "aria-label": label,
33
+ className,
34
+ onClick: onToggle,
35
+ children: /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" })
36
+ }
37
+ );
38
+ }
39
+ return /* @__PURE__ */ jsx(
40
+ Button,
41
+ {
42
+ type: "button",
43
+ variant: "outline",
44
+ size: "icon",
45
+ title: label,
46
+ "aria-label": label,
47
+ className,
48
+ onClick: onToggle,
49
+ children: /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" })
50
+ }
51
+ );
52
+ }
53
+
54
+ export { ThemeModeSwitcher };
55
+ //# sourceMappingURL=chunk-BBI7UHOA.js.map
56
+ //# sourceMappingURL=chunk-BBI7UHOA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/theme-mode-switcher.tsx"],"names":["Button"],"mappings":";;;;;AAiBO,SAAS,iBAAA,CAAkB;AAAA,EAChC,QAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAA;AAAA,EACA,SAAA;AAAA,EACA,IAAA;AAAA,EACA;AACF,CAAA,EAOG;AACD,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,KAAK,CAAA;AAC5C,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,UAAA,CAAW,IAAI,CAAA;AAAA,EACjB,CAAA,EAAG,EAAE,CAAA;AACL,EAAA,MAAM,OAAA,GAAU,UAAU,QAAA,GAAW,OAAA;AACrC,EAAA,MAAM,IAAA,GAAO,OAAA,KAAY,MAAA,GAAS,OAAA,GAAU,MAAA;AAC5C,EAAA,MAAM,KAAA,GAAQ,IAAA,KAAS,MAAA,GAAS,qBAAA,GAAwB,sBAAA;AACxD,EAAA,MAAM,IAAA,GAAO,OAAA,KAAY,MAAA,GAAS,GAAA,GAAM,IAAA;AAExC,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,uBACE,GAAA;AAAA,MAACA,OAAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,QAAA;AAAA,QACL,SAAS,OAAA,IAAW,SAAA;AAAA,QACpB,MAAM,IAAA,IAAQ,IAAA;AAAA,QACd,KAAA;AAAA,QACA,KAAA,EAAO,KAAA;AAAA,QACP,YAAA,EAAY,KAAA;AAAA,QACZ,SAAA;AAAA,QACA,OAAA,EAAS,QAAA;AAAA,QAET,QAAA,kBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAU,SAAA,EAAU;AAAA;AAAA,KAC5B;AAAA,EAEJ;AAEA,EAAA,uBACE,GAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,QAAA;AAAA,MACL,OAAA,EAAQ,SAAA;AAAA,MACR,IAAA,EAAK,MAAA;AAAA,MACL,KAAA,EAAO,KAAA;AAAA,MACP,YAAA,EAAY,KAAA;AAAA,MACZ,SAAA;AAAA,MACA,OAAA,EAAS,QAAA;AAAA,MAET,QAAA,kBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAU,SAAA,EAAU;AAAA;AAAA,GAC5B;AAEJ","file":"chunk-BBI7UHOA.js","sourcesContent":["\"use client\";\n\nimport React, { useEffect, useState } from \"react\";\nimport { Moon, Sun } from \"lucide-react\";\nimport { Button, type ButtonProps } from \"../primitives\";\nimport { Button as ChromeButton } from \"../primitives/components/ui/button\";\nimport type { ThemeStyle } from \"../models\";\nimport type { ResolvedColorMode } from \"../utils\";\n\n/**\n * Light / dark toggle. Public sites pass `theme` so the button uses\n * page-builder primitives; the builder chrome omits it and matches the\n * other icon buttons in the top bar.\n *\n * Preference starts as system (OS). The first click pins an explicit\n * light or dark side; later clicks flip between those two.\n */\nexport function ThemeModeSwitcher({\n resolved,\n onToggle,\n theme,\n className,\n size,\n variant,\n}: {\n resolved: ResolvedColorMode;\n onToggle: () => void;\n theme?: ThemeStyle;\n className?: string;\n size?: ButtonProps[\"size\"];\n variant?: ButtonProps[\"variant\"];\n}) {\n const [mounted, setMounted] = useState(false);\n useEffect(() => {\n setMounted(true);\n }, []);\n const painted = mounted ? resolved : \"light\";\n const next = painted === \"dark\" ? \"light\" : \"dark\";\n const label = next === \"dark\" ? \"Switch to dark mode\" : \"Switch to light mode\";\n const Icon = painted === \"dark\" ? Sun : Moon;\n\n if (theme) {\n return (\n <Button\n type=\"button\"\n variant={variant ?? \"outline\"}\n size={size ?? \"sm\"}\n theme={theme}\n title={label}\n aria-label={label}\n className={className}\n onClick={onToggle}\n >\n <Icon className=\"h-4 w-4\" />\n </Button>\n );\n }\n\n return (\n <ChromeButton\n type=\"button\"\n variant=\"outline\"\n size=\"icon\"\n title={label}\n aria-label={label}\n className={className}\n onClick={onToggle}\n >\n <Icon className=\"h-4 w-4\" />\n </ChromeButton>\n );\n}\n"]}