framefields 2.14.0 → 2.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (334) hide show
  1. package/NOTICE.md +5 -1
  2. package/dist/audio/index.d.mts +3 -3
  3. package/dist/audio/index.mjs +10 -10
  4. package/dist/{audio-DFwRbID_.mjs → audio-6TfPlfl4.mjs} +3 -3
  5. package/dist/{audio-DFwRbID_.mjs.map → audio-6TfPlfl4.mjs.map} +1 -1
  6. package/dist/{audio-CdCuGK5d.d.mts → audio-7oqTUi4G.d.mts} +2 -2
  7. package/dist/{audio-CdCuGK5d.d.mts.map → audio-7oqTUi4G.d.mts.map} +1 -1
  8. package/dist/cli/check-worker.mjs +44 -44
  9. package/dist/cli.mjs +1 -1
  10. package/dist/cloud/index.d.mts.map +1 -1
  11. package/dist/cloud/index.mjs +1 -1
  12. package/dist/{cloud-Cj1TIme8.mjs → cloud-jnk1hPYf.mjs} +2 -2
  13. package/dist/{cloud-Cj1TIme8.mjs.map → cloud-jnk1hPYf.mjs.map} +1 -1
  14. package/dist/components/index.d.mts +11 -11
  15. package/dist/components/index.mjs +43 -43
  16. package/dist/{dist-Kbf-JTry.mjs → dist-BtI6ukB5.mjs} +2 -2
  17. package/dist/{dist-Kbf-JTry.mjs.map → dist-BtI6ukB5.mjs.map} +1 -1
  18. package/dist/{dist-B8Nby2CU.mjs → dist-COOpgG9G.mjs} +4 -3
  19. package/dist/{dist-B8Nby2CU.mjs.map → dist-COOpgG9G.mjs.map} +1 -1
  20. package/dist/{dist--Uu5bQ_6.mjs → dist-XqlFM2a8.mjs} +13733 -5323
  21. package/dist/dist-XqlFM2a8.mjs.map +1 -0
  22. package/dist/{dist-CiTgmfUw.mjs → dist-f1zkl69f.mjs} +4 -4
  23. package/dist/dist-f1zkl69f.mjs.map +1 -0
  24. package/dist/{dist-B_rSWeOz.mjs → dist-umQOWz0a.mjs} +1 -1
  25. package/dist/effects/index.d.mts +4 -4
  26. package/dist/effects/index.mjs +35 -35
  27. package/dist/{effects-WMgv8ZaD.mjs → effects-DlRMovU5.mjs} +2 -2
  28. package/dist/{effects-WMgv8ZaD.mjs.map → effects-DlRMovU5.mjs.map} +1 -1
  29. package/dist/fonts/index.d.mts +1 -1
  30. package/dist/fonts/index.mjs +2 -2
  31. package/dist/{fonts-OW3yAfO5.mjs → fonts-BWYcXjyK.mjs} +3 -3
  32. package/dist/fonts-BWYcXjyK.mjs.map +1 -0
  33. package/dist/{gpu-R4T2Tndu.mjs → gpu-CH1PdM4T.mjs} +2 -2
  34. package/dist/{gpu-R4T2Tndu.mjs.map → gpu-CH1PdM4T.mjs.map} +1 -1
  35. package/dist/{index-CEKxvGY-.d.mts → index-BHTycml5.d.mts} +2 -2
  36. package/dist/{index-CEKxvGY-.d.mts.map → index-BHTycml5.d.mts.map} +1 -1
  37. package/dist/{index-DoP6EiHj.d.mts → index-BcxxxwhV.d.mts} +4 -4
  38. package/dist/{index-DoP6EiHj.d.mts.map → index-BcxxxwhV.d.mts.map} +1 -1
  39. package/dist/{index-Bv7gxGK1.d.mts → index-BnB_Ou2y.d.mts} +2 -2
  40. package/dist/index-BnB_Ou2y.d.mts.map +1 -0
  41. package/dist/index-C-V6CAhP.d.mts.map +1 -1
  42. package/dist/{index-D1FqV1eu.d.mts → index-CMhkkc56.d.mts} +43 -11
  43. package/dist/index-CMhkkc56.d.mts.map +1 -0
  44. package/dist/{index-B0Vq8Bwf.d.mts → index-CYVpYGM-.d.mts} +2 -2
  45. package/dist/{index-B0Vq8Bwf.d.mts.map → index-CYVpYGM-.d.mts.map} +1 -1
  46. package/dist/{index-C7-p9zwU.d.mts → index-DhL7ckvs.d.mts} +5 -5
  47. package/dist/index-DhL7ckvs.d.mts.map +1 -0
  48. package/dist/{index-9xte4JgL.d.mts → index-DkAjKnhW.d.mts} +1464 -559
  49. package/dist/index-DkAjKnhW.d.mts.map +1 -0
  50. package/dist/{index-GA9_Z8Fn.d.mts → index-RILu3ULT.d.mts} +2 -2
  51. package/dist/{index-GA9_Z8Fn.d.mts.map → index-RILu3ULT.d.mts.map} +1 -1
  52. package/dist/{index-C5sgRLlG.d.mts → index-TCtdSXd7.d.mts} +3 -1
  53. package/dist/index-TCtdSXd7.d.mts.map +1 -0
  54. package/dist/{index-CRaydvLi.d.mts → index-s2qQ8ifZ.d.mts} +886 -51
  55. package/dist/index-s2qQ8ifZ.d.mts.map +1 -0
  56. package/dist/index.d.mts +13 -13
  57. package/dist/index.mjs +52 -52
  58. package/dist/preview/index.d.mts +3 -3
  59. package/dist/preview/index.mjs +10 -10
  60. package/dist/preview-BeGF1Bb1.mjs +1002 -0
  61. package/dist/preview-BeGF1Bb1.mjs.map +1 -0
  62. package/dist/preview-engine/audio.mjs +1 -1
  63. package/dist/preview-engine/{chunk-64L4GUOF.mjs → chunk-4F3DG6YB.mjs} +2 -2
  64. package/dist/preview-engine/chunk-A2OTOW3B.mjs +4694 -0
  65. package/dist/preview-engine/{chunk-GNDE3OXQ.mjs → chunk-BR56TQBP.mjs} +1 -1
  66. package/dist/preview-engine/{chunk-ADLIF544.mjs → chunk-H2XKXXAU.mjs} +1 -1
  67. package/dist/preview-engine/chunk-NDUODAY2.mjs +3 -0
  68. package/dist/preview-engine/{chunk-FZ4RD7HV.mjs → chunk-QAQJSWUT.mjs} +1 -1
  69. package/dist/preview-engine/chunk-SWRGQTVC.mjs +138 -0
  70. package/dist/preview-engine/{chunk-52X7SURQ.mjs → chunk-TEA3GVBJ.mjs} +1 -1
  71. package/dist/preview-engine/chunk-VM2ZBPLM.mjs +644 -0
  72. package/dist/preview-engine/{chunk-UBY2UYEL.mjs → chunk-XSHNQJ7L.mjs} +1 -1
  73. package/dist/preview-engine/components.mjs +1 -1
  74. package/dist/preview-engine/effects.mjs +1 -1
  75. package/dist/preview-engine/fonts.mjs +1 -1
  76. package/dist/preview-engine/framefields.mjs +1 -1
  77. package/dist/preview-engine/player.mjs +2 -2
  78. package/dist/preview-engine/{renderers-DU7KPFVV.mjs → renderers-6C7NWWDX.mjs} +1 -1
  79. package/dist/preview-engine/renderers-HHVGNMSJ.mjs +206 -0
  80. package/dist/preview-engine/{src-YXNX4MLK.mjs → src-RCNEKIRP.mjs} +1 -1
  81. package/dist/preview-page/index.html +19 -0
  82. package/dist/preview-page/main.css +1 -0
  83. package/dist/preview-page/main.js +327 -0
  84. package/dist/{program-tFKCWU2j.mjs → program-CMigyfso.mjs} +829 -52
  85. package/dist/program-CMigyfso.mjs.map +1 -0
  86. package/dist/renderer/index.d.mts +2 -2
  87. package/dist/renderer/index.mjs +2 -2
  88. package/dist/{renderer-DkOuQi84.mjs → renderer-0GMEL_Zi.mjs} +3 -3
  89. package/dist/{renderer-DkOuQi84.mjs.map → renderer-0GMEL_Zi.mjs.map} +1 -1
  90. package/dist/{renderer-BGp0An5A.mjs → renderer-3Wv2ZBJG.mjs} +3 -3
  91. package/dist/{renderer-BGp0An5A.mjs.map → renderer-3Wv2ZBJG.mjs.map} +1 -1
  92. package/dist/{renderer-BVIXKfbC.mjs → renderer-4nXkaAWu.mjs} +1178 -199
  93. package/dist/renderer-4nXkaAWu.mjs.map +1 -0
  94. package/dist/{renderer-Cw6_NL2i.mjs → renderer-6SnfLXeg.mjs} +3 -3
  95. package/dist/{renderer-Cw6_NL2i.mjs.map → renderer-6SnfLXeg.mjs.map} +1 -1
  96. package/dist/{renderer-BVU22lBS.mjs → renderer-8gHw3O0P.mjs} +2 -2
  97. package/dist/{renderer-BVU22lBS.mjs.map → renderer-8gHw3O0P.mjs.map} +1 -1
  98. package/dist/{renderer-BjDddtw9.mjs → renderer-AOBglZHC.mjs} +2 -2
  99. package/dist/{renderer-D-KHHWQD.mjs → renderer-B0bSARK3.mjs} +3 -3
  100. package/dist/{renderer-D-KHHWQD.mjs.map → renderer-B0bSARK3.mjs.map} +1 -1
  101. package/dist/{renderer-CCxk-RJR.mjs → renderer-B2_tuRfl.mjs} +2 -2
  102. package/dist/{renderer-CCxk-RJR.mjs.map → renderer-B2_tuRfl.mjs.map} +1 -1
  103. package/dist/{renderer-k5d7JSbs.mjs → renderer-B82FhkEr.mjs} +3 -3
  104. package/dist/{renderer-k5d7JSbs.mjs.map → renderer-B82FhkEr.mjs.map} +1 -1
  105. package/dist/{renderer-I0Hh9cLK.mjs → renderer-B9lzA0PY.mjs} +3 -3
  106. package/dist/{renderer-I0Hh9cLK.mjs.map → renderer-B9lzA0PY.mjs.map} +1 -1
  107. package/dist/{renderer-Dwwnx7Dk.mjs → renderer-BBSIWSry.mjs} +2 -2
  108. package/dist/{renderer-Dwwnx7Dk.mjs.map → renderer-BBSIWSry.mjs.map} +1 -1
  109. package/dist/{renderer-_pC-jB9O.mjs → renderer-BEKDMxbi.mjs} +2 -2
  110. package/dist/{renderer-_pC-jB9O.mjs.map → renderer-BEKDMxbi.mjs.map} +1 -1
  111. package/dist/renderer-BERGAxqA.mjs +5 -0
  112. package/dist/{renderer-raxwsiGI.mjs → renderer-BF960HY8.mjs} +3 -3
  113. package/dist/{renderer-raxwsiGI.mjs.map → renderer-BF960HY8.mjs.map} +1 -1
  114. package/dist/{renderer-Dr0tXA4k.mjs → renderer-BFwyVxCu.mjs} +3 -3
  115. package/dist/{renderer-Dr0tXA4k.mjs.map → renderer-BFwyVxCu.mjs.map} +1 -1
  116. package/dist/{renderer-DEjo6dw_.mjs → renderer-BNiwcI3-.mjs} +2 -2
  117. package/dist/{renderer-DEjo6dw_.mjs.map → renderer-BNiwcI3-.mjs.map} +1 -1
  118. package/dist/{renderer-DIEeHiQA.mjs → renderer-BPbVb2Q4.mjs} +2 -2
  119. package/dist/{renderer-DIEeHiQA.mjs.map → renderer-BPbVb2Q4.mjs.map} +1 -1
  120. package/dist/renderer-BQ_YkBMt.mjs +6 -0
  121. package/dist/{renderer-BBMtmxks.mjs → renderer-BUWxlA8T.mjs} +3 -3
  122. package/dist/{renderer-BBMtmxks.mjs.map → renderer-BUWxlA8T.mjs.map} +1 -1
  123. package/dist/renderer-BW0Tjsv9.mjs +5 -0
  124. package/dist/{renderer-Dgj46uEU.mjs → renderer-BX8liu-e.mjs} +2 -2
  125. package/dist/{renderer-ZnrEfkYh.mjs → renderer-BXIwDAr_.mjs} +2 -2
  126. package/dist/{renderer-ZnrEfkYh.mjs.map → renderer-BXIwDAr_.mjs.map} +1 -1
  127. package/dist/{renderer-DA8YEo_d.mjs → renderer-B_Hy1W-g.mjs} +3 -3
  128. package/dist/{renderer-DA8YEo_d.mjs.map → renderer-B_Hy1W-g.mjs.map} +1 -1
  129. package/dist/{renderer-iMiYStcW.mjs → renderer-Bb6cvSgh.mjs} +2 -2
  130. package/dist/{renderer-iMiYStcW.mjs.map → renderer-Bb6cvSgh.mjs.map} +1 -1
  131. package/dist/{renderer-BacY4nh8.mjs → renderer-BdppwWC9.mjs} +2 -2
  132. package/dist/{renderer-BacY4nh8.mjs.map → renderer-BdppwWC9.mjs.map} +1 -1
  133. package/dist/{renderer-CrxwW6VQ.mjs → renderer-Bhc24HVe.mjs} +3 -3
  134. package/dist/{renderer-CrxwW6VQ.mjs.map → renderer-Bhc24HVe.mjs.map} +1 -1
  135. package/dist/{renderer-BH7UCMPQ.mjs → renderer-BiNA2wF0.mjs} +2 -2
  136. package/dist/{renderer-BH7UCMPQ.mjs.map → renderer-BiNA2wF0.mjs.map} +1 -1
  137. package/dist/{renderer-DVPgWHZw.mjs → renderer-BmoBgTp5.mjs} +3 -3
  138. package/dist/{renderer-DVPgWHZw.mjs.map → renderer-BmoBgTp5.mjs.map} +1 -1
  139. package/dist/{renderer-C20efMI0.mjs → renderer-BmqFmCWS.mjs} +3 -3
  140. package/dist/{renderer-C20efMI0.mjs.map → renderer-BmqFmCWS.mjs.map} +1 -1
  141. package/dist/{renderer-B0yVUOPP.mjs → renderer-BnVwAObV.mjs} +2 -2
  142. package/dist/{renderer-B0yVUOPP.mjs.map → renderer-BnVwAObV.mjs.map} +1 -1
  143. package/dist/{renderer-CP8wLzTU.mjs → renderer-BxttZHme.mjs} +2 -2
  144. package/dist/{renderer-CP8wLzTU.mjs.map → renderer-BxttZHme.mjs.map} +1 -1
  145. package/dist/renderer-BzyPdUD1.mjs +5 -0
  146. package/dist/renderer-C0hM-mtY.mjs +5 -0
  147. package/dist/renderer-C6cyUTvk.mjs +5 -0
  148. package/dist/{renderer-BOSZAdgF.mjs → renderer-C8E4XsSg.mjs} +2 -2
  149. package/dist/{renderer-BOSZAdgF.mjs.map → renderer-C8E4XsSg.mjs.map} +1 -1
  150. package/dist/renderer-C8zY3pzk.mjs +5 -0
  151. package/dist/{renderer-DWq9gYRw.mjs → renderer-C9U-LY50.mjs} +3 -3
  152. package/dist/{renderer-DWq9gYRw.mjs.map → renderer-C9U-LY50.mjs.map} +1 -1
  153. package/dist/{renderer-Dj2H5JPR.mjs → renderer-CB2JVu5x.mjs} +3 -3
  154. package/dist/{renderer-Dj2H5JPR.mjs.map → renderer-CB2JVu5x.mjs.map} +1 -1
  155. package/dist/{renderer-Bcu3UrI-.mjs → renderer-CC4YBJ8Z.mjs} +3 -3
  156. package/dist/{renderer-Bcu3UrI-.mjs.map → renderer-CC4YBJ8Z.mjs.map} +1 -1
  157. package/dist/renderer-CEkSOyKu.mjs +5 -0
  158. package/dist/{renderer-DzLrvCB2.mjs → renderer-CIycc5O-.mjs} +2 -2
  159. package/dist/{renderer-DzLrvCB2.mjs.map → renderer-CIycc5O-.mjs.map} +1 -1
  160. package/dist/renderer-CJYtfa4x.mjs +5 -0
  161. package/dist/{renderer-BeNl_6EG.mjs → renderer-CJraQlV-.mjs} +2 -2
  162. package/dist/{renderer-BeNl_6EG.mjs.map → renderer-CJraQlV-.mjs.map} +1 -1
  163. package/dist/renderer-CKMtHGZh.mjs +5 -0
  164. package/dist/renderer-CLzicoiy.mjs +5 -0
  165. package/dist/renderer-CM2A4BHd.mjs +5 -0
  166. package/dist/{renderer-DtMVitEF.mjs → renderer-COWGWtob.mjs} +2 -2
  167. package/dist/{renderer-DtMVitEF.mjs.map → renderer-COWGWtob.mjs.map} +1 -1
  168. package/dist/{renderer-CT3zkfbf.mjs → renderer-COxG2XGf.mjs} +2 -2
  169. package/dist/{renderer-CT3zkfbf.mjs.map → renderer-COxG2XGf.mjs.map} +1 -1
  170. package/dist/{renderer-DNxWOz8Q.mjs → renderer-CQDCIsQm.mjs} +2 -2
  171. package/dist/{renderer-DNxWOz8Q.mjs.map → renderer-CQDCIsQm.mjs.map} +1 -1
  172. package/dist/{renderer-C5AoaymD.mjs → renderer-CRUeag8i.mjs} +3 -3
  173. package/dist/{renderer-C5AoaymD.mjs.map → renderer-CRUeag8i.mjs.map} +1 -1
  174. package/dist/{renderer-ngmYIIob.mjs → renderer-CWVput06.mjs} +3 -3
  175. package/dist/{renderer-ngmYIIob.mjs.map → renderer-CWVput06.mjs.map} +1 -1
  176. package/dist/renderer-CZlHjcxr.mjs +5 -0
  177. package/dist/{renderer-0rveCDm-.mjs → renderer-CbbnBLOB.mjs} +3 -3
  178. package/dist/{renderer-0rveCDm-.mjs.map → renderer-CbbnBLOB.mjs.map} +1 -1
  179. package/dist/renderer-CbimvSU8.mjs +5 -0
  180. package/dist/renderer-Ccvc63yd.mjs +5 -0
  181. package/dist/renderer-Cdp-SGfq.mjs +5 -0
  182. package/dist/renderer-CeTcSs3e.mjs +5 -0
  183. package/dist/{renderer-Brmbl12Y.mjs → renderer-CfLZein2.mjs} +3 -3
  184. package/dist/{renderer-Brmbl12Y.mjs.map → renderer-CfLZein2.mjs.map} +1 -1
  185. package/dist/{renderer-BJ8ea92W.mjs → renderer-Ch-q1O-q.mjs} +3 -3
  186. package/dist/{renderer-BJ8ea92W.mjs.map → renderer-Ch-q1O-q.mjs.map} +1 -1
  187. package/dist/{renderer-CP108ABB.mjs → renderer-Ch5JvJWl.mjs} +2 -2
  188. package/dist/{renderer-CP108ABB.mjs.map → renderer-Ch5JvJWl.mjs.map} +1 -1
  189. package/dist/{renderer-47y12Z37.mjs → renderer-ChtEzq-R.mjs} +2 -2
  190. package/dist/{renderer-47y12Z37.mjs.map → renderer-ChtEzq-R.mjs.map} +1 -1
  191. package/dist/{renderer-DhyMfG1v.mjs → renderer-Cj9nTC5l.mjs} +3 -3
  192. package/dist/{renderer-DhyMfG1v.mjs.map → renderer-Cj9nTC5l.mjs.map} +1 -1
  193. package/dist/{renderer-BDzn1AKF.mjs → renderer-CqT8HsSS.mjs} +2 -2
  194. package/dist/{renderer-BDzn1AKF.mjs.map → renderer-CqT8HsSS.mjs.map} +1 -1
  195. package/dist/{renderer-B7G1KohJ.mjs → renderer-CuQjMhdV.mjs} +2 -2
  196. package/dist/renderer-CvNuu52U.mjs +5 -0
  197. package/dist/renderer-CwciC0oI.mjs +5 -0
  198. package/dist/renderer-CysLUbIr.mjs +5 -0
  199. package/dist/{renderer-Cm0tsbQH.mjs → renderer-Cz30EVws.mjs} +2 -2
  200. package/dist/{renderer-Cm0tsbQH.mjs.map → renderer-Cz30EVws.mjs.map} +1 -1
  201. package/dist/renderer-D3A22Vxb.mjs +5 -0
  202. package/dist/renderer-D5SY9EmA.mjs +5 -0
  203. package/dist/renderer-D8h3ZvaE.mjs +5 -0
  204. package/dist/renderer-DE-B6N9n.mjs +5 -0
  205. package/dist/renderer-DETZTI7t.mjs +5 -0
  206. package/dist/{renderer-nHS3Sius.mjs → renderer-DHoX-5U_.mjs} +3 -3
  207. package/dist/{renderer-nHS3Sius.mjs.map → renderer-DHoX-5U_.mjs.map} +1 -1
  208. package/dist/{renderer-BWSRryIA.mjs → renderer-DOkm0Ycd.mjs} +2 -2
  209. package/dist/{renderer-BWSRryIA.mjs.map → renderer-DOkm0Ycd.mjs.map} +1 -1
  210. package/dist/{renderer-BHYJlK6H.d.mts → renderer-DU3f6ZrS.d.mts} +2 -2
  211. package/dist/{renderer-BHYJlK6H.d.mts.map → renderer-DU3f6ZrS.d.mts.map} +1 -1
  212. package/dist/{renderer-BpVOk9ux.mjs → renderer-DUzv-shq.mjs} +2 -2
  213. package/dist/{renderer-BpVOk9ux.mjs.map → renderer-DUzv-shq.mjs.map} +1 -1
  214. package/dist/renderer-DWnDj0IM.mjs +5 -0
  215. package/dist/renderer-DcGUIbQF.mjs +5 -0
  216. package/dist/renderer-Dfq6FoNO.mjs +5 -0
  217. package/dist/renderer-DhasXW6S.mjs +3 -0
  218. package/dist/{renderer-NRMlYkX6.mjs → renderer-DhnOWnEA.mjs} +3 -3
  219. package/dist/{renderer-NRMlYkX6.mjs.map → renderer-DhnOWnEA.mjs.map} +1 -1
  220. package/dist/{renderer-COgwYqev.mjs → renderer-Dhy1XHzz.mjs} +3 -3
  221. package/dist/{renderer-COgwYqev.mjs.map → renderer-Dhy1XHzz.mjs.map} +1 -1
  222. package/dist/renderer-DjCvpsV_.mjs +5 -0
  223. package/dist/{renderer-BfZNIiSv.mjs → renderer-DjJshz9Y.mjs} +2 -2
  224. package/dist/{renderer-BfZNIiSv.mjs.map → renderer-DjJshz9Y.mjs.map} +1 -1
  225. package/dist/{renderer-CKo7VR8x.mjs → renderer-DmTUIdus.mjs} +3 -3
  226. package/dist/{renderer-CKo7VR8x.mjs.map → renderer-DmTUIdus.mjs.map} +1 -1
  227. package/dist/{renderer-Baw6Utxi.mjs → renderer-Dq7AioJa.mjs} +2 -2
  228. package/dist/{renderer-Baw6Utxi.mjs.map → renderer-Dq7AioJa.mjs.map} +1 -1
  229. package/dist/renderer-DrAaM6JD.mjs +5 -0
  230. package/dist/{renderer-D-GWBoVT.mjs → renderer-Dt4sqNEu.mjs} +2 -2
  231. package/dist/{renderer-D-GWBoVT.mjs.map → renderer-Dt4sqNEu.mjs.map} +1 -1
  232. package/dist/{renderer-FYOL5Za6.mjs → renderer-Dtcs4idV.mjs} +3 -3
  233. package/dist/{renderer-FYOL5Za6.mjs.map → renderer-Dtcs4idV.mjs.map} +1 -1
  234. package/dist/renderer-Dxlv8LYm.mjs +5 -0
  235. package/dist/{renderer-D-RhYvVl.mjs → renderer-Gj8SrE2W.mjs} +2 -2
  236. package/dist/{renderer-D-RhYvVl.mjs.map → renderer-Gj8SrE2W.mjs.map} +1 -1
  237. package/dist/{renderer-D_j1WKMD.mjs → renderer-KfnXDJS0.mjs} +3 -3
  238. package/dist/{renderer-D_j1WKMD.mjs.map → renderer-KfnXDJS0.mjs.map} +1 -1
  239. package/dist/{renderer-Bpm145BW.mjs → renderer-MXVlg4p5.mjs} +3 -3
  240. package/dist/{renderer-Bpm145BW.mjs.map → renderer-MXVlg4p5.mjs.map} +1 -1
  241. package/dist/{renderer-Nnmi8Gt6.mjs → renderer-N2b6QZ1E.mjs} +3 -3
  242. package/dist/{renderer-Nnmi8Gt6.mjs.map → renderer-N2b6QZ1E.mjs.map} +1 -1
  243. package/dist/renderer-Pb43OO2t.mjs +5 -0
  244. package/dist/{renderer-Ca1KjNCO.mjs → renderer-Q7gDzm8c.mjs} +2 -2
  245. package/dist/{renderer-Ca1KjNCO.mjs.map → renderer-Q7gDzm8c.mjs.map} +1 -1
  246. package/dist/{renderer-D2wNFNRf.mjs → renderer-RCiANtRV.mjs} +2 -2
  247. package/dist/{renderer-D2wNFNRf.mjs.map → renderer-RCiANtRV.mjs.map} +1 -1
  248. package/dist/{renderer-Cqb7PGrI.mjs → renderer-Sig9nZcI.mjs} +2 -2
  249. package/dist/renderer-VQbm-cGr.mjs +5 -0
  250. package/dist/{renderer-W1bVNVR6.mjs → renderer-fabBgwQX.mjs} +3 -3
  251. package/dist/{renderer-W1bVNVR6.mjs.map → renderer-fabBgwQX.mjs.map} +1 -1
  252. package/dist/{renderer-zRq0j6Xy.mjs → renderer-g-0PCNoo.mjs} +3 -3
  253. package/dist/{renderer-zRq0j6Xy.mjs.map → renderer-g-0PCNoo.mjs.map} +1 -1
  254. package/dist/{renderer-2PjR3w-q.mjs → renderer-gmHKIbKI.mjs} +3 -3
  255. package/dist/{renderer-2PjR3w-q.mjs.map → renderer-gmHKIbKI.mjs.map} +1 -1
  256. package/dist/{renderer-03mYJLgX.mjs → renderer-kVZwiRoK.mjs} +3 -3
  257. package/dist/{renderer-03mYJLgX.mjs.map → renderer-kVZwiRoK.mjs.map} +1 -1
  258. package/dist/renderer-oPMypDM1.mjs +5 -0
  259. package/dist/{renderer-DcAKDAnS.mjs → renderer-p7tgxP-A.mjs} +3 -3
  260. package/dist/{renderer-DcAKDAnS.mjs.map → renderer-p7tgxP-A.mjs.map} +1 -1
  261. package/dist/{renderer-jUKdkmG5.mjs → renderer-tvYj306A.mjs} +81 -78
  262. package/dist/renderer-tvYj306A.mjs.map +1 -0
  263. package/dist/renderer-xvWGpVyp.mjs +5 -0
  264. package/dist/renderer-zafZbD6Q.mjs +5 -0
  265. package/dist/{renderers-CP8CFWDs-CshljORp.mjs → renderers-CP8CFWDs-DLjtjrwx.mjs} +2 -2
  266. package/dist/{renderers-CP8CFWDs-CshljORp.mjs.map → renderers-CP8CFWDs-DLjtjrwx.mjs.map} +1 -1
  267. package/dist/sam/index.d.mts +2 -2
  268. package/dist/sam/index.mjs +1 -1
  269. package/dist/signals/index.d.mts +4 -4
  270. package/dist/signals/index.mjs +4 -4
  271. package/dist/{src-BU6vm9sP-DdTHmCr4.mjs → src-B23p_eh7-Cj6-lvV6.mjs} +293 -6
  272. package/dist/src-B23p_eh7-Cj6-lvV6.mjs.map +1 -0
  273. package/dist/{src-Dy4gnc6w.mjs → src-CoHAjviq.mjs} +1349 -177
  274. package/dist/src-CoHAjviq.mjs.map +1 -0
  275. package/dist/storage/index.mjs +1 -1
  276. package/package.json +63 -60
  277. package/dist/dist--Uu5bQ_6.mjs.map +0 -1
  278. package/dist/dist-CiTgmfUw.mjs.map +0 -1
  279. package/dist/fonts-OW3yAfO5.mjs.map +0 -1
  280. package/dist/index-9xte4JgL.d.mts.map +0 -1
  281. package/dist/index-Bv7gxGK1.d.mts.map +0 -1
  282. package/dist/index-C5sgRLlG.d.mts.map +0 -1
  283. package/dist/index-C7-p9zwU.d.mts.map +0 -1
  284. package/dist/index-CRaydvLi.d.mts.map +0 -1
  285. package/dist/index-D1FqV1eu.d.mts.map +0 -1
  286. package/dist/preview-D7BGmE1E.mjs +0 -2446
  287. package/dist/preview-D7BGmE1E.mjs.map +0 -1
  288. package/dist/preview-engine/chunk-5DZTPUMH.mjs +0 -2568
  289. package/dist/preview-engine/chunk-NCQHOGZK.mjs +0 -3
  290. package/dist/preview-engine/chunk-PH3UUX6A.mjs +0 -138
  291. package/dist/preview-engine/chunk-UPZURPJY.mjs +0 -2227
  292. package/dist/preview-engine/renderers-DLJOA3BM.mjs +0 -228
  293. package/dist/program-tFKCWU2j.mjs.map +0 -1
  294. package/dist/renderer-6_bzbbXt.mjs +0 -5
  295. package/dist/renderer-8M-9G6F_.mjs +0 -5
  296. package/dist/renderer-B5OzKvF8.mjs +0 -5
  297. package/dist/renderer-BBCZ2qbE.mjs +0 -5
  298. package/dist/renderer-BChbxCux.mjs +0 -5
  299. package/dist/renderer-BGeMPr8C.mjs +0 -5
  300. package/dist/renderer-BPQ8Pkjb.mjs +0 -5
  301. package/dist/renderer-BTRpA3HD.mjs +0 -5
  302. package/dist/renderer-BVIXKfbC.mjs.map +0 -1
  303. package/dist/renderer-BVsECSn-.mjs +0 -5
  304. package/dist/renderer-Bgos68gc.mjs +0 -6
  305. package/dist/renderer-BjHOvoqO.mjs +0 -5
  306. package/dist/renderer-BjXMPPlV.mjs +0 -5
  307. package/dist/renderer-Byobxqkv.mjs +0 -5
  308. package/dist/renderer-CKrsg3EG.mjs +0 -5
  309. package/dist/renderer-Cj875NuH.mjs +0 -5
  310. package/dist/renderer-CnmzJoMv.mjs +0 -5
  311. package/dist/renderer-CtklDaMg.mjs +0 -5
  312. package/dist/renderer-D1tK3in_.mjs +0 -5
  313. package/dist/renderer-D2yc9P61.mjs +0 -5
  314. package/dist/renderer-D4v-JvSr.mjs +0 -5
  315. package/dist/renderer-D5yp74NL.mjs +0 -3
  316. package/dist/renderer-D7WRWDwB.mjs +0 -5
  317. package/dist/renderer-DGvA0tdB.mjs +0 -5
  318. package/dist/renderer-DO7v5Sdm.mjs +0 -5
  319. package/dist/renderer-DRVvt7-V.mjs +0 -5
  320. package/dist/renderer-DYMCd3jL.mjs +0 -5
  321. package/dist/renderer-DmHKw-MM.mjs +0 -5
  322. package/dist/renderer-DoDsuZ6G.mjs +0 -5
  323. package/dist/renderer-EpgclS70.mjs +0 -5
  324. package/dist/renderer-GroKiYyK.mjs +0 -5
  325. package/dist/renderer-MQ5K_xIS.mjs +0 -5
  326. package/dist/renderer-U43SflML.mjs +0 -5
  327. package/dist/renderer-UqOmBgCv.mjs +0 -5
  328. package/dist/renderer-XLULgJM0.mjs +0 -5
  329. package/dist/renderer-jUKdkmG5.mjs.map +0 -1
  330. package/dist/renderer-lNjxY1GG.mjs +0 -5
  331. package/dist/renderer-ukufL7pl.mjs +0 -5
  332. package/dist/renderer-wb0NCKdF.mjs +0 -5
  333. package/dist/src-BU6vm9sP-DdTHmCr4.mjs.map +0 -1
  334. package/dist/src-Dy4gnc6w.mjs.map +0 -1
@@ -1,8 +1,9 @@
1
1
  import { Dn as sampleMediaSignal, Et as emojiPresentation, F as MediaTimeRemapInputSchema, It as getActiveMediaMetadata, St as createVirtualMedia, Xt as isSignal, _t as compositionFrameContext, dn as parseCssGradient, ht as assertNever, in as mixColors, l as Color, mt as assertFps, un as parseCssColor, y as Effect, zn as validateMediaTimeRemap } from "./dist-C8XSqfTx.mjs";
2
2
  import { t as ColorSchema } from "./dist-BSKAbyea.mjs";
3
- import { Dt as AdvancedTextAnimatorSchema, Hn as signalRegistry, Tt as AETextAnimatorSchema, Vt as KineticMarqueeConfigSchema, dn as TypewriterAnimatorSchema, in as TextPathOptionsSchema } from "./dist--Uu5bQ_6.mjs";
3
+ import { Cr as signalRegistry, Kn as TypewriterAnimatorSchema, Sn as KineticMarqueeConfigSchema, cn as AdvancedTextAnimatorSchema, on as AETextAnimatorSchema, zn as TextPathOptionsSchema } from "./dist-XqlFM2a8.mjs";
4
4
  import { z } from "zod";
5
5
  import { loadYoga } from "yoga-layout/load";
6
+ import gsapModule from "gsap";
6
7
 
7
8
  //#region ../compositions/dist/program/index.mjs
8
9
  let yogaInstance = null;
@@ -391,6 +392,14 @@ function collectInlineSignals(nodes, out = {}) {
391
392
  }
392
393
  return out;
393
394
  }
395
+ const PROP_ALIASES = {
396
+ rotationX: "rotateX",
397
+ rotationY: "rotateY",
398
+ rotationZ: "rotateZ"
399
+ };
400
+ function normalizeAnimatableProp(prop) {
401
+ return PROP_ALIASES[prop] ?? prop;
402
+ }
394
403
  const isKeyframeTrack = (t) => !t.source || t.source.type === "keyframe";
395
404
  /**
396
405
  * Merges keyframe tracks that animate the same prop into one sorted track,
@@ -577,6 +586,15 @@ var LayerAnimation = class LayerAnimation$1 {
577
586
  static rotateZ(fromAngle, toAngle, options = {}) {
578
587
  return new LayerAnimation$1().fromTo("rotateZ", fromAngle, toAngle, options);
579
588
  }
589
+ static rotationX(fromAngle, toAngle, options = {}) {
590
+ return new LayerAnimation$1().fromTo("rotateX", fromAngle, toAngle, options);
591
+ }
592
+ static rotationY(fromAngle, toAngle, options = {}) {
593
+ return new LayerAnimation$1().fromTo("rotateY", fromAngle, toAngle, options);
594
+ }
595
+ static rotationZ(fromAngle, toAngle, options = {}) {
596
+ return new LayerAnimation$1().fromTo("rotateZ", fromAngle, toAngle, options);
597
+ }
580
598
  static rotation(fromAngle, toAngle, options = {}) {
581
599
  return new LayerAnimation$1().fromTo("rotation", fromAngle, toAngle, options);
582
600
  }
@@ -599,16 +617,18 @@ var LayerAnimation = class LayerAnimation$1 {
599
617
  * - `N`: repeats N times after the initial iteration (total N + 1 iterations).
600
618
  */
601
619
  repeat(count = -1, prop) {
620
+ const canonical = prop ? normalizeAnimatableProp(prop) : void 0;
602
621
  this.defaultRepeat = count;
603
- for (const track of this.tracks) if (!prop || track.prop === prop) track.repeat = count;
622
+ for (const track of this.tracks) if (!canonical || track.prop === canonical) track.repeat = count;
604
623
  return this;
605
624
  }
606
625
  /**
607
626
  * Enables or disables yoyo (alternate playback direction on each repeat iteration).
608
627
  */
609
628
  yoyo(enable = true, prop) {
629
+ const canonical = prop ? normalizeAnimatableProp(prop) : void 0;
610
630
  this.defaultYoyo = enable;
611
- for (const track of this.tracks) if (!prop || track.prop === prop) track.yoyo = enable;
631
+ for (const track of this.tracks) if (!canonical || track.prop === canonical) track.yoyo = enable;
612
632
  return this;
613
633
  }
614
634
  /**
@@ -623,7 +643,8 @@ var LayerAnimation = class LayerAnimation$1 {
623
643
  /**
624
644
  * Creates a keyframed track animating from fromValue to toValue.
625
645
  */
626
- fromTo(prop, fromValue, toValue, options = {}) {
646
+ fromTo(rawProp, fromValue, toValue, options = {}) {
647
+ const prop = normalizeAnimatableProp(rawProp);
627
648
  const start = options.from ?? options.start ?? options.fromFrame ?? 0;
628
649
  const end = options.to ?? options.end ?? options.toFrame ?? (options.durationFrames !== void 0 ? start + options.durationFrames : start + 24);
629
650
  const ease = parseEase(options.ease);
@@ -665,7 +686,8 @@ var LayerAnimation = class LayerAnimation$1 {
665
686
  /**
666
687
  * Appends a keyframe to an existing track for prop, or creates a new track.
667
688
  */
668
- keyframe(prop, frame, value, ease) {
689
+ keyframe(rawProp, frame, value, ease) {
690
+ const prop = normalizeAnimatableProp(rawProp);
669
691
  let track = this.tracks.find((t) => t.prop === prop && (!t.source || t.source.type === "keyframe"));
670
692
  if (!track) {
671
693
  const newTrack = {
@@ -696,7 +718,8 @@ var LayerAnimation = class LayerAnimation$1 {
696
718
  * `.keys("scale", [[0, 0], [12, 1.1, "back.out"], [20, 1]])`.
697
719
  * Frames are rounded to whole frames, so beat math can be passed straight in.
698
720
  */
699
- keys(prop, keyframes, options) {
721
+ keys(rawProp, keyframes, options) {
722
+ const prop = normalizeAnimatableProp(rawProp);
700
723
  for (const [frame, value, ease] of keyframes) this.keyframe(prop, Math.round(frame), value, ease);
701
724
  if (options) {
702
725
  const track = this.tracks.find((t) => t.prop === prop && (!t.source || t.source.type === "keyframe"));
@@ -815,6 +838,18 @@ var LayerAnimation = class LayerAnimation$1 {
815
838
  rotateZ(fromAngle, toAngle, options = {}) {
816
839
  return this.fromTo("rotateZ", fromAngle, toAngle, options);
817
840
  }
841
+ /** Alias for {@link rotateX}. */
842
+ rotationX(fromAngle, toAngle, options = {}) {
843
+ return this.fromTo("rotateX", fromAngle, toAngle, options);
844
+ }
845
+ /** Alias for {@link rotateY}. */
846
+ rotationY(fromAngle, toAngle, options = {}) {
847
+ return this.fromTo("rotateY", fromAngle, toAngle, options);
848
+ }
849
+ /** Alias for {@link rotateZ}. */
850
+ rotationZ(fromAngle, toAngle, options = {}) {
851
+ return this.fromTo("rotateZ", fromAngle, toAngle, options);
852
+ }
818
853
  /**
819
854
  * Animate scale along the X axis.
820
855
  */
@@ -883,7 +918,8 @@ var LayerAnimation = class LayerAnimation$1 {
883
918
  * registered with the program automatically — or the name of a signal
884
919
  * registered with `comp.addSignal(name, signal)`.
885
920
  */
886
- signal(prop, signalOrHandleId, options = {}) {
921
+ signal(rawProp, signalOrHandleId, options = {}) {
922
+ const prop = normalizeAnimatableProp(rawProp);
887
923
  const { handleId, inline } = resolveSignalArg(signalOrHandleId);
888
924
  const id = `${prop}_sig_${handleId}_${this.tracks.length}`;
889
925
  const source = {
@@ -912,7 +948,8 @@ var LayerAnimation = class LayerAnimation$1 {
912
948
  * Modulates color interpolation based on an active signal (object or
913
949
  * registered name, as in {@link LayerAnimation.signal}).
914
950
  */
915
- colorSignal(prop, signalOrHandleId, options) {
951
+ colorSignal(rawProp, signalOrHandleId, options) {
952
+ const prop = normalizeAnimatableProp(rawProp);
916
953
  const { handleId, inline } = resolveSignalArg(signalOrHandleId);
917
954
  const id = `${prop}_colorSig_${handleId}_${this.tracks.length}`;
918
955
  const source = {
@@ -939,7 +976,8 @@ var LayerAnimation = class LayerAnimation$1 {
939
976
  /**
940
977
  * Adds organic Perlin noise wiggling to a property.
941
978
  */
942
- wiggle(prop, options = {}) {
979
+ wiggle(rawProp, options = {}) {
980
+ const prop = normalizeAnimatableProp(rawProp);
943
981
  const id = `${prop}_wiggle_${this.tracks.length}`;
944
982
  const source = {
945
983
  type: "wiggle",
@@ -959,7 +997,8 @@ var LayerAnimation = class LayerAnimation$1 {
959
997
  /**
960
998
  * Adds physical harmonic spring overshoot behavior to a property transition.
961
999
  */
962
- spring(prop, options = {}) {
1000
+ spring(rawProp, options = {}) {
1001
+ const prop = normalizeAnimatableProp(rawProp);
963
1002
  const id = `${prop}_spring_${this.tracks.length}`;
964
1003
  const source = {
965
1004
  type: "springOvershoot",
@@ -1261,6 +1300,132 @@ var CameraAnimation = class CameraAnimation$1 extends LayerAnimation {
1261
1300
  return this;
1262
1301
  }
1263
1302
  };
1303
+ /**
1304
+ * Schemas for character animation on model nodes: layered clips, two-bone
1305
+ * IK, look-at, spring bones, and skinned crowds on instance nodes.
1306
+ *
1307
+ * Time-varying values are tracks: a constant, keyframes `[[frame, …value]]`
1308
+ * (linear, in the layer's own frames), or, in process, a function of the
1309
+ * frame or a signal (anything with `get(ctx)`: audio, physics, vision,
1310
+ * `Signal.*`). Functions and signals are not serializable; a spec sent as
1311
+ * JSON keeps constants and keys.
1312
+ */
1313
+ const Vec3Schema$1 = z.tuple([
1314
+ z.number(),
1315
+ z.number(),
1316
+ z.number()
1317
+ ]);
1318
+ const isFunction = (v) => typeof v === "function";
1319
+ const isSignal$1 = (v) => typeof v === "object" && v !== null && typeof v.get === "function";
1320
+ /**
1321
+ * A number over time: constant, `[[frame, value], …]` keys, `(frame) =>
1322
+ * value`, or a signal.
1323
+ */
1324
+ const NumberTrackSchema = z.union([
1325
+ z.number(),
1326
+ z.array(z.tuple([z.number(), z.number()])).min(1),
1327
+ z.custom(isFunction),
1328
+ z.custom(isSignal$1)
1329
+ ]);
1330
+ /**
1331
+ * A point over time: `[x, y, z]` where each axis is a {@link NumberTrack}
1332
+ * (so a constant, keys, a function or a signal per axis), `[[frame, x, y,
1333
+ * z], …]` keys, or `(frame) => [x, y, z]`.
1334
+ */
1335
+ const Vec3TrackSchema = z.union([
1336
+ z.tuple([
1337
+ NumberTrackSchema,
1338
+ NumberTrackSchema,
1339
+ NumberTrackSchema
1340
+ ]),
1341
+ z.array(z.tuple([
1342
+ z.number(),
1343
+ z.number(),
1344
+ z.number(),
1345
+ z.number()
1346
+ ])).min(1),
1347
+ z.custom(isFunction)
1348
+ ]);
1349
+ const ClipRefSchema = z.union([z.string(), z.number().int().min(0)]);
1350
+ const ModelAnimationLayerSchema = z.object({
1351
+ clip: ClipRefSchema,
1352
+ weight: NumberTrackSchema.optional(),
1353
+ speed: z.number().optional(),
1354
+ timeOffset: z.number().optional(),
1355
+ mask: z.array(z.string()).optional(),
1356
+ loop: z.boolean().optional()
1357
+ }).strict();
1358
+ const TwoBoneIkSchema = z.object({
1359
+ chain: z.tuple([
1360
+ z.string(),
1361
+ z.string(),
1362
+ z.string()
1363
+ ]),
1364
+ target: Vec3TrackSchema,
1365
+ poleTarget: Vec3TrackSchema.optional(),
1366
+ weight: NumberTrackSchema.optional()
1367
+ }).strict();
1368
+ const LookAtSchema = z.object({
1369
+ joint: z.string(),
1370
+ target: Vec3TrackSchema,
1371
+ weight: NumberTrackSchema.optional(),
1372
+ maxAngleDeg: z.number().min(0).max(180).optional(),
1373
+ axis: Vec3Schema$1.optional()
1374
+ }).strict();
1375
+ /**
1376
+ * A joint posed directly, in its own local frame: Euler degrees (applied
1377
+ * Z, then Y, then X, like layers) and a translation offset in model units,
1378
+ * on top of the animated pose (`"additive"`, default) or of the joint's rest
1379
+ * pose (`"rest"`: clips no longer move it).
1380
+ */
1381
+ const JointPoseSchema = z.object({
1382
+ rotateX: NumberTrackSchema.optional(),
1383
+ rotateY: NumberTrackSchema.optional(),
1384
+ rotateZ: NumberTrackSchema.optional(),
1385
+ x: NumberTrackSchema.optional(),
1386
+ y: NumberTrackSchema.optional(),
1387
+ z: NumberTrackSchema.optional(),
1388
+ weight: NumberTrackSchema.optional(),
1389
+ mode: z.enum(["additive", "rest"]).optional()
1390
+ }).strict();
1391
+ /**
1392
+ * Points a bone along a scene direction (the joint turns so the bone,
1393
+ * toward its first child, or its local `axis` lies along it). Retargeting a
1394
+ * performer's pose is a chain of aims, parents first.
1395
+ */
1396
+ const AimSchema = z.object({
1397
+ joint: z.string(),
1398
+ direction: Vec3TrackSchema,
1399
+ weight: NumberTrackSchema.optional(),
1400
+ axis: Vec3Schema$1.optional()
1401
+ }).strict();
1402
+ /**
1403
+ * A joint driven by another: it turns by a share of the source joint's turn
1404
+ * from its rest, per local axis (Euler degrees, Z then Y then X). Applied
1405
+ * after look-ats, before IK, so eyelids follow eyes a `lookAt` aims.
1406
+ */
1407
+ const JointDriverSchema = z.object({
1408
+ joint: z.string(),
1409
+ from: z.string(),
1410
+ rotate: z.object({
1411
+ x: z.number().optional(),
1412
+ y: z.number().optional(),
1413
+ z: z.number().optional()
1414
+ }).strict()
1415
+ }).strict();
1416
+ const SpringBoneChainSchema = z.object({
1417
+ joints: z.array(z.string()).min(1),
1418
+ stiffness: z.number().min(0).optional(),
1419
+ damping: z.number().min(0).max(1).optional(),
1420
+ gravity: Vec3Schema$1.optional()
1421
+ }).strict();
1422
+ const CrowdSchema = z.object({
1423
+ clips: z.array(ClipRefSchema).min(1),
1424
+ fps: z.number().min(1).max(120).optional(),
1425
+ seed: z.number().optional(),
1426
+ speedRange: z.tuple([z.number().min(0), z.number().min(0)]).optional(),
1427
+ phase: z.enum(["random", "sync"]).optional()
1428
+ }).strict();
1264
1429
  const SAMPLES = 128;
1265
1430
  const CURVE_STEPS = 16;
1266
1431
  const NUM_RE = /-?(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?/gi;
@@ -1976,7 +2141,10 @@ const COLOR_PROPS$1 = new Set([
1976
2141
  "fillColor",
1977
2142
  "strokeColor",
1978
2143
  "textBackgroundColor",
1979
- "color"
2144
+ "color",
2145
+ "emissive",
2146
+ "subsurfaceColor",
2147
+ "sheenColor"
1980
2148
  ]);
1981
2149
  function computeRepeatFrame(track, localFrame, startFrame, lastFrame) {
1982
2150
  const repeat = track.repeat ?? 0;
@@ -2121,6 +2289,12 @@ function textOf(node) {
2121
2289
  const spans = node.spans ?? [];
2122
2290
  return [node.text, ...spans.map((s) => s.text)].filter((t) => typeof t === "string").join("");
2123
2291
  }
2292
+ const DIRECT_LIGHTS = new Set([
2293
+ "directional",
2294
+ "spot",
2295
+ "point",
2296
+ "rect"
2297
+ ]);
2124
2298
  /** Contrast below this makes text hard to read (WCAG large-text minimum). */
2125
2299
  const MIN_TEXT_CONTRAST = 3;
2126
2300
  function tracksOf(node) {
@@ -2147,6 +2321,21 @@ function solidColor(value) {
2147
2321
  const c = parseCssColor(value);
2148
2322
  return c && c[3] > .99 ? value : null;
2149
2323
  }
2324
+ /**
2325
+ * Cube cameras (panoramic lenses, relativity) and what they cannot combine
2326
+ * with. Returns whether the camera draws a cube.
2327
+ */
2328
+ function lintCamera(node, id, push) {
2329
+ const lens = node.lens;
2330
+ const projection = lens?.projection ?? "perspective";
2331
+ if (projection === "perspective" && (lens?.fov ?? 0) > 160) push("error", "camera_fov_range", `'${id}' has a ${lens?.fov}° perspective lens: perspective goes up to 160°. Use projection "fisheye" for wider views.`, id);
2332
+ const relativity = node.relativity;
2333
+ const cube = projection !== "perspective" || (relativity?.speed ?? 0) > 0 || animates(node, ["relativitySpeed"]);
2334
+ const dof = node.dof;
2335
+ if (cube && (dof?.enabled || animates(node, ["focusDistance"]))) push("error", "camera_cube_dof", `'${id}' is a cube camera (${relativity ? "relativity" : projection}) with depth of field: depth of field needs a single perspective view.`, id);
2336
+ if (cube && node.motionBlur) push("error", "camera_cube_motion_blur", `'${id}' is a cube camera (${relativity ? "relativity" : projection}) with motionBlur: shutter motion blur needs a single perspective view.`, id);
2337
+ return cube;
2338
+ }
2150
2339
  function lintComposition(config, options = {}) {
2151
2340
  const out = [];
2152
2341
  const push = (severity, code, message, layerId) => out.push({
@@ -2163,6 +2352,10 @@ function lintComposition(config, options = {}) {
2163
2352
  const pbrNodes = [];
2164
2353
  const emojiText = [];
2165
2354
  const seenIds = /* @__PURE__ */ new Set();
2355
+ let directLights = 0;
2356
+ let fogLight;
2357
+ let cubeCamera;
2358
+ let screenSpaceLight;
2166
2359
  const visit = (node, backdrop, atRoot) => {
2167
2360
  const id = String(node.id ?? "?");
2168
2361
  if (typeof node.id === "string") {
@@ -2181,12 +2374,18 @@ function lintComposition(config, options = {}) {
2181
2374
  const type = node.lightType ?? "directional";
2182
2375
  if (type === "environment") hasEnvironment = true;
2183
2376
  if (type === "ambient") ambientLights.push(id);
2377
+ if (DIRECT_LIGHTS.has(String(type))) directLights++;
2378
+ if (type === "environment" && node.volumetricFog) fogLight = id;
2379
+ if (type === "environment" && (node.ssr || node.gi)) screenSpaceLight = id;
2184
2380
  if (node.castShadow) {
2185
- if (type !== "directional" && type !== "spot") push("warning", "shadow_unsupported_light", `'${id}' is a ${String(type)} light: only directional and spot lights cast shadows.`, id);
2381
+ if (type !== "directional" && type !== "spot" && type !== "point" && type !== "rect") push("warning", "shadow_unsupported_light", `'${id}' is a ${String(type)} light: only directional, spot, point, and rect lights cast shadows.`, id);
2186
2382
  }
2187
2383
  return;
2188
2384
  }
2189
- if (node.kind === "camera") return;
2385
+ if (node.kind === "camera") {
2386
+ if (lintCamera(node, id, push)) cubeCamera = id;
2387
+ return;
2388
+ }
2190
2389
  if (node.kind === "media") {
2191
2390
  const src = node.inputHandleId;
2192
2391
  if (typeof src === "string") {
@@ -2199,7 +2398,9 @@ function lintComposition(config, options = {}) {
2199
2398
  }
2200
2399
  const is3D = Boolean(node.is3D) || typeof node.z === "number" && node.z !== 0;
2201
2400
  if (is3D || node.kind === "model3d") has3D = true;
2202
- if (node.roughness !== void 0 || node.metallic !== void 0) pbrNodes.push(id);
2401
+ const scatter = node.scatter3d;
2402
+ if (scatter && scatter.count > 0 && options.scatterCoverage?.(scatter) === 0) push("warning", "scatter_filters_reject_all", `'${id}' scatters onto a surface its slopeRange / elevationRange filters reject entirely, so no instance is placed. Widen the ranges (slope is degrees from level, elevation 0..1 from the surface's lowest to highest point).`, id);
2403
+ if (node.roughness !== void 0 || node.metallic !== void 0 || node.clearcoat !== void 0 || node.anisotropy !== void 0) pbrNodes.push(id);
2203
2404
  if (node.kind === "text" && backdrop && !animates(node, ["fill", "color"])) {
2204
2405
  const fg = solidColor(node.fill ?? node.color);
2205
2406
  const behind = solidColor(node.background) ?? backdrop;
@@ -2246,7 +2447,9 @@ function lintComposition(config, options = {}) {
2246
2447
  push("warning", "missing_emoji_font", `${emojiText.length === 1 ? "Text" : `${emojiText.length} text layers`} ${shown}${emojiText.length > 3 ? ", …" : ""} ${emojiText.length === 1 ? "has" : "have"} emoji, but no emoji font is registered, so the emoji draw nothing. Run \`npx framefields fonts add emoji\` and call the generated \`registerFonts()\`, or \`FontManager.registerEmojiFont(path)\` with a color emoji font.`, emojiText[0]);
2247
2448
  }
2248
2449
  if (hasEnvironment && ambientLights.length > 0) push("info", "ambient_with_environment", `The environment already fills shadows with light; ambient light ${ambientLights.join(", ")} adds flat light on top (remove it, or lower it, if the scene looks washed out).`);
2249
- if (has3D && pbrNodes.length > 0 && !hasEnvironment) push("info", "pbr_without_environment", `roughness / metallic are set (${pbrNodes.slice(0, 3).join(", ")}${pbrNodes.length > 3 ? ", …" : ""}) but the scene has no Layer.environment(): add one for physically based shading, reflections and tone mapping.`);
2450
+ if (cubeCamera && screenSpaceLight) push("error", "camera_cube_screen_space", `'${cubeCamera}' is a cube camera, and '${screenSpaceLight}' turns on ssr / gi: screen-space reflections and GI need a single perspective view. Use the environment's floor for reflections.`, screenSpaceLight);
2451
+ if (fogLight && directLights === 0) push("warning", "volumetric_fog_without_lights", `'${fogLight}' turns on volumetricFog, but the scene has no directional, spot, point or rect light: fog scatters only direct light, so there are no light shafts. Add a light (castShadow for shafts).`, fogLight);
2452
+ if (has3D && pbrNodes.length > 0 && !hasEnvironment) push("info", "pbr_without_environment", `roughness / metallic / clearcoat / anisotropy are set (${pbrNodes.slice(0, 3).join(", ")}${pbrNodes.length > 3 ? ", …" : ""}) but the scene has no Layer.environment(): add one for physically based shading, the coat and brushed-metal reflections, and tone mapping.`);
2250
2453
  return out;
2251
2454
  }
2252
2455
  const GEOMETRY = [
@@ -2272,12 +2475,27 @@ function companion(owner, src, suffix, tag) {
2272
2475
  if (Array.isArray(node.children)) node.children = hoistMattes(node.children);
2273
2476
  return node;
2274
2477
  }
2275
- function hoistOne(owner) {
2478
+ function textureCompanion(owner, src, size) {
2479
+ const node = companion(owner, src, "texture", {
2480
+ textureOf: String(owner.id),
2481
+ is3D: false,
2482
+ z: 0
2483
+ });
2484
+ if (GEOMETRY.every((k) => src[k] === void 0)) {
2485
+ node.x = 0;
2486
+ node.y = 0;
2487
+ if (size.width !== void 0) node.width = size.width;
2488
+ if (size.height !== void 0) node.height = size.height;
2489
+ }
2490
+ return node;
2491
+ }
2492
+ function hoistOne(owner, size) {
2276
2493
  const matte = owner.matte;
2277
2494
  const relief = owner.relief;
2278
- const { matte: _matte, relief: _relief, ...rest } = owner;
2495
+ const texture = owner.textureLayer;
2496
+ const { matte: _matte, relief: _relief, textureLayer: _texture, ...rest } = owner;
2279
2497
  const self = { ...rest };
2280
- if (Array.isArray(self.children)) self.children = hoistMattes(self.children);
2498
+ if (Array.isArray(self.children)) self.children = hoistMattes(self.children, size);
2281
2499
  const out = [self];
2282
2500
  if (matte?.node) {
2283
2501
  const node = companion(owner, matte.node, "matte", {
@@ -2297,11 +2515,16 @@ function hoistOne(owner) {
2297
2515
  self.reliefAmount = relief.amount ?? 0;
2298
2516
  out.push(node);
2299
2517
  }
2518
+ if (texture?.node) {
2519
+ const node = textureCompanion(owner, texture.node, size);
2520
+ self.textureLayerId = node.id;
2521
+ out.push(node);
2522
+ }
2300
2523
  return out;
2301
2524
  }
2302
- /** Returns the tree with every `matte` and `relief` turned into a sibling companion layer. */
2303
- function hoistMattes(nodes) {
2304
- return nodes.flatMap((n) => hoistOne(n));
2525
+ /** Returns the tree with every `matte`, `relief` and `textureLayer` turned into a sibling companion layer. */
2526
+ function hoistMattes(nodes, size = {}) {
2527
+ return nodes.flatMap((n) => hoistOne(n, size));
2305
2528
  }
2306
2529
  /**
2307
2530
  * Read a `timeRemap` signal at a composition frame: a signal instance, a named
@@ -2334,6 +2557,181 @@ function sampleMediaTimeSignal(binding, layer, clock) {
2334
2557
  };
2335
2558
  }
2336
2559
  /**
2560
+ * Schemas for procedural 3D content: terrain, SDF sculptures, surface
2561
+ * scattering and wind. A model node's `primitive3d` is checked against the
2562
+ * terrain / SDF schema when it names one of them.
2563
+ */
2564
+ const Vec3Schema = z.tuple([
2565
+ z.number(),
2566
+ z.number(),
2567
+ z.number()
2568
+ ]);
2569
+ const RangeSchema = (min, max) => z.tuple([z.number().min(min).max(max), z.number().min(min).max(max)]);
2570
+ const ShadingSchema = z.enum([
2571
+ "lit",
2572
+ "unlit",
2573
+ "toon"
2574
+ ]);
2575
+ const PrimitiveSurfaceFields = {
2576
+ color: z.string().optional(),
2577
+ material: ShadingSchema.optional(),
2578
+ shininess: z.number().min(0).optional(),
2579
+ roughness: z.number().min(0).max(1).optional(),
2580
+ metallic: z.number().min(0).max(1).optional()
2581
+ };
2582
+ const TerrainNoiseSchema = z.object({
2583
+ seed: z.number().optional(),
2584
+ scale: z.number().positive().optional(),
2585
+ octaves: z.number().int().min(1).max(10).optional(),
2586
+ persistence: z.number().min(0).max(1).optional(),
2587
+ lacunarity: z.number().min(1).max(4).optional(),
2588
+ ridgeMode: z.enum([
2589
+ "fbm",
2590
+ "ridged",
2591
+ "terrace"
2592
+ ]).optional(),
2593
+ terraceSteps: z.number().int().min(2).max(32).optional()
2594
+ }).strict();
2595
+ const TerrainColorByElevationSchema = z.object({
2596
+ lowColor: z.string(),
2597
+ midColor: z.string().optional(),
2598
+ highColor: z.string(),
2599
+ cliffColor: z.string().optional(),
2600
+ cliffThreshold: z.number().min(0).max(1).optional(),
2601
+ bands: RangeSchema(0, 1).optional()
2602
+ }).strict();
2603
+ const TerrainGeometrySchema = z.object({
2604
+ type: z.literal("terrain"),
2605
+ width: z.number().positive(),
2606
+ depth: z.number().positive(),
2607
+ height: z.number().min(0).optional(),
2608
+ segments: z.union([z.number().int().min(1).max(512), z.tuple([z.number().int().min(1).max(512), z.number().int().min(1).max(512)])]).optional(),
2609
+ noise: TerrainNoiseSchema.optional(),
2610
+ heights: z.array(z.number().min(0).max(1)).optional(),
2611
+ overhangWarp: z.number().min(0).optional(),
2612
+ colorByElevation: TerrainColorByElevationSchema.optional(),
2613
+ flatShaded: z.boolean().optional(),
2614
+ base: z.number().min(0).optional(),
2615
+ ...PrimitiveSurfaceFields
2616
+ }).strict();
2617
+ const SdfBaseFields = {
2618
+ op: z.enum([
2619
+ "union",
2620
+ "subtract",
2621
+ "intersect"
2622
+ ]).optional(),
2623
+ smoothness: z.number().min(0).optional(),
2624
+ center: Vec3Schema.optional(),
2625
+ rotation: Vec3Schema.optional(),
2626
+ color: z.string().optional()
2627
+ };
2628
+ const SdfPrimitiveSchema = z.discriminatedUnion("shape", [
2629
+ z.object({
2630
+ ...SdfBaseFields,
2631
+ shape: z.literal("sphere"),
2632
+ radius: z.number().positive()
2633
+ }).strict(),
2634
+ z.object({
2635
+ ...SdfBaseFields,
2636
+ shape: z.literal("box"),
2637
+ size: z.tuple([
2638
+ z.number().positive(),
2639
+ z.number().positive(),
2640
+ z.number().positive()
2641
+ ]),
2642
+ radius: z.number().min(0).optional()
2643
+ }).strict(),
2644
+ z.object({
2645
+ ...SdfBaseFields,
2646
+ shape: z.literal("cylinder"),
2647
+ radius: z.number().positive(),
2648
+ height: z.number().positive()
2649
+ }).strict(),
2650
+ z.object({
2651
+ ...SdfBaseFields,
2652
+ shape: z.literal("capsule"),
2653
+ radius: z.number().positive(),
2654
+ height: z.number().positive()
2655
+ }).strict(),
2656
+ z.object({
2657
+ ...SdfBaseFields,
2658
+ shape: z.literal("torus"),
2659
+ radius: z.number().positive(),
2660
+ tube: z.number().positive()
2661
+ }).strict(),
2662
+ z.object({
2663
+ ...SdfBaseFields,
2664
+ shape: z.literal("gyroid"),
2665
+ scale: z.number().positive(),
2666
+ thickness: z.number().positive()
2667
+ }).strict()
2668
+ ]);
2669
+ const SdfGeometrySchema = z.object({
2670
+ type: z.literal("sdf"),
2671
+ primitives: z.array(SdfPrimitiveSchema).min(1),
2672
+ bounds: z.tuple([
2673
+ z.number().positive(),
2674
+ z.number().positive(),
2675
+ z.number().positive()
2676
+ ]),
2677
+ resolution: z.number().int().min(16).max(160).optional(),
2678
+ flatShaded: z.boolean().optional(),
2679
+ ...PrimitiveSurfaceFields
2680
+ }).strict();
2681
+ /** `primitive3d`: free-form for the classic primitives, strict for terrain and SDF. */
2682
+ const Primitive3DSpecSchema = z.unknown().superRefine((value, ctx) => {
2683
+ const type = value?.type;
2684
+ const schema = type === "terrain" ? TerrainGeometrySchema : type === "sdf" ? SdfGeometrySchema : void 0;
2685
+ if (!schema) return;
2686
+ const parsed = schema.safeParse(value);
2687
+ if (parsed.success) return;
2688
+ for (const issue$1 of parsed.error.issues) ctx.addIssue({
2689
+ ...issue$1,
2690
+ code: "custom",
2691
+ message: issue$1.message
2692
+ });
2693
+ });
2694
+ const WindSchema = z.object({
2695
+ amplitudeDeg: z.number().min(0).max(90).optional(),
2696
+ frequency: z.number().min(0).max(20).optional(),
2697
+ direction: z.tuple([z.number(), z.number()]).optional(),
2698
+ waveScale: z.number().positive().optional()
2699
+ }).strict();
2700
+ const ScatterExclusionSchema = z.object({
2701
+ x: z.number(),
2702
+ z: z.number(),
2703
+ radius: z.number().min(0),
2704
+ falloff: z.number().min(0).optional()
2705
+ }).strict();
2706
+ const Scatter3DSchema = z.object({
2707
+ surface: z.custom((v) => typeof v === "object" && v !== null),
2708
+ count: z.number().int().min(0).max(2e5),
2709
+ minDistance: z.number().min(0).optional(),
2710
+ seed: z.number().optional(),
2711
+ slopeRange: RangeSchema(0, 180).optional(),
2712
+ elevationRange: RangeSchema(0, 1).optional(),
2713
+ alignToNormal: z.number().min(0).max(1).optional(),
2714
+ scaleRange: z.tuple([z.number().positive(), z.number().positive()]).optional(),
2715
+ randomYaw: z.boolean().optional(),
2716
+ exclude: z.array(ScatterExclusionSchema).optional(),
2717
+ sink: z.number().optional()
2718
+ }).strict();
2719
+ /** A layer drawn offscreen every frame and wrapped onto a model's surface. */
2720
+ const TextureLayerSchema = z.object({ node: z.custom((v) => typeof v === "object" && v !== null) }).strict();
2721
+ /**
2722
+ * Voronoi destruction (`world.fracture`): the model is cut into `cells`
2723
+ * pieces, drawn as one rigidly skinned mesh posed per frame from `track`.
2724
+ * Without a track the pieces rest in place and the model looks whole.
2725
+ */
2726
+ const Fracture3DSchema = z.object({
2727
+ cells: z.number().int().min(2).max(256).optional(),
2728
+ seed: z.number().optional(),
2729
+ impactPoint: Vec3Schema.optional(),
2730
+ interiorColor: z.string().optional(),
2731
+ interiorRoughness: z.number().min(0).max(1).optional(),
2732
+ track: z.array(z.number()).optional()
2733
+ }).strict();
2734
+ /**
2337
2735
  * Compositor program document v2 — THE single source of truth for a
2338
2736
  * composition (spec: `nodes/node-compositor/SKILL.md`).
2339
2737
  *
@@ -2437,6 +2835,7 @@ const AnimatablePropSchema = z.enum([
2437
2835
  "maxBlurRadius",
2438
2836
  "shakeTranslation",
2439
2837
  "shakeRotation",
2838
+ "relativitySpeed",
2440
2839
  "orbitRadius",
2441
2840
  "orbitAzimuth",
2442
2841
  "orbitElevation",
@@ -2465,7 +2864,24 @@ const AnimatablePropSchema = z.enum([
2465
2864
  "scaleY",
2466
2865
  "emissive",
2467
2866
  "emissiveIntensity",
2468
- "exposure"
2867
+ "clearcoat",
2868
+ "clearcoatRoughness",
2869
+ "anisotropy",
2870
+ "anisotropyRotation",
2871
+ "subsurface",
2872
+ "subsurfaceColor",
2873
+ "sheen",
2874
+ "sheenColor",
2875
+ "sheenRoughness",
2876
+ "iridescence",
2877
+ "iridescenceThickness",
2878
+ "iridescenceIor",
2879
+ "triplanarScale",
2880
+ "triplanarSharpness",
2881
+ "exposure",
2882
+ "volumetricFogDensity",
2883
+ "volumetricFogAnisotropy",
2884
+ "volumetricFogNoiseStrength"
2469
2885
  ]);
2470
2886
  const MatteModeSchema = z.enum([
2471
2887
  "alpha",
@@ -2746,6 +3162,15 @@ const GeometryOutlineOptionsSchema = z.object({
2746
3162
  depthThreshold: z.number().positive().max(1).optional(),
2747
3163
  opacity: z.number().min(0).max(1).optional()
2748
3164
  }).strict();
3165
+ const IridescenceConfigSchema = z.object({
3166
+ intensity: z.number().min(0).max(1).optional(),
3167
+ thickness: z.number().min(100).max(1200).optional(),
3168
+ ior: z.number().min(1.05).max(2.5).optional()
3169
+ }).strict();
3170
+ const TriplanarConfigSchema = z.object({
3171
+ scale: z.number().min(0).optional(),
3172
+ sharpness: z.number().min(1).max(16).optional()
3173
+ }).strict();
2749
3174
  const BaseNodeFields = {
2750
3175
  id: z.string().min(1),
2751
3176
  inputHandleId: z.string().optional(),
@@ -2806,6 +3231,21 @@ const BaseNodeFields = {
2806
3231
  envIntensity: z.number().min(0).max(10).optional(),
2807
3232
  emissive: ColorSchema.optional(),
2808
3233
  emissiveIntensity: z.number().min(0).optional(),
3234
+ clearcoat: z.number().min(0).max(1).optional(),
3235
+ clearcoatRoughness: z.number().min(0).max(1).optional(),
3236
+ anisotropy: z.number().min(-1).max(1).optional(),
3237
+ anisotropyRotation: z.number().optional(),
3238
+ subsurface: z.number().min(0).max(1).optional(),
3239
+ subsurfaceColor: ColorSchema.optional(),
3240
+ sheen: z.number().min(0).max(1).optional(),
3241
+ sheenColor: ColorSchema.optional(),
3242
+ sheenRoughness: z.number().min(.05).max(1).optional(),
3243
+ iridescence: z.union([z.number().min(0).max(1), IridescenceConfigSchema]).optional(),
3244
+ iridescenceThickness: z.number().min(100).max(1200).optional(),
3245
+ iridescenceIor: z.number().min(1.05).max(2.5).optional(),
3246
+ triplanar: z.union([z.boolean(), TriplanarConfigSchema]).optional(),
3247
+ triplanarScale: z.number().min(0).optional(),
3248
+ triplanarSharpness: z.number().min(1).max(16).optional(),
2809
3249
  castShadow: z.boolean().optional(),
2810
3250
  toon: ToonShadingSchema.optional(),
2811
3251
  outline: z.boolean().optional(),
@@ -2823,6 +3263,7 @@ const BaseNodeFields = {
2823
3263
  reliefId: z.string().optional(),
2824
3264
  reliefOf: z.string().optional(),
2825
3265
  reliefAmount: z.number().optional(),
3266
+ textureOf: z.string().optional(),
2826
3267
  animation: LayerAnimationSchema.default({ tracks: [] }),
2827
3268
  vision: z.unknown().optional(),
2828
3269
  relighting: z.unknown().optional()
@@ -2934,13 +3375,25 @@ const TextAnimator = {
2934
3375
  };
2935
3376
  }
2936
3377
  };
3378
+ /**
3379
+ * The picture a camera draws. `perspective` is an ordinary lens; the others
3380
+ * are cube cameras: the scene is drawn as six 90° faces around the eye and
3381
+ * remapped, so they can show what no single frustum holds.
3382
+ */
3383
+ const CameraProjectionSchema = z.enum([
3384
+ "perspective",
3385
+ "equirectangular",
3386
+ "fisheye"
3387
+ ]);
2937
3388
  const CameraLensSchema = z.object({
2938
3389
  focalLength: z.number().min(5).max(500).default(50),
2939
- fov: z.number().min(5).max(160).optional(),
3390
+ fov: z.number().min(5).max(360).optional(),
2940
3391
  sensorWidth: z.number().default(36),
2941
3392
  near: z.number().min(.1).default(1),
2942
3393
  far: z.number().min(10).default(5e4),
2943
- zoom: z.number().min(.01).default(1)
3394
+ zoom: z.number().min(.01).default(1),
3395
+ projection: CameraProjectionSchema.default("perspective"),
3396
+ cubeSize: z.number().int().min(64).max(8192).optional()
2944
3397
  }).strict();
2945
3398
  const CameraDoFSchema = z.object({
2946
3399
  enabled: z.boolean().default(false),
@@ -2957,6 +3410,33 @@ const CameraShakeSchema = z.object({
2957
3410
  octaves: z.number().int().min(1).max(6).default(3),
2958
3411
  seed: z.number().default(42)
2959
3412
  }).strict();
3413
+ /**
3414
+ * Per-object shutter motion blur for the 3D scene: every mesh, skinned
3415
+ * joint, instance and fractured piece streaks by its own motion over the
3416
+ * shutter (and the camera's), reconstructed from a velocity buffer.
3417
+ */
3418
+ const CameraMotionBlurSchema = z.object({
3419
+ shutter: z.number().min(1).max(720).default(180),
3420
+ samples: z.number().int().min(4).max(64).default(20),
3421
+ maxBlur: z.number().min(4).max(160).default(48)
3422
+ }).strict();
3423
+ /**
3424
+ * The camera moves through the scene near the speed of light. What it sees
3425
+ * is physics, not grading: rays crowd towards the direction of motion
3426
+ * (aberration), colours shift blue ahead and red behind (Doppler) and ahead
3427
+ * brightens (beaming). Always drawn by a cube camera.
3428
+ */
3429
+ const CameraRelativitySchema = z.object({
3430
+ speed: z.number().min(0).max(.9999).default(0),
3431
+ direction: z.tuple([
3432
+ z.number(),
3433
+ z.number(),
3434
+ z.number()
3435
+ ]).optional(),
3436
+ doppler: z.boolean().default(true),
3437
+ beaming: z.boolean().default(true),
3438
+ exposure: z.union([z.literal("auto"), z.number().min(-64).max(16)]).default("auto")
3439
+ }).strict();
2960
3440
  const CameraNodeSchema = z.object({
2961
3441
  id: z.string().min(1),
2962
3442
  kind: z.literal("camera"),
@@ -2977,6 +3457,8 @@ const CameraNodeSchema = z.object({
2977
3457
  lens: CameraLensSchema.optional(),
2978
3458
  dof: CameraDoFSchema.optional(),
2979
3459
  shake: CameraShakeSchema.optional(),
3460
+ motionBlur: z.union([z.boolean(), CameraMotionBlurSchema]).optional(),
3461
+ relativity: CameraRelativitySchema.optional(),
2980
3462
  startFrame: z.number().int().min(0).default(0),
2981
3463
  durationFrames: z.number().int().min(1).optional(),
2982
3464
  animation: LayerAnimationSchema.default({ tracks: [] })
@@ -2986,13 +3468,16 @@ const LightTypeSchema = z.enum([
2986
3468
  "directional",
2987
3469
  "point",
2988
3470
  "spot",
3471
+ "rect",
2989
3472
  "environment"
2990
3473
  ]);
2991
3474
  const EnvironmentPresetSchema = z.enum([
2992
3475
  "studio",
2993
3476
  "soft",
3477
+ "warm",
2994
3478
  "sunset",
2995
3479
  "night",
3480
+ "neon",
2996
3481
  "neutral"
2997
3482
  ]);
2998
3483
  const ToneMappingSchema = z.enum([
@@ -3021,6 +3506,39 @@ const EnvironmentFloorSchema = z.object({
3021
3506
  fadeDistance: z.number().min(0).optional(),
3022
3507
  opacity: z.number().min(0).max(1).optional()
3023
3508
  }).strict();
3509
+ const EnvironmentVolumetricFogNoiseSchema = z.object({
3510
+ scale: z.number().min(1e-4).optional(),
3511
+ strength: z.number().min(0).max(1).optional(),
3512
+ speed: z.tuple([
3513
+ z.number(),
3514
+ z.number(),
3515
+ z.number()
3516
+ ]).optional(),
3517
+ octaves: z.number().int().min(1).max(3).optional()
3518
+ }).strict();
3519
+ const EnvironmentVolumetricFogSchema = z.object({
3520
+ density: z.number().min(0).optional(),
3521
+ color: ColorSchema.optional(),
3522
+ anisotropy: z.number().min(-.95).max(.95).optional(),
3523
+ heightFalloff: z.number().min(0).optional(),
3524
+ baseHeight: z.number().optional(),
3525
+ steps: z.number().int().min(8).max(64).optional(),
3526
+ maxDistance: z.number().min(100).optional(),
3527
+ lightIntensity: z.number().min(0).optional(),
3528
+ ambientIntensity: z.number().min(0).optional(),
3529
+ noise: z.union([z.boolean(), EnvironmentVolumetricFogNoiseSchema]).optional()
3530
+ }).strict();
3531
+ const EnvironmentSsrSchema = z.object({
3532
+ intensity: z.number().min(0).max(1).optional(),
3533
+ maxRoughness: z.number().min(0).max(1).optional(),
3534
+ thickness: z.number().min(1).optional(),
3535
+ steps: z.number().int().min(16).max(64).optional()
3536
+ }).strict();
3537
+ const EnvironmentGiSchema = z.object({
3538
+ intensity: z.number().min(0).max(4).optional(),
3539
+ radius: z.number().min(1).optional(),
3540
+ samples: z.number().int().min(4).max(16).optional()
3541
+ }).strict();
3024
3542
  const LightNodeSchema = z.object({
3025
3543
  id: z.string().min(1),
3026
3544
  kind: z.literal("light"),
@@ -3042,11 +3560,15 @@ const LightNodeSchema = z.object({
3042
3560
  decay: z.number().min(0).default(2),
3043
3561
  angle: z.number().min(0).max(180).default(45),
3044
3562
  penumbra: z.number().min(0).max(1).default(.2),
3563
+ width: z.number().min(0).optional(),
3564
+ height: z.number().min(0).optional(),
3565
+ twoSided: z.boolean().optional(),
3045
3566
  castShadow: z.boolean().optional(),
3046
3567
  shadowSoftness: z.number().min(0).max(64).optional(),
3047
3568
  shadowDarkness: z.number().min(0).max(1).optional(),
3048
3569
  shadowMapSize: z.number().int().min(256).max(8192).optional(),
3049
3570
  preset: EnvironmentPresetSchema.optional(),
3571
+ hdri: z.union([z.string(), z.custom((v) => v instanceof Uint8Array)]).optional(),
3050
3572
  top: ColorSchema.optional(),
3051
3573
  horizon: ColorSchema.optional(),
3052
3574
  bottom: ColorSchema.optional(),
@@ -3056,6 +3578,12 @@ const LightNodeSchema = z.object({
3056
3578
  toneMapping: ToneMappingSchema.optional(),
3057
3579
  fog: EnvironmentFogSchema.optional(),
3058
3580
  floor: EnvironmentFloorSchema.optional(),
3581
+ volumetricFog: z.union([z.boolean(), EnvironmentVolumetricFogSchema]).optional(),
3582
+ volumetricFogDensity: z.number().min(0).optional(),
3583
+ volumetricFogAnisotropy: z.number().min(-.95).max(.95).optional(),
3584
+ volumetricFogNoiseStrength: z.number().min(0).max(1).optional(),
3585
+ ssr: z.union([z.boolean(), EnvironmentSsrSchema]).optional(),
3586
+ gi: z.union([z.boolean(), EnvironmentGiSchema]).optional(),
3059
3587
  outlines: z.union([z.boolean(), GeometryOutlineOptionsSchema]).optional(),
3060
3588
  bloom: z.union([z.boolean(), BloomConfigSchema]).optional(),
3061
3589
  startFrame: z.number().int().min(0).default(0),
@@ -3180,6 +3708,7 @@ const TextFields = {
3180
3708
  fontSize: z.number().positive().optional(),
3181
3709
  fontWeight: z.union([z.number().int(), z.string()]).optional(),
3182
3710
  fontStyle: z.string().optional(),
3711
+ fontVariations: z.record(z.string(), z.number()).optional(),
3183
3712
  fill: ColorSchema,
3184
3713
  align: z.enum([
3185
3714
  "start",
@@ -3385,9 +3914,23 @@ const Model3DNodeSchema = z.object({
3385
3914
  color: ColorSchema.optional(),
3386
3915
  colorTint: ColorSchema.optional(),
3387
3916
  text3dOptions: z.unknown().optional(),
3388
- primitive3d: z.unknown().optional(),
3917
+ primitive3d: Primitive3DSpecSchema.optional(),
3389
3918
  instances3d: z.unknown().optional(),
3390
- swarm3d: z.unknown().optional()
3919
+ swarm3d: z.unknown().optional(),
3920
+ scatter3d: Scatter3DSchema.optional(),
3921
+ fracture3d: Fracture3DSchema.optional(),
3922
+ wind: WindSchema.optional(),
3923
+ textureLayer: TextureLayerSchema.optional(),
3924
+ textureLayerId: z.string().optional(),
3925
+ animationLayers: z.array(ModelAnimationLayerSchema).optional(),
3926
+ ik: z.array(TwoBoneIkSchema).optional(),
3927
+ lookAt: z.array(LookAtSchema).optional(),
3928
+ springBones: z.array(SpringBoneChainSchema).optional(),
3929
+ pose: z.record(z.string(), JointPoseSchema).optional(),
3930
+ morphs: z.record(z.string(), NumberTrackSchema).optional(),
3931
+ aim: z.array(AimSchema).optional(),
3932
+ drive: z.array(JointDriverSchema).optional(),
3933
+ crowd: CrowdSchema.optional()
3391
3934
  }).strict();
3392
3935
  /**
3393
3936
  * Dispatch on `kind`, not a plain union: a plain union tries every member,
@@ -3427,7 +3970,6 @@ const CompositorProgramSchema = z.object({
3427
3970
  * @module @framefields/compositions/program/sequence
3428
3971
  *
3429
3972
  * Multi-Scene Timeline Orchestration, Camera Choreography & Carrier Match Cuts.
3430
- * Complies with specs/cinematic-sequencing.ts.
3431
3973
  */
3432
3974
  /**
3433
3975
  * Camera Transition Type across scene boundaries.
@@ -3679,6 +4221,29 @@ function isScene3D(node) {
3679
4221
  const kids = node.children;
3680
4222
  return kids.some((c) => c.kind === "camera") && kids.some((c) => c.kind !== "camera" && c.kind !== "light");
3681
4223
  }
4224
+ /**
4225
+ * `media` with `node`'s effects applied in order, each a pass over the
4226
+ * picture below it: a clip's frames, or a 3D scene's finished composition.
4227
+ */
4228
+ function wrapEffects(media, node) {
4229
+ if (!Array.isArray(node.effects)) return media;
4230
+ let current = media;
4231
+ for (const eff of node.effects) {
4232
+ const effOp = eff && typeof eff.toOperation === "function" ? eff.toOperation() : eff;
4233
+ current = {
4234
+ metadata: { ...current.metadata },
4235
+ operation: {
4236
+ op: String(effOp.op ?? "effect"),
4237
+ id: node.id ? `${node.id}-${effOp.op ?? "effect"}` : void 0,
4238
+ effect: eff,
4239
+ ...effOp,
4240
+ dataType: current.operation.dataType
4241
+ },
4242
+ children: [current]
4243
+ };
4244
+ }
4245
+ return current;
4246
+ }
3682
4247
  function nodeToVirtualMedia(node, resolveMedia, fps, inheritedOffset = 0, compDurationMs, inheritedDurationFrames, resolveSignal) {
3683
4248
  if (node.kind === "media" && node.timeRemap !== void 0) {
3684
4249
  const parsed = MediaTimeRemapInputSchema.safeParse(node.timeRemap);
@@ -3708,24 +4273,7 @@ function nodeToVirtualMedia(node, resolveMedia, fps, inheritedOffset = 0, compDu
3708
4273
  children: [media]
3709
4274
  };
3710
4275
  }
3711
- if (media && Array.isArray(node.effects)) {
3712
- let currentMedia = media;
3713
- for (const eff of node.effects) {
3714
- const effOp = eff && typeof eff.toOperation === "function" ? eff.toOperation() : eff;
3715
- currentMedia = {
3716
- metadata: { ...currentMedia.metadata },
3717
- operation: {
3718
- op: String(effOp.op ?? "effect"),
3719
- id: node.id ? `${node.id}-${effOp.op ?? "effect"}` : void 0,
3720
- effect: eff,
3721
- ...effOp,
3722
- dataType: currentMedia.operation.dataType
3723
- },
3724
- children: [currentMedia]
3725
- };
3726
- }
3727
- media = currentMedia;
3728
- }
4276
+ if (media) media = wrapEffects(media, node);
3729
4277
  if (media && node.vision) {
3730
4278
  const visionRaw = node.vision;
3731
4279
  const visionOp = typeof visionRaw.toOperation === "function" ? visionRaw.toOperation() : visionRaw;
@@ -3755,7 +4303,20 @@ function nodeToVirtualMedia(node, resolveMedia, fps, inheritedOffset = 0, compDu
3755
4303
  return nodeToVirtualMedia(c, resolveMedia, fps, scene ? delay : inheritedOffset + nodeStart + delay, compDurationMs, c.durationFrames === void 0 ? nodeDuration : void 0, resolveSignal);
3756
4304
  });
3757
4305
  if (scene) {
3758
- const durationMs$1 = (nodeDuration ?? Math.round((compDurationMs ?? 1e4) / 1e3 * fps)) / fps * 1e3;
4306
+ const frames = nodeDuration ?? Math.round((compDurationMs ?? 1e4) / 1e3 * fps);
4307
+ const durationMs$1 = frames / fps * 1e3;
4308
+ const background = typeof node.background === "string" ? node.background : void 0;
4309
+ const clear = background && parseCssColor(background) ? background : void 0;
4310
+ if (background && !clear) children.unshift(nodeToVirtualMedia({
4311
+ kind: "box",
4312
+ id: `${node.id ?? "scene"}-background`,
4313
+ position: "absolute",
4314
+ x: 0,
4315
+ y: 0,
4316
+ width: node.width,
4317
+ height: node.height,
4318
+ background
4319
+ }, resolveMedia, fps, 0, compDurationMs, frames, resolveSignal));
3759
4320
  media = {
3760
4321
  metadata: {
3761
4322
  width: node.width,
@@ -3771,10 +4332,11 @@ function nodeToVirtualMedia(node, resolveMedia, fps, inheritedOffset = 0, compDu
3771
4332
  mode: "Video",
3772
4333
  dataType: "Video",
3773
4334
  volume: 1,
3774
- ...typeof node.background === "string" && { backgroundColor: node.background }
4335
+ ...clear && { backgroundColor: clear }
3775
4336
  },
3776
4337
  children
3777
4338
  };
4339
+ media = wrapEffects(media, node);
3778
4340
  children = [media];
3779
4341
  }
3780
4342
  }
@@ -3791,7 +4353,8 @@ function nodeToVirtualMedia(node, resolveMedia, fps, inheritedOffset = 0, compDu
3791
4353
  let dur = typeof node.durationFrames === "number" && Number.isFinite(node.durationFrames) && node.durationFrames > 0 ? Math.round(node.durationFrames) : void 0;
3792
4354
  const defaultCompDuration = inheritedDurationFrames ?? Math.round((compDurationMs ?? 1e4) / 1e3 * fps);
3793
4355
  if (isContainer && children.length > 0) {
3794
- if (dur === void 0) {
4356
+ if (dur === void 0 && isScene3D(node)) dur = Math.max(1, defaultCompDuration);
4357
+ else if (dur === void 0) {
3795
4358
  const childEnds = children.map((c) => (c.operation.startFrame ?? 0) + (c.operation.durationFrames ?? defaultCompDuration));
3796
4359
  dur = Math.max(1, Math.max(...childEnds) - startFrame);
3797
4360
  }
@@ -3821,7 +4384,8 @@ function nodeToVirtualMedia(node, resolveMedia, fps, inheritedOffset = 0, compDu
3821
4384
  ...isScene3D(node) && {
3822
4385
  kind: "media",
3823
4386
  background: void 0,
3824
- children: void 0
4387
+ children: void 0,
4388
+ effects: void 0
3825
4389
  },
3826
4390
  startFrame,
3827
4391
  durationFrames: dur,
@@ -3867,7 +4431,10 @@ function compositorToProgram(config, options) {
3867
4431
  signals: programSignals,
3868
4432
  ...config.onRequestFrame || options.onRequestFrame ? { onRequestFrame: config.onRequestFrame ?? options.onRequestFrame } : {}
3869
4433
  },
3870
- children: hoistMattes(config.layout).map((n) => nodeToVirtualMedia(n, resolveMedia, fps, 0, durationMs, void 0, resolveMediaSignal))
4434
+ children: hoistMattes(config.layout, {
4435
+ width: config.width,
4436
+ height: config.height
4437
+ }).map((n) => nodeToVirtualMedia(n, resolveMedia, fps, 0, durationMs, void 0, resolveMediaSignal))
3871
4438
  };
3872
4439
  shareSignals(rootMedia.children ?? [], programSignals);
3873
4440
  const effectsList = Array.isArray(options.effects) ? options.effects : Array.isArray(config.effects) ? config.effects : [];
@@ -3908,6 +4475,32 @@ function shareSignals(nodes, signals) {
3908
4475
  * Recursively gather every node op from a render tree (in order), stopping at
3909
4476
  * nested scene compositions: their layers belong to their own render.
3910
4477
  */
4478
+ /**
4479
+ * Every layer, 3D scenes' layers included, with its start on the
4480
+ * composition's clock. A scene's layers run on the scene's own clock, which
4481
+ * starts where the scene's layer does, so their starts are offset by it.
4482
+ */
4483
+ function collectLayersOnClock(nodes) {
4484
+ const out = [];
4485
+ const walk = (vm, offset, layerStart) => {
4486
+ const op = vm?.operation;
4487
+ if (op?.op === "Compositor") {
4488
+ for (const c of vm.children ?? []) walk(c, layerStart, layerStart);
4489
+ return;
4490
+ }
4491
+ let start = layerStart;
4492
+ if (op?.op === "CompositorLayer") {
4493
+ start = offset + (op.startFrame ?? 0);
4494
+ out.push({
4495
+ vm,
4496
+ startFrame: start
4497
+ });
4498
+ }
4499
+ for (const c of vm?.children ?? []) walk(c, offset, start);
4500
+ };
4501
+ for (const n of nodes) walk(n, 0, 0);
4502
+ return out;
4503
+ }
3911
4504
  function collectNodeOps(nodes) {
3912
4505
  const out = [];
3913
4506
  const walk = (vm) => {
@@ -3918,7 +4511,191 @@ function collectNodeOps(nodes) {
3918
4511
  for (const n of nodes) walk(n);
3919
4512
  return out;
3920
4513
  }
4514
+ /**
4515
+ * Sampling a layer's animation at a frame exactly as the compositor draws
4516
+ * it: keyframe segments shaped by GSAP's eases (what the compiled GSAP
4517
+ * timeline plays), other sources (wiggle, spring, signals) by the program
4518
+ * evaluator. The compositor's draw-time tracks and anything that must agree
4519
+ * with the picture outside a render (physics following a layer) share it.
4520
+ */
4521
+ const gsap = gsapModule.default ?? gsapModule;
4522
+ /**
4523
+ * Solves a cubic bezier curve defined by control points (x1, y1) and (x2, y2)
4524
+ * for a given progress parameter t in [0, 1].
4525
+ */
4526
+ function solveCubicBezier(x1, y1, x2, y2, t) {
4527
+ if (t <= 0) return 0;
4528
+ if (t >= 1) return 1;
4529
+ if (x1 === y1 && x2 === y2) return t;
4530
+ let u = t;
4531
+ for (let i = 0; i < 8; i++) {
4532
+ const oneMinusU$1 = 1 - u;
4533
+ const oneMinusU2 = oneMinusU$1 * oneMinusU$1;
4534
+ const u2 = u * u;
4535
+ const diff = 3 * oneMinusU2 * u * x1 + 3 * oneMinusU$1 * u2 * x2 + u2 * u - t;
4536
+ if (Math.abs(diff) < 1e-6) break;
4537
+ const dx = 3 * oneMinusU2 * x1 + 6 * oneMinusU$1 * u * (x2 - x1) + 3 * u2 * (1 - x2);
4538
+ if (Math.abs(dx) < 1e-6) break;
4539
+ u -= diff / dx;
4540
+ u = Math.max(0, Math.min(1, u));
4541
+ }
4542
+ const oneMinusU = 1 - u;
4543
+ const checkX = 3 * oneMinusU * oneMinusU * u * x1 + 3 * oneMinusU * u * u * x2 + u * u * u;
4544
+ if (Math.abs(checkX - t) > .001) {
4545
+ let low = 0;
4546
+ let high = 1;
4547
+ u = t;
4548
+ for (let i = 0; i < 16; i++) {
4549
+ const mid = (low + high) * .5;
4550
+ const oMid = 1 - mid;
4551
+ const xMid = 3 * oMid * oMid * mid * x1 + 3 * oMid * mid * mid * x2 + mid * mid * mid;
4552
+ if (Math.abs(xMid - t) < 1e-5) {
4553
+ u = mid;
4554
+ break;
4555
+ }
4556
+ if (xMid < t) low = mid;
4557
+ else high = mid;
4558
+ u = mid;
4559
+ }
4560
+ }
4561
+ const oU = 1 - u;
4562
+ return 3 * oU * oU * u * y1 + 3 * oU * u * u * y2 + u * u * u;
4563
+ }
4564
+ function mappedEase(ease, durationFrames, fps = 24) {
4565
+ if (!ease) return "none";
4566
+ const { name, dir, params } = ease;
4567
+ if (name === "none") return "none";
4568
+ if (name === "spring") {
4569
+ const damping = Math.max(.001, params?.[0] ?? 10);
4570
+ const stiffness = Math.max(.001, params?.[1] ?? 100);
4571
+ const mass = Math.max(.001, params?.[2] ?? 1);
4572
+ return (p) => {
4573
+ const t = p * (durationFrames && durationFrames > 0 ? durationFrames / (fps > 0 ? fps : 24) : 1);
4574
+ const m = mass;
4575
+ const k = stiffness;
4576
+ const c = damping;
4577
+ const w0 = Math.sqrt(k / m);
4578
+ const zeta = c / (2 * Math.sqrt(k * m));
4579
+ let x = 0;
4580
+ if (zeta < 1) {
4581
+ const wd = w0 * Math.sqrt(1 - zeta * zeta);
4582
+ const A = -1;
4583
+ const B = -zeta * w0 / wd;
4584
+ x = Math.exp(-zeta * w0 * t) * (A * Math.cos(wd * t) + B * Math.sin(wd * t));
4585
+ } else if (zeta === 1) {
4586
+ const A = -1;
4587
+ const B = -w0;
4588
+ x = Math.exp(-w0 * t) * (A + B * t);
4589
+ } else {
4590
+ const r1 = -w0 * (zeta - Math.sqrt(zeta * zeta - 1));
4591
+ const r2 = -w0 * (zeta + Math.sqrt(zeta * zeta - 1));
4592
+ const C1 = -1 / (1 - r1 / r2);
4593
+ const C2 = -1 - C1;
4594
+ x = C1 * Math.exp(r1 * t) + C2 * Math.exp(r2 * t);
4595
+ }
4596
+ return 1 + x;
4597
+ };
4598
+ }
4599
+ if (name === "cubic") {
4600
+ const x1 = params?.[0] ?? .25;
4601
+ const y1 = params?.[1] ?? .1;
4602
+ const x2 = params?.[2] ?? .25;
4603
+ const y2 = params?.[3] ?? 1;
4604
+ return (p) => solveCubicBezier(x1, y1, x2, y2, p);
4605
+ }
4606
+ if (name === "hold") return (p) => p >= .9999 ? 1 : 0;
4607
+ const easeName = name;
4608
+ let suffix = "";
4609
+ if (params && params.length > 0) suffix = `(${params.join(", ")})`;
4610
+ else if (name === "back") suffix = "(1.7)";
4611
+ else if (name === "elastic") suffix = "(1, 0.3)";
4612
+ return `${easeName}.${dir}${suffix}`;
4613
+ }
4614
+ /** GSAP's shaping for a keyframe segment, so draw-time tracks ease like baked ones. */
4615
+ function gsapEase(fps) {
4616
+ return (ease, deltaFrames, t) => {
4617
+ const e = mappedEase(ease, deltaFrames, fps);
4618
+ const fn = typeof e === "function" ? e : gsap.parseEase(e);
4619
+ return fn ? fn(t) : t;
4620
+ };
4621
+ }
4622
+ /** A track's value at composition frame `frame`. */
4623
+ function sampleTrack(track, frame, fps, ctx = {}) {
4624
+ const startFrame = ctx.startFrame ?? 0;
4625
+ const step = ctx.step ?? 1;
4626
+ const f = step > 1 ? startFrame + Math.floor((frame - startFrame) / step) * step : frame;
4627
+ if ((track.source ?? { type: "keyframe" }).type === "keyframe") return evaluateKeyframes(track, f - startFrame, gsapEase(fps));
4628
+ return evaluateTrackAtFrame(track, f, fps, {
4629
+ startFrame,
4630
+ baseValues: ctx.base,
4631
+ signals: ctx.signals
4632
+ });
4633
+ }
4634
+ /**
4635
+ * A layer's numeric prop at composition frame `frame`: its own value, then
4636
+ * each of its tracks on that prop in order (a later track overrides).
4637
+ */
4638
+ function sampleLayerProp(layer, prop, frame, fps, fallback = 0) {
4639
+ const own = layer[prop];
4640
+ let value = typeof own === "number" && Number.isFinite(own) ? own : fallback;
4641
+ const animation = layer.animation;
4642
+ for (const track of animation?.tracks ?? []) {
4643
+ if (track.prop !== prop) continue;
4644
+ const v = sampleTrack(track, frame, fps, {
4645
+ startFrame: layer.startFrame ?? 0,
4646
+ step: animation?.frameStep,
4647
+ base: layer
4648
+ });
4649
+ if (typeof v === "number" && Number.isFinite(v)) value = v;
4650
+ }
4651
+ return value;
4652
+ }
4653
+ const signalContext = (c) => ({
4654
+ frame: c.frame,
4655
+ fps: c.fps,
4656
+ time: c.frame / c.fps,
4657
+ duration: 0,
4658
+ durationMs: 0,
4659
+ progress: 0,
4660
+ deltaTime: 1 / c.fps
4661
+ });
4662
+ /** A number track's value: constant, keys, function, or signal. */
4663
+ function numberAt(track, clock, fallback) {
4664
+ if (track === void 0) return fallback;
4665
+ if (typeof track === "number") return track;
4666
+ if (typeof track === "function") return track(clock.frame);
4667
+ if (Array.isArray(track)) return keyed(track, clock.frame, 1)[0] ?? fallback;
4668
+ const v = track.get(signalContext(clock));
4669
+ return Number.isFinite(v) ? v : fallback;
4670
+ }
4671
+ /** Whether a point track is `[[frame, x, y, z], …]` keys (not one track per axis). */
4672
+ const isPointKeys = (track) => Array.isArray(track[0]) && track[0].length === 4;
4673
+ /** A point track's value: per-axis tracks, keys, or a function. */
4674
+ function vec3At(track, clock) {
4675
+ if (typeof track === "function") return track(clock.frame);
4676
+ if (isPointKeys(track)) return keyed(track, clock.frame, 3);
4677
+ const axes = track;
4678
+ return [
4679
+ numberAt(axes[0], clock, 0),
4680
+ numberAt(axes[1], clock, 0),
4681
+ numberAt(axes[2], clock, 0)
4682
+ ];
4683
+ }
4684
+ /** Linear interpolation over `[[frame, …values]]` keys, held past the ends. */
4685
+ function keyed(keys, frame, size) {
4686
+ const sorted = keys;
4687
+ const first = sorted[0];
4688
+ const last = sorted[sorted.length - 1];
4689
+ if (frame <= first[0]) return first.slice(1, 1 + size);
4690
+ if (frame >= last[0]) return last.slice(1, 1 + size);
4691
+ let k = 0;
4692
+ while (k + 1 < sorted.length && sorted[k + 1][0] <= frame) k++;
4693
+ const a = sorted[k];
4694
+ const b = sorted[k + 1];
4695
+ const u = (frame - a[0]) / Math.max(1e-9, b[0] - a[0]);
4696
+ return a.slice(1, 1 + size).map((v, i) => v + (b[i + 1] - v) * u);
4697
+ }
3921
4698
 
3922
4699
  //#endregion
3923
- export { TextSpanSchema as A, computeStaggerDelay as B, SceneTransitionTypeSchema as C, TextAnimatorSchema as D, TextAnimator as E, collectNodeOps as F, initLayout as G, evaluateKeyframes as H, compositorToProgram as I, mergeAnimationTracks as J, lintComposition as K, computeCarrierContinuity as L, ToonShadingSchema as M, applyStaggerToChildren as N, TextNodeSchema as O, calculateSequenceTimeline as P, computeLayout as R, SceneDefinitionSchema as S, ShapeNodeSchema as T, evaluateTrackAtFrame as U, evaluateAnimationAtFrame as V, hoistMattes as W, sampleMediaTimeSignal as Y, MaterialTypeSchema as _, CarrierHandoffConfigSchema as a, Model3DNodeSchema as b, EnvironmentFloorSchema as c, FlexNodeSchema as d, GeometryOutlineOptionsSchema as f, LightTypeSchema as g, LightNodeSchema as h, CameraNodeSchema as i, ToneMappingSchema as j, TextSpanMarkSchema as k, EnvironmentFogSchema as l, LayoutNodeSchema as m, BoxNodeSchema as n, ColorStopSchema as o, LayerAnimation as p, mediaSignalSampler as q, CameraAnimation as r, CompositorProgramSchema as s, BloomConfigSchema as t, EnvironmentPresetSchema as u, MatteModeSchema as v, Sequence as w, Scene as x, MediaNodeSchema as y, computeLayoutSync as z };
3924
- //# sourceMappingURL=program-tFKCWU2j.mjs.map
4700
+ export { mergeAnimationTracks as $, TextAnimator as A, collectNodeOps as B, MediaNodeSchema as C, SceneTransitionTypeSchema as D, SceneDefinitionSchema as E, ToneMappingSchema as F, computeStaggerDelay as G, computeCarrierContinuity as H, ToonShadingSchema as I, hoistMattes as J, evaluateAnimationAtFrame as K, applyStaggerToChildren as L, TextNodeSchema as M, TextSpanMarkSchema as N, Sequence as O, TextSpanSchema as P, mediaSignalSampler as Q, calculateSequenceTimeline as R, MatteModeSchema as S, Scene as T, computeLayout as U, compositorToProgram as V, computeLayoutSync as W, lintComposition as X, initLayout as Y, mappedEase as Z, LayerAnimation as _, CarrierHandoffConfigSchema as a, LightTypeSchema as b, EnvironmentFloorSchema as c, EnvironmentPresetSchema as d, numberAt as et, EnvironmentSsrSchema as f, GeometryOutlineOptionsSchema as g, FlexNodeSchema as h, CameraNodeSchema as i, vec3At as it, TextAnimatorSchema as j, ShapeNodeSchema as k, EnvironmentFogSchema as l, EnvironmentVolumetricFogSchema as m, BoxNodeSchema as n, sampleMediaTimeSignal as nt, ColorStopSchema as o, EnvironmentVolumetricFogNoiseSchema as p, evaluateTrackAtFrame as q, CameraAnimation as r, sampleTrack as rt, CompositorProgramSchema as s, BloomConfigSchema as t, sampleLayerProp as tt, EnvironmentGiSchema as u, LayoutNodeSchema as v, Model3DNodeSchema as w, MaterialTypeSchema as x, LightNodeSchema as y, collectLayersOnClock as z };
4701
+ //# sourceMappingURL=program-CMigyfso.mjs.map