@graphrefly/ts 0.0.1 → 0.0.2

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 (330) hide show
  1. package/dist/actions-types-CSC3NMDl.d.ts +657 -0
  2. package/dist/actions-types-wl9Mgkmr.d.cts +657 -0
  3. package/dist/adapters/index.cjs +5157 -2951
  4. package/dist/adapters/index.cjs.map +1 -1
  5. package/dist/adapters/index.d.cts +207 -70
  6. package/dist/adapters/index.d.ts +207 -70
  7. package/dist/adapters/index.js +3738 -1688
  8. package/dist/adapters/index.js.map +1 -1
  9. package/dist/adapters/nestjs/microservices.cjs +841 -0
  10. package/dist/adapters/nestjs/microservices.cjs.map +1 -0
  11. package/dist/adapters/nestjs/microservices.d.cts +45 -0
  12. package/dist/adapters/nestjs/microservices.d.ts +45 -0
  13. package/dist/adapters/nestjs/microservices.js +206 -0
  14. package/dist/adapters/nestjs/microservices.js.map +1 -0
  15. package/dist/adapters/nestjs/native.cjs +1391 -0
  16. package/dist/adapters/nestjs/native.cjs.map +1 -0
  17. package/dist/adapters/nestjs/native.d.cts +111 -0
  18. package/dist/adapters/nestjs/native.d.ts +111 -0
  19. package/dist/adapters/nestjs/native.js +577 -0
  20. package/dist/adapters/nestjs/native.js.map +1 -0
  21. package/dist/adapters/nestjs/websockets.cjs +924 -0
  22. package/dist/adapters/nestjs/websockets.cjs.map +1 -0
  23. package/dist/adapters/nestjs/websockets.d.cts +47 -0
  24. package/dist/adapters/nestjs/websockets.d.ts +47 -0
  25. package/dist/adapters/nestjs/websockets.js +286 -0
  26. package/dist/adapters/nestjs/websockets.js.map +1 -0
  27. package/dist/adapters/nestjs.cjs +1085 -0
  28. package/dist/adapters/nestjs.cjs.map +1 -0
  29. package/dist/adapters/nestjs.d.cts +385 -0
  30. package/dist/adapters/nestjs.d.ts +385 -0
  31. package/dist/adapters/nestjs.js +112 -0
  32. package/dist/adapters/nestjs.js.map +1 -0
  33. package/dist/adapters/observe-storage.d.cts +3 -3
  34. package/dist/adapters/observe-storage.d.ts +3 -3
  35. package/dist/adapters/observe-storage.js +4 -4
  36. package/dist/adapters/react.cjs.map +1 -1
  37. package/dist/adapters/react.d.cts +2 -2
  38. package/dist/adapters/react.d.ts +2 -2
  39. package/dist/adapters/react.js +1 -1
  40. package/dist/adapters/solid.cjs.map +1 -1
  41. package/dist/adapters/solid.d.cts +2 -2
  42. package/dist/adapters/solid.d.ts +2 -2
  43. package/dist/adapters/solid.js +1 -1
  44. package/dist/adapters/svelte.cjs.map +1 -1
  45. package/dist/adapters/svelte.d.cts +2 -2
  46. package/dist/adapters/svelte.d.ts +2 -2
  47. package/dist/adapters/svelte.js +1 -1
  48. package/dist/adapters/vue.cjs.map +1 -1
  49. package/dist/adapters/vue.d.cts +2 -2
  50. package/dist/adapters/vue.d.ts +2 -2
  51. package/dist/adapters/vue.js +1 -1
  52. package/dist/{agent-runtime-DZTJ3C-p.d.cts → agent-runtime-types-core-CaXfKNtY.d.cts} +171 -320
  53. package/dist/{agent-runtime-BesGDZcB.d.ts → agent-runtime-types-core-hU299uIC.d.ts} +171 -320
  54. package/dist/agent-runtime-types-tool-BEpSINol.d.ts +695 -0
  55. package/dist/agent-runtime-types-tool-DninPEzk.d.cts +695 -0
  56. package/dist/agentic-memory-retention-BmGX368S.d.ts +14 -0
  57. package/dist/agentic-memory-retention-Ih1qhX9Z.d.cts +14 -0
  58. package/dist/{agentic-memory-BmRCvh0d.d.ts → agentic-memory-types-CVSUS6XR.d.ts} +13 -57
  59. package/dist/{agentic-memory-DfuVZ-lY.d.cts → agentic-memory-types-FnnYlVUs.d.cts} +13 -57
  60. package/dist/{capability-admission-g0mn9hpq.d.ts → capability-admission-BW2CziT6.d.ts} +3 -3
  61. package/dist/{capability-admission-B0BzqAm5.d.cts → capability-admission-lwSecxXs.d.cts} +3 -3
  62. package/dist/chunk-2KUAG2GZ.js +9693 -0
  63. package/dist/chunk-2KUAG2GZ.js.map +1 -0
  64. package/dist/chunk-2NJP6GO4.js +1320 -0
  65. package/dist/chunk-2NJP6GO4.js.map +1 -0
  66. package/dist/{chunk-YDSIVHRR.js → chunk-4NWSNI4K.js} +1598 -1584
  67. package/dist/chunk-4NWSNI4K.js.map +1 -0
  68. package/dist/{chunk-Z2ANQ6JW.js → chunk-4Q77MMJY.js} +2 -2
  69. package/dist/chunk-6E76H4OU.js +132 -0
  70. package/dist/chunk-6E76H4OU.js.map +1 -0
  71. package/dist/chunk-7GOTIIQ7.js +819 -0
  72. package/dist/chunk-7GOTIIQ7.js.map +1 -0
  73. package/dist/{chunk-IXZBUWSP.js → chunk-7HZRJMN6.js} +2 -2
  74. package/dist/{chunk-SS2A464I.js → chunk-CJIFGJQG.js} +3 -3
  75. package/dist/{chunk-V7CIJE4B.js → chunk-CX6B6PO2.js} +92 -9
  76. package/dist/chunk-CX6B6PO2.js.map +1 -0
  77. package/dist/{chunk-FBUU43PM.js → chunk-E4QCH32M.js} +448 -446
  78. package/dist/chunk-E4QCH32M.js.map +1 -0
  79. package/dist/{chunk-HKK2JD7Z.js → chunk-ECURQ3HD.js} +12 -125
  80. package/dist/chunk-ECURQ3HD.js.map +1 -0
  81. package/dist/{chunk-3JR3EDB2.js → chunk-EOKT4QFF.js} +121 -115
  82. package/dist/chunk-EOKT4QFF.js.map +1 -0
  83. package/dist/{chunk-K3FXTC3I.js → chunk-HJACH5PU.js} +3 -3
  84. package/dist/{chunk-GTPCOEOZ.js → chunk-IDMLXLLG.js} +3 -3
  85. package/dist/{chunk-DKP56CSW.js → chunk-JKAYLDQV.js} +2 -2
  86. package/dist/{chunk-4VLAQHZI.js → chunk-K7FB3JTD.js} +17 -1
  87. package/dist/chunk-K7FB3JTD.js.map +1 -0
  88. package/dist/{chunk-H75VXTGT.js → chunk-L6LDXRWE.js} +3 -3
  89. package/dist/{chunk-H75VXTGT.js.map → chunk-L6LDXRWE.js.map} +1 -1
  90. package/dist/{chunk-YXMZ2N6J.js → chunk-M7J6Z4IJ.js} +1071 -1025
  91. package/dist/chunk-M7J6Z4IJ.js.map +1 -0
  92. package/dist/chunk-MQEQMS7B.js +1009 -0
  93. package/dist/chunk-MQEQMS7B.js.map +1 -0
  94. package/dist/chunk-MTELVIYR.js +1421 -0
  95. package/dist/chunk-MTELVIYR.js.map +1 -0
  96. package/dist/{chunk-QFY4AFY4.js → chunk-PVC7WDKI.js} +58 -52
  97. package/dist/chunk-PVC7WDKI.js.map +1 -0
  98. package/dist/{chunk-VTHLCFN4.js → chunk-RAHNUYA5.js} +2 -2
  99. package/dist/{chunk-XKXWK2KP.js → chunk-SHZDP2MQ.js} +1157 -1021
  100. package/dist/chunk-SHZDP2MQ.js.map +1 -0
  101. package/dist/{chunk-CZNV3VXM.js → chunk-SIDJO2T4.js} +11 -11
  102. package/dist/chunk-STXRMPW4.js +4131 -0
  103. package/dist/chunk-STXRMPW4.js.map +1 -0
  104. package/dist/{chunk-2747WN4Y.js → chunk-TPND5MJS.js} +3 -3
  105. package/dist/chunk-TQPCAIQI.js +612 -0
  106. package/dist/chunk-TQPCAIQI.js.map +1 -0
  107. package/dist/{chunk-43BKLFZU.js → chunk-YDWBXXQZ.js} +10 -10
  108. package/dist/{chunk-6PHB5CJS.js → chunk-ZLFRB6FI.js} +2 -2
  109. package/dist/composition/index.cjs +1228 -1076
  110. package/dist/composition/index.cjs.map +1 -1
  111. package/dist/composition/index.d.cts +3 -3
  112. package/dist/composition/index.d.ts +3 -3
  113. package/dist/composition/index.js +4 -4
  114. package/dist/core/index.cjs +1198 -1046
  115. package/dist/core/index.cjs.map +1 -1
  116. package/dist/core/index.d.cts +1 -1
  117. package/dist/core/index.d.ts +1 -1
  118. package/dist/core/index.js +2 -2
  119. package/dist/cqrs/index.d.cts +3 -3
  120. package/dist/cqrs/index.d.ts +3 -3
  121. package/dist/cqrs/messaging.d.cts +4 -4
  122. package/dist/cqrs/messaging.d.ts +4 -4
  123. package/dist/cqrs/work-queue.d.cts +5 -5
  124. package/dist/cqrs/work-queue.d.ts +5 -5
  125. package/dist/data-structures/index.cjs +1226 -1074
  126. package/dist/data-structures/index.cjs.map +1 -1
  127. package/dist/data-structures/index.d.cts +8 -7
  128. package/dist/data-structures/index.d.ts +8 -7
  129. package/dist/data-structures/index.js +6 -5
  130. package/dist/{describe-BpyJuWkw.d.ts → describe-B_A5fbXH.d.ts} +1 -1
  131. package/dist/{describe-DYMw_l1C.d.cts → describe-CQRrkv-Q.d.cts} +1 -1
  132. package/dist/executors/tool-provider-adapters.cjs +3091 -0
  133. package/dist/executors/tool-provider-adapters.cjs.map +1 -0
  134. package/dist/executors/tool-provider-adapters.d.cts +174 -0
  135. package/dist/executors/tool-provider-adapters.d.ts +174 -0
  136. package/dist/executors/tool-provider-adapters.js +1336 -0
  137. package/dist/executors/tool-provider-adapters.js.map +1 -0
  138. package/dist/executors/tool-provider-runtime.cjs +5178 -0
  139. package/dist/executors/tool-provider-runtime.cjs.map +1 -0
  140. package/dist/executors/tool-provider-runtime.d.cts +17 -0
  141. package/dist/executors/tool-provider-runtime.d.ts +17 -0
  142. package/dist/executors/tool-provider-runtime.js +15 -0
  143. package/dist/executors/tool-provider-runtime.js.map +1 -0
  144. package/dist/executors/tool-provider.cjs +6392 -0
  145. package/dist/executors/tool-provider.cjs.map +1 -0
  146. package/dist/executors/tool-provider.d.cts +60 -0
  147. package/dist/executors/tool-provider.d.ts +60 -0
  148. package/dist/executors/tool-provider.js +89 -0
  149. package/dist/executors/tool-provider.js.map +1 -0
  150. package/dist/executors/work-queue.d.cts +6 -6
  151. package/dist/executors/work-queue.d.ts +6 -6
  152. package/dist/graph/index.cjs +1499 -1341
  153. package/dist/graph/index.cjs.map +1 -1
  154. package/dist/graph/index.d.cts +9 -8
  155. package/dist/graph/index.d.ts +9 -8
  156. package/dist/graph/index.js +23 -22
  157. package/dist/{graph-DCEWh4T2.d.cts → graph-CWK3HLPB.d.cts} +133 -131
  158. package/dist/{graph-D-1-SQeC.d.ts → graph-ho5sotHP.d.ts} +133 -131
  159. package/dist/{index-Bmxeu0nK.d.ts → index-CQWcE0Dw.d.ts} +18 -4
  160. package/dist/{index-72VZC0-E.d.cts → index-DHA1i67c.d.cts} +18 -4
  161. package/dist/index.cjs +3397 -3140
  162. package/dist/index.cjs.map +1 -1
  163. package/dist/index.d.cts +12 -9
  164. package/dist/index.d.ts +12 -9
  165. package/dist/index.js +110 -109
  166. package/dist/inspection/boundary.d.cts +4 -4
  167. package/dist/inspection/boundary.d.ts +4 -4
  168. package/dist/measurements-C0mAvWU1.d.cts +164 -0
  169. package/dist/measurements-OMpCeBwh.d.ts +164 -0
  170. package/dist/messaging/index.cjs +57 -51
  171. package/dist/messaging/index.cjs.map +1 -1
  172. package/dist/messaging/index.d.cts +11 -276
  173. package/dist/messaging/index.d.ts +11 -276
  174. package/dist/messaging/index.js +1 -1
  175. package/dist/operators/index.cjs +1228 -1076
  176. package/dist/operators/index.cjs.map +1 -1
  177. package/dist/operators/index.d.cts +5 -5
  178. package/dist/operators/index.d.ts +5 -5
  179. package/dist/operators/index.js +5 -5
  180. package/dist/orchestration/index.cjs +8844 -6071
  181. package/dist/orchestration/index.cjs.map +1 -1
  182. package/dist/orchestration/index.d.cts +171 -224
  183. package/dist/orchestration/index.d.ts +171 -224
  184. package/dist/orchestration/index.js +42 -991
  185. package/dist/orchestration/index.js.map +1 -1
  186. package/dist/orchestration/messaging.d.cts +5 -8
  187. package/dist/orchestration/messaging.d.ts +5 -8
  188. package/dist/orchestration/work-queue.cjs +1243 -5
  189. package/dist/orchestration/work-queue.cjs.map +1 -1
  190. package/dist/orchestration/work-queue.d.cts +121 -10
  191. package/dist/orchestration/work-queue.d.ts +121 -10
  192. package/dist/orchestration/work-queue.js +1067 -4
  193. package/dist/orchestration/work-queue.js.map +1 -1
  194. package/dist/patterns/event-flow.cjs +6 -20
  195. package/dist/patterns/event-flow.cjs.map +1 -1
  196. package/dist/patterns/event-flow.d.cts +4 -4
  197. package/dist/patterns/event-flow.d.ts +4 -4
  198. package/dist/patterns/event-flow.js +2 -2
  199. package/dist/patterns/index.cjs +453 -465
  200. package/dist/patterns/index.cjs.map +1 -1
  201. package/dist/patterns/index.d.cts +6 -5
  202. package/dist/patterns/index.d.ts +6 -5
  203. package/dist/patterns/index.js +3 -3
  204. package/dist/process-types-C9uMYz3i.d.ts +200 -0
  205. package/dist/process-types-h3uRlzDc.d.cts +200 -0
  206. package/dist/{reactive-collection-DNV0-gFi.d.cts → reactive-collection-B9R0Bl1P.d.cts} +4 -34
  207. package/dist/{reactive-collection-BAmfrGjd.d.ts → reactive-collection-BXFrH0U2.d.ts} +4 -34
  208. package/dist/{reactive-collection-storage-BNEldDyi.d.cts → reactive-collection-storage-BLGv8Xp8.d.cts} +5 -5
  209. package/dist/{reactive-collection-storage-YZsAQsWK.d.ts → reactive-collection-storage-a4zD3665.d.ts} +5 -5
  210. package/dist/{reactive-map-DRD1LJ2H.d.cts → reactive-map-C_8sOfdS.d.cts} +3 -2
  211. package/dist/{reactive-map-EsDiCmJk.d.ts → reactive-map-jle5dnok.d.ts} +3 -2
  212. package/dist/render/index.d.cts +2 -2
  213. package/dist/render/index.d.ts +2 -2
  214. package/dist/scheduled-readiness-5rwQlyjV.d.ts +91 -0
  215. package/dist/scheduled-readiness-DpRY8jI0.d.cts +91 -0
  216. package/dist/semantic-memory-graph-C2ZUwIlq.d.ts +30 -0
  217. package/dist/semantic-memory-graph-DlZBD_Eu.d.cts +30 -0
  218. package/dist/{semantic-memory-graph-DKuNzuWw.d.cts → semantic-memory-graph-types-BvzdqmkY.d.cts} +2 -28
  219. package/dist/{semantic-memory-graph-uwbwJdhe.d.ts → semantic-memory-graph-types-Ci-OtahO.d.ts} +2 -28
  220. package/dist/solutions/index.cjs +6353 -6169
  221. package/dist/solutions/index.cjs.map +1 -1
  222. package/dist/solutions/index.d.cts +12 -10
  223. package/dist/solutions/index.d.ts +12 -10
  224. package/dist/solutions/index.js +5 -5
  225. package/dist/solutions/reactive-layout/browser/index.cjs +116 -108
  226. package/dist/solutions/reactive-layout/browser/index.cjs.map +1 -1
  227. package/dist/solutions/reactive-layout/browser/index.d.cts +4 -4
  228. package/dist/solutions/reactive-layout/browser/index.d.ts +4 -4
  229. package/dist/solutions/reactive-layout/browser/index.js +3 -3
  230. package/dist/solutions/reactive-layout/index.cjs +3578 -3350
  231. package/dist/solutions/reactive-layout/index.cjs.map +1 -1
  232. package/dist/solutions/reactive-layout/index.d.cts +32 -576
  233. package/dist/solutions/reactive-layout/index.d.ts +32 -576
  234. package/dist/solutions/reactive-layout/index.js +65 -5
  235. package/dist/solutions/reactive-layout/node-canvas/index.cjs +127 -117
  236. package/dist/solutions/reactive-layout/node-canvas/index.cjs.map +1 -1
  237. package/dist/solutions/reactive-layout/node-canvas/index.d.cts +4 -4
  238. package/dist/solutions/reactive-layout/node-canvas/index.d.ts +4 -4
  239. package/dist/solutions/reactive-layout/node-canvas/index.js +3 -3
  240. package/dist/solutions/reactive-layout/react-native/index.cjs +127 -117
  241. package/dist/solutions/reactive-layout/react-native/index.cjs.map +1 -1
  242. package/dist/solutions/reactive-layout/react-native/index.d.cts +4 -4
  243. package/dist/solutions/reactive-layout/react-native/index.d.ts +4 -4
  244. package/dist/solutions/reactive-layout/react-native/index.js +3 -3
  245. package/dist/solutions/reactive-layout/skia/index.cjs +127 -117
  246. package/dist/solutions/reactive-layout/skia/index.cjs.map +1 -1
  247. package/dist/solutions/reactive-layout/skia/index.d.cts +4 -4
  248. package/dist/solutions/reactive-layout/skia/index.d.ts +4 -4
  249. package/dist/solutions/reactive-layout/skia/index.js +3 -3
  250. package/dist/solutions/work-item/actions.cjs +1609 -1428
  251. package/dist/solutions/work-item/actions.cjs.map +1 -1
  252. package/dist/solutions/work-item/actions.d.cts +23 -184
  253. package/dist/solutions/work-item/actions.d.ts +23 -184
  254. package/dist/solutions/work-item/actions.js +1558 -934
  255. package/dist/solutions/work-item/actions.js.map +1 -1
  256. package/dist/solutions/work-item/scheduling.cjs +9181 -1838
  257. package/dist/solutions/work-item/scheduling.cjs.map +1 -1
  258. package/dist/solutions/work-item/scheduling.d.cts +1763 -328
  259. package/dist/solutions/work-item/scheduling.d.ts +1763 -328
  260. package/dist/solutions/work-item/scheduling.js +117 -3
  261. package/dist/solutions/work-item/work-queue.d.cts +7 -7
  262. package/dist/solutions/work-item/work-queue.d.ts +7 -7
  263. package/dist/sources/browser.cjs +1318 -1083
  264. package/dist/sources/browser.cjs.map +1 -1
  265. package/dist/sources/browser.d.cts +4 -4
  266. package/dist/sources/browser.d.ts +4 -4
  267. package/dist/sources/browser.js +4 -4
  268. package/dist/sources/index.cjs +1318 -1083
  269. package/dist/sources/index.cjs.map +1 -1
  270. package/dist/sources/index.d.cts +4 -4
  271. package/dist/sources/index.d.ts +4 -4
  272. package/dist/sources/index.js +4 -4
  273. package/dist/sources/node.d.cts +3 -3
  274. package/dist/sources/node.d.ts +3 -3
  275. package/dist/storage/browser.cjs +16 -0
  276. package/dist/storage/browser.cjs.map +1 -1
  277. package/dist/storage/browser.js +3 -3
  278. package/dist/storage/index.cjs +16 -0
  279. package/dist/storage/index.cjs.map +1 -1
  280. package/dist/storage/index.d.cts +5 -4
  281. package/dist/storage/index.d.ts +5 -4
  282. package/dist/storage/index.js +6 -6
  283. package/dist/storage/node.cjs +16 -0
  284. package/dist/storage/node.cjs.map +1 -1
  285. package/dist/storage/node.js +3 -3
  286. package/dist/{store-C-joM4gh.d.ts → store-BmtEs9mG.d.ts} +1 -1
  287. package/dist/{store-CNJwmT-h.d.cts → store-PAAsYvML.d.cts} +1 -1
  288. package/dist/types-BRNKoFHj.d.ts +357 -0
  289. package/dist/{types-CcPIn7sy.d.cts → types-BS6CyR-x.d.cts} +27 -108
  290. package/dist/types-BWK2ay3e.d.cts +457 -0
  291. package/dist/types-BXKSAoE1.d.cts +357 -0
  292. package/dist/types-BaPpZItj.d.ts +457 -0
  293. package/dist/types-BhveCMg5.d.cts +274 -0
  294. package/dist/{types-BsJvElYZ.d.ts → types-C9NOgNJw.d.ts} +27 -108
  295. package/dist/types-CTsQ8Ww4.d.ts +274 -0
  296. package/dist/types-DL_05n2M.d.ts +34 -0
  297. package/dist/types-XDoqxYO9.d.cts +34 -0
  298. package/dist/{work-item-runtime-C3M79vE9.d.ts → work-item-runtime-types-BqtWnSCS.d.ts} +3 -93
  299. package/dist/{work-item-runtime-qaVgsL0T.d.cts → work-item-runtime-types-CHO03AKh.d.cts} +3 -93
  300. package/dist/work-queue/index.cjs +957 -953
  301. package/dist/work-queue/index.cjs.map +1 -1
  302. package/dist/work-queue/index.d.cts +9 -357
  303. package/dist/work-queue/index.d.ts +9 -357
  304. package/dist/work-queue/index.js +957 -953
  305. package/dist/work-queue/index.js.map +1 -1
  306. package/package.json +603 -513
  307. package/dist/chunk-3JR3EDB2.js.map +0 -1
  308. package/dist/chunk-4VLAQHZI.js.map +0 -1
  309. package/dist/chunk-6XAIOL3X.js +0 -2407
  310. package/dist/chunk-6XAIOL3X.js.map +0 -1
  311. package/dist/chunk-FBUU43PM.js.map +0 -1
  312. package/dist/chunk-HKK2JD7Z.js.map +0 -1
  313. package/dist/chunk-PC3BTTBE.js +0 -3217
  314. package/dist/chunk-PC3BTTBE.js.map +0 -1
  315. package/dist/chunk-QFY4AFY4.js.map +0 -1
  316. package/dist/chunk-V7CIJE4B.js.map +0 -1
  317. package/dist/chunk-XKXWK2KP.js.map +0 -1
  318. package/dist/chunk-YDSIVHRR.js.map +0 -1
  319. package/dist/chunk-YXMZ2N6J.js.map +0 -1
  320. /package/dist/{chunk-Z2ANQ6JW.js.map → chunk-4Q77MMJY.js.map} +0 -0
  321. /package/dist/{chunk-IXZBUWSP.js.map → chunk-7HZRJMN6.js.map} +0 -0
  322. /package/dist/{chunk-SS2A464I.js.map → chunk-CJIFGJQG.js.map} +0 -0
  323. /package/dist/{chunk-K3FXTC3I.js.map → chunk-HJACH5PU.js.map} +0 -0
  324. /package/dist/{chunk-GTPCOEOZ.js.map → chunk-IDMLXLLG.js.map} +0 -0
  325. /package/dist/{chunk-DKP56CSW.js.map → chunk-JKAYLDQV.js.map} +0 -0
  326. /package/dist/{chunk-VTHLCFN4.js.map → chunk-RAHNUYA5.js.map} +0 -0
  327. /package/dist/{chunk-CZNV3VXM.js.map → chunk-SIDJO2T4.js.map} +0 -0
  328. /package/dist/{chunk-2747WN4Y.js.map → chunk-TPND5MJS.js.map} +0 -0
  329. /package/dist/{chunk-43BKLFZU.js.map → chunk-YDWBXXQZ.js.map} +0 -0
  330. /package/dist/{chunk-6PHB5CJS.js.map → chunk-ZLFRB6FI.js.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Node
3
- } from "./chunk-XKXWK2KP.js";
3
+ } from "./chunk-SHZDP2MQ.js";
4
4
  import {
5
5
  depLatest
6
6
  } from "./chunk-WQIA3GFB.js";
@@ -8,12 +8,7 @@ import {
8
8
  errorPayload
9
9
  } from "./chunk-S6HXABGL.js";
10
10
 
11
- // src/solutions/reactive-layout/index.ts
12
- var TEXT_SEGMENTS_MEASUREMENT_KIND = "text-segments";
13
- var BLOCKS_MEASUREMENT_KIND = "blocks";
14
- var READINESS_MEASUREMENT_KIND = "readiness";
15
- var IMAGE_SIZE_MEASUREMENT_KIND = "image-size";
16
- var SVG_BOUNDS_MEASUREMENT_KIND = "svg-bounds";
11
+ // src/solutions/reactive-layout/segment.ts
17
12
  var kinsokuStart = /* @__PURE__ */ new Set([
18
13
  "\u3001",
19
14
  "\u3002",
@@ -159,6 +154,43 @@ function measuredWidth(value) {
159
154
  function metricKey(text, font) {
160
155
  return `${font}\0${text}`;
161
156
  }
157
+
158
+ // src/solutions/reactive-layout/utils.ts
159
+ function nonNegativeFinite(value, fallback) {
160
+ return Number.isFinite(value) ? Math.max(0, value) : fallback;
161
+ }
162
+ function finiteNumber(value, fallback) {
163
+ return Number.isFinite(value) ? value : fallback;
164
+ }
165
+ function emitLayoutError(ctx, error, fallback) {
166
+ ctx.down([["ERROR", errorPayload(error, fallback)]]);
167
+ }
168
+ function positiveFinite(value, fallback) {
169
+ return Number.isFinite(value) && value > 0 ? value : fallback;
170
+ }
171
+ function clampDimension(value) {
172
+ return nonNegativeFinite(value ?? 0, 0);
173
+ }
174
+ function fitSize(size, maxWidth) {
175
+ const width = nonNegativeFinite(size.width, 0);
176
+ const height = nonNegativeFinite(size.height, 0);
177
+ if (width === 0 || maxWidth <= 0 || width <= maxWidth) return { width, height };
178
+ const scale = maxWidth / width;
179
+ return { width: maxWidth, height: height * scale };
180
+ }
181
+ function blockMaxWidth(blockMaxWidth2, maxWidth) {
182
+ const own = blockMaxWidth2 === void 0 ? maxWidth : nonNegativeFinite(blockMaxWidth2, maxWidth);
183
+ if (maxWidth <= 0) return own;
184
+ if (own <= 0) return maxWidth;
185
+ return Math.min(own, maxWidth);
186
+ }
187
+ function resolveTextAdapter(opts) {
188
+ const adapter = opts.adapters?.text ?? opts.adapter;
189
+ if (!adapter) throw new Error("Text blocks require a MeasurementAdapter");
190
+ return adapter;
191
+ }
192
+
193
+ // src/solutions/reactive-layout/adapters.ts
162
194
  var InjectedMeasureAdapter = class {
163
195
  measure;
164
196
  shouldCache;
@@ -289,1075 +321,1055 @@ function isImageSizeLookup(value) {
289
321
  if (valueType !== "object" && valueType !== "function") return false;
290
322
  return typeof value.get === "function";
291
323
  }
292
- function measurementIssue(code, message, targetId, measurementKind, opts = {}) {
293
- return {
294
- kind: "issue",
295
- code,
296
- message,
297
- severity: opts.severity ?? "warning",
298
- source: opts.source,
299
- subjectId: targetId,
300
- measurementKind,
301
- details: opts.details,
302
- metadata: opts.metadata
303
- };
304
- }
305
- function measurementOk(targetId, measurementKind, value, opts = {}) {
306
- return {
307
- kind: "ok",
308
- targetId,
309
- measurementKind,
310
- value,
311
- source: opts.source,
312
- metadata: opts.metadata
313
- };
314
- }
315
- function latestMeasurementValue(measurements, targetId, measurementKind) {
316
- let value;
317
- for (const fact of measurements) {
318
- if (fact.kind === "ok" && fact.targetId === targetId && fact.measurementKind === measurementKind) {
319
- value = fact.value;
320
- }
324
+
325
+ // src/solutions/reactive-layout/line.ts
326
+ function analyzeAndMeasure(text, font, adapter, cache, stats, segmentAdapter) {
327
+ const normalized = normalizeWhitespace(text);
328
+ if (normalized.length === 0) {
329
+ return [];
321
330
  }
322
- return value;
323
- }
324
- function tryMeasureHyphenWidth(adapter, font) {
325
- try {
326
- return nonNegativeFinite(adapter.measureSegment("-", font).width, 0);
327
- } catch {
328
- return void 0;
331
+ const segAdapter = segmentAdapter ?? getDefaultSegmentAdapter();
332
+ const pieces = segmentText(normalized, segAdapter);
333
+ const rawTexts = [];
334
+ const rawKinds = [];
335
+ const rawWordLike = [];
336
+ for (const piece of pieces) {
337
+ for (let i = 0; i < piece.texts.length; i += 1) {
338
+ rawTexts.push(piece.texts[i]);
339
+ rawKinds.push(piece.kinds[i]);
340
+ rawWordLike.push(piece.isWordLike[i]);
341
+ }
329
342
  }
330
- }
331
- function validMeasurementSize(size, label) {
332
- if (!Number.isFinite(size.width) || !Number.isFinite(size.height) || size.width < 0 || size.height < 0) {
333
- throw new Error(`Invalid ${label} measurement size`);
343
+ const mergedTexts = [];
344
+ const mergedKinds = [];
345
+ const mergedWordLike = [];
346
+ for (let i = 0; i < rawTexts.length; i += 1) {
347
+ const t = rawTexts[i];
348
+ const k = rawKinds[i];
349
+ const wl = rawWordLike[i];
350
+ if (k === "text" && !wl && mergedTexts.length > 0 && mergedKinds[mergedTexts.length - 1] === "text") {
351
+ const isSticky = t.length === 1 && (leftStickyPunctuation.has(t) || kinsokuStart.has(t));
352
+ if (isSticky) {
353
+ mergedTexts[mergedTexts.length - 1] += t;
354
+ continue;
355
+ }
356
+ }
357
+ if (t === "-" && mergedTexts.length > 0 && mergedKinds[mergedKinds.length - 1] === "text" && mergedWordLike[mergedWordLike.length - 1]) {
358
+ mergedTexts[mergedTexts.length - 1] += t;
359
+ continue;
360
+ }
361
+ mergedTexts.push(t);
362
+ mergedKinds.push(k);
363
+ mergedWordLike.push(wl);
334
364
  }
335
- return size;
336
- }
337
- function textMeasurementFacts(text, font, adapter, cache, segmentAdapter, targetId, source) {
338
- try {
339
- const segments = analyzeAndMeasure(text, font, adapter, cache, void 0, segmentAdapter);
340
- const hyphenWidth = tryMeasureHyphenWidth(adapter, font);
341
- const facts = [
342
- measurementOk(
343
- targetId,
344
- TEXT_SEGMENTS_MEASUREMENT_KIND,
345
- hyphenWidth === void 0 ? { segments } : { segments, hyphenWidth },
346
- { source }
347
- )
348
- ];
349
- if (hyphenWidth === void 0) {
350
- facts.push(
351
- measurementIssue(
352
- "measurement.hyphen.failed",
353
- `Hyphen measurement failed for '${targetId}'`,
354
- targetId,
355
- TEXT_SEGMENTS_MEASUREMENT_KIND,
356
- { source, severity: "warning" }
357
- )
358
- );
365
+ const fontCache = cache.get(font) ?? /* @__PURE__ */ new Map();
366
+ if (!cache.has(font)) cache.set(font, fontCache);
367
+ function measureCached(segment) {
368
+ const cached = fontCache.get(segment);
369
+ if (cached === void 0) {
370
+ if (stats) stats.misses += 1;
371
+ const measured = adapter.measureSegment(segment, font).width;
372
+ const width = Number.isFinite(measured) && measured >= 0 ? measured : 0;
373
+ fontCache.set(segment, width);
374
+ return width;
359
375
  }
360
- return facts;
361
- } catch (error) {
362
- return [
363
- measurementIssue(
364
- "measurement.failed",
365
- `Text measurement failed for '${targetId}'`,
366
- targetId,
367
- TEXT_SEGMENTS_MEASUREMENT_KIND,
368
- { source, details: error, severity: "error" }
369
- )
370
- ];
376
+ if (stats) stats.hits += 1;
377
+ return cached;
371
378
  }
372
- }
373
- function inputNode(g, input, fallback, name) {
374
- if (input instanceof Node) {
375
- return {
376
- node: input,
377
- set(value) {
378
- const maybeState = input;
379
- if (typeof maybeState.set !== "function") {
380
- throw new TypeError(`reactive-layout input '${name}' is not a writable state node`);
379
+ const out = [];
380
+ for (let i = 0; i < mergedTexts.length; i += 1) {
381
+ const t = mergedTexts[i];
382
+ const kind = mergedKinds[i];
383
+ if (kind !== "text") {
384
+ out.push({
385
+ text: t,
386
+ width: kind === "space" ? measureCached(" ") * t.length : 0,
387
+ kind,
388
+ graphemeWidths: null
389
+ });
390
+ continue;
391
+ }
392
+ if (isCJK(t)) {
393
+ let unitText = "";
394
+ for (const graphemeSegment of segAdapter.segmentGraphemes(t)) {
395
+ const grapheme = graphemeSegment.segment;
396
+ if (unitText.length > 0 && kinsokuStart.has(grapheme)) {
397
+ unitText += grapheme;
398
+ continue;
381
399
  }
382
- maybeState.set(value);
400
+ if (unitText.length > 0) {
401
+ out.push({
402
+ text: unitText,
403
+ width: measureCached(unitText),
404
+ kind: "text",
405
+ graphemeWidths: null
406
+ });
407
+ }
408
+ unitText = grapheme;
383
409
  }
384
- };
410
+ if (unitText.length > 0) {
411
+ out.push({
412
+ text: unitText,
413
+ width: measureCached(unitText),
414
+ kind: "text",
415
+ graphemeWidths: null
416
+ });
417
+ }
418
+ continue;
419
+ }
420
+ const textWidth = measureCached(t);
421
+ let graphemeWidths = null;
422
+ if (mergedWordLike[i] && t.length > 1) {
423
+ const widths = [];
424
+ for (const grapheme of segAdapter.segmentGraphemes(t)) {
425
+ widths.push(measureCached(grapheme.segment));
426
+ }
427
+ if (widths.length > 1) graphemeWidths = widths;
428
+ }
429
+ out.push({
430
+ text: t,
431
+ width: textWidth,
432
+ kind: "text",
433
+ graphemeWidths
434
+ });
385
435
  }
386
- const state = g.state(input ?? fallback, { name });
387
- return { node: state, set: (value) => state.set(value) };
388
- }
389
- function scopedName(scope, local) {
390
- return scope === local ? local : `${scope}:${local}`;
436
+ return out;
391
437
  }
392
- function textMeasurementProvider(opts) {
393
- const targetId = opts.targetId ?? "text";
394
- const name = opts.name ?? `${targetId}-measurements`;
395
- const source = opts.source ?? name;
396
- const cache = /* @__PURE__ */ new Map();
397
- let activeAdapter = null;
398
- return opts.graph.node(
399
- opts.segmentAdapter ? [opts.text, opts.font, opts.adapter, opts.segmentAdapter] : [opts.text, opts.font, opts.adapter],
400
- (ctx) => {
401
- const flush = () => {
402
- cache.clear();
403
- depLatest(ctx, 2).clearCache?.();
404
- };
405
- ctx.onDeactivation(flush);
406
- ctx.onInvalidate(flush);
407
- const text = depLatest(ctx, 0);
408
- const font = depLatest(ctx, 1);
409
- const adapter = depLatest(ctx, 2);
410
- if (adapter !== activeAdapter) {
411
- cache.clear();
412
- activeAdapter = adapter;
413
- }
414
- const segmentAdapter = opts.segmentAdapter === void 0 ? getDefaultSegmentAdapter() : depLatest(ctx, 3);
415
- ctx.down([
416
- [
417
- "DATA",
418
- textMeasurementFacts(text, font, adapter, cache, segmentAdapter, targetId, source)
419
- ]
420
- ]);
421
- },
422
- { name }
423
- );
424
- }
425
- function injectedTextMeasurements(opts) {
426
- const targetId = opts.targetId ?? "text";
427
- const adapter = opts.graph.state(
428
- new InjectedMeasureAdapter(opts.measure, { cache: opts.cache }),
429
- {
430
- name: opts.name ? scopedName(opts.name, "measure-capability") : `${targetId}-measure-capability`
438
+ function computeLineBreaks(segments, maxWidth, opts = {}) {
439
+ if (segments.length === 0) return { lines: [], lineCount: 0 };
440
+ const segAdapter = opts.segmentAdapter ?? getDefaultSegmentAdapter();
441
+ const lines = [];
442
+ let cursor = { segmentIndex: 0, graphemeIndex: 0 };
443
+ while (cursor.segmentIndex < segments.length) {
444
+ const next = layoutNextLine(segments, cursor, maxWidth, {
445
+ hyphenWidth: opts.hyphenWidth,
446
+ segmentAdapter: segAdapter
447
+ });
448
+ if (next === null) break;
449
+ lines.push({
450
+ text: next.text,
451
+ width: next.width,
452
+ startSegment: next.start.segmentIndex,
453
+ startGrapheme: next.start.graphemeIndex,
454
+ endSegment: next.end.segmentIndex,
455
+ endGrapheme: next.end.graphemeIndex
456
+ });
457
+ if (next.end.segmentIndex === cursor.segmentIndex && next.end.graphemeIndex === cursor.graphemeIndex) {
458
+ break;
431
459
  }
432
- );
433
- return textMeasurementProvider({
434
- ...opts,
435
- adapter,
436
- source: opts.source ?? "injectedTextMeasurements"
437
- });
460
+ cursor = next.end;
461
+ }
462
+ return { lines, lineCount: lines.length };
438
463
  }
439
- function precomputedTextMeasurements(opts) {
440
- const targetId = opts.targetId ?? "text";
441
- const adapter = opts.graph.state(new PrecomputedMeasureAdapter(opts), {
442
- name: opts.name ? scopedName(opts.name, "measure-capability") : `${targetId}-measure-capability`
443
- });
444
- return textMeasurementProvider({
445
- ...opts,
446
- adapter,
447
- source: opts.source ?? "precomputedTextMeasurements"
448
- });
464
+ function canBreakAfter(kind) {
465
+ return kind === "space" || kind === "zero-width-break" || kind === "soft-hyphen";
449
466
  }
450
- function cellTextMeasurements(opts) {
451
- const targetId = opts.targetId ?? "text";
452
- const adapter = opts.graph.state(new CellMeasureAdapter(opts), {
453
- name: opts.name ? scopedName(opts.name, "measure-capability") : `${targetId}-measure-capability`
454
- });
455
- return textMeasurementProvider({
456
- ...opts,
457
- adapter,
458
- source: opts.source ?? "cellTextMeasurements"
459
- });
467
+ function sliceSegmentText(seg, startGrapheme, endGrapheme, segmentAdapter) {
468
+ if (startGrapheme === 0 && endGrapheme < 0) return seg.text;
469
+ const graphemes = [...segmentAdapter.segmentGraphemes(seg.text)].map((g) => g.segment);
470
+ const stop = endGrapheme < 0 ? graphemes.length : endGrapheme;
471
+ return graphemes.slice(startGrapheme, stop).join("");
460
472
  }
461
- function capabilityTextMeasurements(opts) {
462
- const targetId = opts.targetId ?? "text";
463
- const adapter = opts.graph.node(
464
- [opts.capability],
465
- (ctx) => {
466
- ctx.down([
467
- ["DATA", new CapabilityMeasureAdapter(depLatest(ctx, 0))]
468
- ]);
469
- },
470
- {
471
- name: opts.name ? scopedName(opts.name, "measure-capability") : `${targetId}-measure-capability`
473
+ function buildLineText(segments, startSegment, startGrapheme, endSegment, endGrapheme, appendHyphen, segmentAdapter) {
474
+ let text = "";
475
+ for (let i = startSegment; i < endSegment; i += 1) {
476
+ const seg = segments[i];
477
+ if (seg.kind === "soft-hyphen" || seg.kind === "hard-break") continue;
478
+ if (i === startSegment && startGrapheme > 0) {
479
+ text += sliceSegmentText(seg, startGrapheme, -1, segmentAdapter);
480
+ } else {
481
+ text += seg.text;
472
482
  }
473
- );
474
- return textMeasurementProvider({
475
- ...opts,
476
- adapter,
477
- source: opts.source ?? "capabilityTextMeasurements"
478
- });
483
+ }
484
+ if (endGrapheme > 0 && endSegment < segments.length) {
485
+ const seg = segments[endSegment];
486
+ const from = startSegment === endSegment ? startGrapheme : 0;
487
+ text += sliceSegmentText(seg, from, endGrapheme, segmentAdapter);
488
+ }
489
+ if (appendHyphen) text += "-";
490
+ return text;
479
491
  }
480
- function readinessTextMeasurements(opts) {
481
- const targetId = opts.targetId ?? "text";
482
- const name = opts.name ?? `${targetId}-measurements`;
483
- const source = opts.source ?? name;
484
- const cache = /* @__PURE__ */ new Map();
485
- let activeAdapter = null;
486
- let activeReadiness = null;
487
- const deps = opts.segmentAdapter ? [opts.text, opts.font, opts.adapter, opts.readiness, opts.segmentAdapter] : [opts.text, opts.font, opts.adapter, opts.readiness];
488
- return opts.graph.node(
489
- deps,
490
- (ctx) => {
491
- const flush = () => {
492
- cache.clear();
493
- depLatest(ctx, 2).clearCache?.();
494
- };
495
- ctx.onDeactivation(flush);
496
- ctx.onInvalidate(flush);
497
- const text = depLatest(ctx, 0);
498
- const font = depLatest(ctx, 1);
499
- const adapter = depLatest(ctx, 2);
500
- if (adapter !== activeAdapter) {
501
- cache.clear();
502
- activeAdapter = adapter;
492
+ function resolveHyphenWidth(ctx) {
493
+ if (ctx?.hyphenWidth !== void 0) return nonNegativeFinite(ctx.hyphenWidth, 0);
494
+ if (ctx?.adapter === void 0 || ctx.font === void 0) return 0;
495
+ const cache = ctx.cache;
496
+ if (cache) {
497
+ let fontCache = cache.get(ctx.font);
498
+ if (fontCache === void 0) {
499
+ fontCache = /* @__PURE__ */ new Map();
500
+ cache.set(ctx.font, fontCache);
501
+ }
502
+ let width = fontCache.get("-");
503
+ if (width === void 0) {
504
+ width = ctx.adapter.measureSegment("-", ctx.font).width;
505
+ fontCache.set("-", width);
506
+ }
507
+ return width;
508
+ }
509
+ return ctx.adapter.measureSegment("-", ctx.font).width;
510
+ }
511
+ function layoutNextLine(segments, cursor, slotWidth, ctx) {
512
+ let i = cursor.segmentIndex;
513
+ const initialGrapheme = cursor.graphemeIndex;
514
+ const segmentAdapter = ctx?.segmentAdapter ?? getDefaultSegmentAdapter();
515
+ if (i >= segments.length) return null;
516
+ if (initialGrapheme === 0) {
517
+ while (i < segments.length) {
518
+ const seg = segments[i];
519
+ if (seg.kind === "hard-break") {
520
+ return {
521
+ text: "",
522
+ width: 0,
523
+ start: { segmentIndex: cursor.segmentIndex, graphemeIndex: 0 },
524
+ end: { segmentIndex: i + 1, graphemeIndex: 0 }
525
+ };
503
526
  }
504
- const readiness = depLatest(ctx, 3);
505
- if (readiness !== activeReadiness) {
506
- cache.clear();
507
- activeReadiness = readiness;
527
+ if (seg.kind === "space" || seg.kind === "zero-width-break" || seg.kind === "soft-hyphen") {
528
+ i += 1;
529
+ continue;
508
530
  }
509
- if (!readiness.ready) {
510
- ctx.down([
511
- [
512
- "DATA",
513
- [
514
- measurementIssue(
515
- readiness.code ?? "measurement.not-ready",
516
- readiness.message ?? `Measurement readiness blocked '${targetId}'`,
517
- targetId,
518
- TEXT_SEGMENTS_MEASUREMENT_KIND,
519
- {
520
- source: readiness.source ?? source,
521
- details: readiness.details,
522
- metadata: readiness.metadata,
523
- severity: "warning"
524
- }
525
- )
526
- ]
527
- ]
528
- ]);
529
- return;
531
+ break;
532
+ }
533
+ if (i >= segments.length) return null;
534
+ }
535
+ const hyphenWidth = resolveHyphenWidth(ctx);
536
+ const startSegment = i;
537
+ const startGrapheme = i === cursor.segmentIndex ? initialGrapheme : 0;
538
+ let lineW = 0;
539
+ let lineEndSegment = startSegment;
540
+ let lineEndGrapheme = 0;
541
+ let hasContent = false;
542
+ let pendingBreakSegment = -1;
543
+ let pendingBreakGrapheme = 0;
544
+ let pendingBreakWidth = 0;
545
+ let pendingBreakSoftHyphen = false;
546
+ const recordPending = (sIdx, gIdx, width, kind) => {
547
+ pendingBreakSegment = sIdx;
548
+ pendingBreakGrapheme = gIdx;
549
+ pendingBreakWidth = width;
550
+ pendingBreakSoftHyphen = kind === "soft-hyphen";
551
+ };
552
+ const consumeBreakable = (segIdx, startG, widths) => {
553
+ for (let g = startG; g < widths.length; g += 1) {
554
+ const gw = widths[g];
555
+ if (!hasContent) {
556
+ lineW = gw;
557
+ lineEndSegment = segIdx;
558
+ lineEndGrapheme = g + 1;
559
+ hasContent = true;
560
+ continue;
530
561
  }
531
- const segmentAdapter = opts.segmentAdapter === void 0 ? getDefaultSegmentAdapter() : depLatest(ctx, 4);
532
- ctx.down([
533
- [
534
- "DATA",
535
- textMeasurementFacts(text, font, adapter, cache, segmentAdapter, targetId, source)
536
- ]
537
- ]);
538
- },
539
- { name }
540
- );
541
- }
542
- function readinessMeasurements(opts) {
543
- const targetId = opts.targetId ?? "measurement-readiness";
544
- const measurementKind = opts.measurementKind ?? READINESS_MEASUREMENT_KIND;
545
- const name = opts.name ?? `${targetId}-measurements`;
546
- const source = opts.source ?? name;
547
- return opts.graph.node(
548
- [opts.readiness],
549
- (ctx) => {
550
- const readiness = depLatest(ctx, 0);
551
- if (!readiness.ready) {
552
- ctx.down([
553
- [
554
- "DATA",
555
- [
556
- measurementIssue(
557
- readiness.code ?? "measurement.not-ready",
558
- readiness.message ?? `Measurement readiness blocked '${targetId}'`,
559
- targetId,
560
- measurementKind,
561
- {
562
- source: readiness.source ?? source,
563
- details: readiness.details,
564
- metadata: readiness.metadata,
565
- severity: "warning"
566
- }
567
- )
568
- ]
569
- ]
570
- ]);
571
- return;
562
+ if (lineW + gw > slotWidth + 1e-3) {
563
+ return true;
572
564
  }
573
- ctx.down([
574
- [
575
- "DATA",
576
- [
577
- measurementOk(targetId, measurementKind, readiness, {
578
- source: readiness.source ?? source,
579
- metadata: readiness.metadata
580
- })
581
- ]
582
- ]
583
- ]);
584
- },
585
- { name }
586
- );
587
- }
588
- function imageSizeMeasurements(opts) {
589
- const measurementKind = opts.measurementKind ?? IMAGE_SIZE_MEASUREMENT_KIND;
590
- const name = opts.name ?? "image-size-measurements";
591
- const source = opts.source ?? name;
592
- return opts.graph.node(
593
- [opts.images, opts.measurer],
594
- (ctx) => {
595
- const images = depLatest(ctx, 0);
596
- const measurer = depLatest(ctx, 1);
597
- const facts = [];
598
- for (let i = 0; i < images.length; i += 1) {
599
- const image = images[i];
600
- const subjectId = image?.id ?? image?.src ?? `image:${i}`;
601
- try {
602
- if (image === void 0) throw new Error(`Missing image target at index ${i}`);
603
- facts.push(
604
- measurementOk(
605
- subjectId,
606
- measurementKind,
607
- validMeasurementSize(measurer.measureImage(image.src), "image"),
608
- {
609
- source,
610
- metadata: image.metadata
611
- }
612
- )
613
- );
614
- } catch (error) {
615
- facts.push(
616
- measurementIssue(
617
- "measurement.image-size.failed",
618
- `Image size measurement failed for '${subjectId}'`,
619
- subjectId,
620
- measurementKind,
621
- {
622
- source,
623
- details: { error, index: i, src: image?.src },
624
- metadata: image?.metadata,
625
- severity: "error"
626
- }
627
- )
628
- );
629
- }
565
+ lineW += gw;
566
+ lineEndSegment = segIdx;
567
+ lineEndGrapheme = g + 1;
568
+ }
569
+ if (lineEndSegment === segIdx && lineEndGrapheme === widths.length) {
570
+ lineEndSegment = segIdx + 1;
571
+ lineEndGrapheme = 0;
572
+ }
573
+ return false;
574
+ };
575
+ if (startGrapheme > 0 && startSegment < segments.length) {
576
+ const seg = segments[startSegment];
577
+ if (seg.graphemeWidths) {
578
+ const overflow = consumeBreakable(startSegment, startGrapheme, seg.graphemeWidths);
579
+ if (overflow) {
580
+ const text2 = buildLineText(
581
+ segments,
582
+ startSegment,
583
+ startGrapheme,
584
+ lineEndSegment,
585
+ lineEndGrapheme,
586
+ false,
587
+ segmentAdapter
588
+ );
589
+ return {
590
+ text: text2,
591
+ width: lineW,
592
+ start: { segmentIndex: startSegment, graphemeIndex: startGrapheme },
593
+ end: { segmentIndex: lineEndSegment, graphemeIndex: lineEndGrapheme }
594
+ };
630
595
  }
631
- ctx.down([["DATA", facts]]);
632
- },
633
- { name }
634
- );
635
- }
636
- function svgBoundsMeasurements(opts) {
637
- const measurementKind = opts.measurementKind ?? SVG_BOUNDS_MEASUREMENT_KIND;
638
- const name = opts.name ?? "svg-bounds-measurements";
639
- const source = opts.source ?? name;
640
- return opts.graph.node(
641
- [opts.svgs, opts.measurer],
642
- (ctx) => {
643
- const svgs = depLatest(ctx, 0);
644
- const measurer = depLatest(ctx, 1);
645
- const facts = [];
646
- for (let i = 0; i < svgs.length; i += 1) {
647
- const svg = svgs[i];
648
- const subjectId = svg?.id ?? `svg:${i}`;
649
- try {
650
- if (svg === void 0) throw new Error(`Missing SVG target at index ${i}`);
651
- facts.push(
652
- measurementOk(
653
- subjectId,
654
- measurementKind,
655
- validMeasurementSize(measurer.measureSvg(svg.svg), "SVG"),
656
- {
657
- source,
658
- metadata: svg.metadata
659
- }
660
- )
661
- );
662
- } catch (error) {
663
- facts.push(
664
- measurementIssue(
665
- "measurement.svg-bounds.failed",
666
- `SVG bounds measurement failed for '${subjectId}'`,
667
- subjectId,
668
- measurementKind,
669
- {
670
- source,
671
- details: { error, index: i },
672
- metadata: svg?.metadata,
673
- severity: "error"
674
- }
675
- )
596
+ i = lineEndSegment;
597
+ }
598
+ }
599
+ for (; i < segments.length; i += 1) {
600
+ const seg = segments[i];
601
+ if (seg.kind === "hard-break") {
602
+ if (hasContent) {
603
+ const endsAtSoftHyphen2 = lineEndSegment > 0 && segments[lineEndSegment - 1]?.kind === "soft-hyphen";
604
+ const text2 = buildLineText(
605
+ segments,
606
+ startSegment,
607
+ startGrapheme,
608
+ lineEndSegment,
609
+ lineEndGrapheme,
610
+ endsAtSoftHyphen2,
611
+ segmentAdapter
612
+ );
613
+ return {
614
+ text: text2,
615
+ width: lineW + (endsAtSoftHyphen2 ? hyphenWidth : 0),
616
+ start: { segmentIndex: startSegment, graphemeIndex: startGrapheme },
617
+ end: { segmentIndex: i + 1, graphemeIndex: 0 }
618
+ };
619
+ }
620
+ return {
621
+ text: "",
622
+ width: 0,
623
+ start: { segmentIndex: startSegment, graphemeIndex: startGrapheme },
624
+ end: { segmentIndex: i + 1, graphemeIndex: 0 }
625
+ };
626
+ }
627
+ const w = seg.width;
628
+ if (!hasContent) {
629
+ if (w > slotWidth && seg.graphemeWidths) {
630
+ const overflow = consumeBreakable(i, 0, seg.graphemeWidths);
631
+ if (overflow) {
632
+ const text2 = buildLineText(
633
+ segments,
634
+ startSegment,
635
+ startGrapheme,
636
+ lineEndSegment,
637
+ lineEndGrapheme,
638
+ false,
639
+ segmentAdapter
676
640
  );
641
+ return {
642
+ text: text2,
643
+ width: lineW,
644
+ start: { segmentIndex: startSegment, graphemeIndex: startGrapheme },
645
+ end: { segmentIndex: lineEndSegment, graphemeIndex: lineEndGrapheme }
646
+ };
677
647
  }
648
+ i = lineEndSegment - 1;
649
+ continue;
678
650
  }
679
- ctx.down([["DATA", facts]]);
680
- },
681
- { name }
682
- );
683
- }
684
- function mergeMeasurements(opts) {
685
- const sources = [...opts.sources];
686
- return opts.graph.node(
687
- sources,
688
- (ctx) => {
689
- const facts = [];
690
- for (let i = 0; i < sources.length; i += 1) {
691
- facts.push(...depLatest(ctx, i));
651
+ lineW = w;
652
+ lineEndSegment = i + 1;
653
+ lineEndGrapheme = 0;
654
+ hasContent = true;
655
+ if (canBreakAfter(seg.kind)) {
656
+ recordPending(i + 1, 0, seg.kind === "space" ? lineW - w : lineW, seg.kind);
657
+ }
658
+ continue;
659
+ }
660
+ const projectedWidth = lineW + w;
661
+ if (projectedWidth > slotWidth + 1e-3) {
662
+ if (canBreakAfter(seg.kind)) {
663
+ lineEndSegment = i + 1;
664
+ lineEndGrapheme = 0;
665
+ const endsAtSoftHyphen2 = seg.kind === "soft-hyphen";
666
+ const text3 = buildLineText(
667
+ segments,
668
+ startSegment,
669
+ startGrapheme,
670
+ lineEndSegment,
671
+ lineEndGrapheme,
672
+ endsAtSoftHyphen2,
673
+ segmentAdapter
674
+ );
675
+ return {
676
+ text: text3,
677
+ width: seg.kind === "space" ? lineW : lineW + (endsAtSoftHyphen2 ? hyphenWidth : 0),
678
+ start: { segmentIndex: startSegment, graphemeIndex: startGrapheme },
679
+ end: { segmentIndex: lineEndSegment, graphemeIndex: lineEndGrapheme }
680
+ };
681
+ }
682
+ if (pendingBreakSegment >= 0) {
683
+ const text3 = buildLineText(
684
+ segments,
685
+ startSegment,
686
+ startGrapheme,
687
+ pendingBreakSegment,
688
+ pendingBreakGrapheme,
689
+ pendingBreakSoftHyphen,
690
+ segmentAdapter
691
+ );
692
+ return {
693
+ text: text3,
694
+ width: pendingBreakWidth + (pendingBreakSoftHyphen ? hyphenWidth : 0),
695
+ start: { segmentIndex: startSegment, graphemeIndex: startGrapheme },
696
+ end: { segmentIndex: pendingBreakSegment, graphemeIndex: pendingBreakGrapheme }
697
+ };
698
+ }
699
+ if (w > slotWidth && seg.graphemeWidths) {
700
+ const text3 = buildLineText(
701
+ segments,
702
+ startSegment,
703
+ startGrapheme,
704
+ lineEndSegment,
705
+ lineEndGrapheme,
706
+ false,
707
+ segmentAdapter
708
+ );
709
+ return {
710
+ text: text3,
711
+ width: lineW,
712
+ start: { segmentIndex: startSegment, graphemeIndex: startGrapheme },
713
+ end: { segmentIndex: lineEndSegment, graphemeIndex: lineEndGrapheme }
714
+ };
692
715
  }
693
- ctx.down([["DATA", facts]]);
694
- },
695
- { name: opts.name ?? "measurements" }
696
- );
697
- }
698
- function blockAdaptersProvider(opts) {
699
- const deps = [];
700
- const positions = {};
701
- if (opts.text) {
702
- positions.text = deps.length;
703
- deps.push(opts.text);
704
- }
705
- if (opts.svg) {
706
- positions.svg = deps.length;
707
- deps.push(opts.svg);
708
- }
709
- if (opts.image) {
710
- positions.image = deps.length;
711
- deps.push(opts.image);
712
- }
713
- return opts.graph.node(
714
- deps,
715
- (ctx) => {
716
- const adapters = {
717
- text: positions.text === void 0 ? void 0 : depLatest(ctx, positions.text),
718
- svg: positions.svg === void 0 ? void 0 : depLatest(ctx, positions.svg),
719
- image: positions.image === void 0 ? void 0 : depLatest(ctx, positions.image)
716
+ const text2 = buildLineText(
717
+ segments,
718
+ startSegment,
719
+ startGrapheme,
720
+ lineEndSegment,
721
+ lineEndGrapheme,
722
+ false,
723
+ segmentAdapter
724
+ );
725
+ return {
726
+ text: text2,
727
+ width: lineW,
728
+ start: { segmentIndex: startSegment, graphemeIndex: startGrapheme },
729
+ end: { segmentIndex: lineEndSegment, graphemeIndex: lineEndGrapheme }
720
730
  };
721
- ctx.down([["DATA", adapters]]);
722
- },
723
- { name: opts.name ?? "block-adapters" }
731
+ }
732
+ lineW = projectedWidth;
733
+ lineEndSegment = i + 1;
734
+ lineEndGrapheme = 0;
735
+ if (canBreakAfter(seg.kind)) {
736
+ recordPending(i + 1, 0, seg.kind === "space" ? lineW - w : lineW, seg.kind);
737
+ }
738
+ }
739
+ if (!hasContent) return null;
740
+ const endsAtSoftHyphen = lineEndSegment > 0 && segments[lineEndSegment - 1]?.kind === "soft-hyphen";
741
+ const text = buildLineText(
742
+ segments,
743
+ startSegment,
744
+ startGrapheme,
745
+ lineEndSegment,
746
+ lineEndGrapheme,
747
+ endsAtSoftHyphen,
748
+ segmentAdapter
724
749
  );
750
+ return {
751
+ text,
752
+ width: lineW + (endsAtSoftHyphen ? hyphenWidth : 0),
753
+ start: { segmentIndex: startSegment, graphemeIndex: startGrapheme },
754
+ end: { segmentIndex: lineEndSegment, graphemeIndex: lineEndGrapheme }
755
+ };
725
756
  }
726
- function blockMeasurementProvider(opts) {
727
- const targetId = opts.targetId ?? "blocks";
728
- const name = opts.name ?? `${targetId}-measurements`;
729
- const source = opts.source ?? name;
730
- const cache = /* @__PURE__ */ new Map();
731
- let activeTextAdapter;
732
- const deps = [opts.blocks, opts.maxWidth, opts.adapters];
733
- if (opts.font) deps.push(opts.font);
734
- if (opts.lineHeight) deps.push(opts.lineHeight);
735
- if (opts.segmentAdapter) deps.push(opts.segmentAdapter);
736
- return opts.graph.node(
737
- deps,
738
- (ctx) => {
739
- const flush = () => {
740
- cache.clear();
741
- const adapters = depLatest(ctx, 2);
742
- adapters.text?.clearCache?.();
743
- };
744
- ctx.onDeactivation(flush);
745
- ctx.onInvalidate(flush);
746
- try {
747
- const blocks = depLatest(ctx, 0);
748
- const maxWidth = nonNegativeFinite(depLatest(ctx, 1), 0);
749
- const adapters = depLatest(ctx, 2);
750
- if (adapters.text !== activeTextAdapter) {
751
- cache.clear();
752
- activeTextAdapter = adapters.text;
753
- }
754
- let depIndex = 3;
755
- const font = opts.font ? depLatest(ctx, depIndex++) : void 0;
756
- const lineHeight = opts.lineHeight ? nonNegativeFinite(depLatest(ctx, depIndex++), 0) : void 0;
757
- const segmentAdapter = opts.segmentAdapter ? depLatest(ctx, depIndex) : getDefaultSegmentAdapter();
758
- const measured = [];
759
- const issues = [];
760
- for (let i = 0; i < blocks.length; i += 1) {
761
- const block = blocks[i];
762
- const subjectId = block?.id ?? `${targetId}:${i}`;
763
- try {
764
- if (block === void 0) {
765
- throw new Error(`Missing content block at index ${i}`);
766
- }
767
- const blockFont = block.kind === "text" ? block.font ?? font ?? "16px sans-serif" : void 0;
768
- const hyphenWidth = block.kind === "text" && adapters.text ? tryMeasureHyphenWidth(adapters.text, blockFont ?? "16px sans-serif") : void 0;
769
- measured.push(
770
- measureBlock(block, {
771
- adapters,
772
- font,
773
- hyphenWidth,
774
- lineHeight,
775
- maxWidth,
776
- cache,
777
- segmentAdapter
778
- })
779
- );
780
- if (block.kind === "text" && adapters.text) {
781
- if (hyphenWidth === void 0) {
782
- issues.push(
783
- measurementIssue(
784
- "measurement.hyphen.failed",
785
- `Hyphen measurement failed for '${subjectId}'`,
786
- subjectId,
787
- BLOCKS_MEASUREMENT_KIND,
788
- {
789
- source,
790
- details: { targetId, index: i },
791
- severity: "warning"
792
- }
793
- )
794
- );
795
- }
796
- }
797
- } catch (error) {
798
- issues.push(
799
- measurementIssue(
800
- "measurement.block.failed",
801
- `Block measurement failed for '${subjectId}'`,
802
- subjectId,
803
- BLOCKS_MEASUREMENT_KIND,
804
- {
805
- source,
806
- details: { error, targetId, index: i, blockKind: block?.kind },
807
- severity: "error"
808
- }
809
- )
810
- );
811
- }
812
- }
813
- ctx.down([
814
- [
815
- "DATA",
816
- [
817
- measurementOk(
818
- targetId,
819
- BLOCKS_MEASUREMENT_KIND,
820
- { blocks: measured },
821
- { source }
822
- ),
823
- ...issues
824
- ]
825
- ]
826
- ]);
827
- } catch (error) {
828
- ctx.down([
829
- [
830
- "DATA",
831
- [
832
- measurementIssue(
833
- "measurement.failed",
834
- `Block measurement failed for '${targetId}'`,
835
- targetId,
836
- BLOCKS_MEASUREMENT_KIND,
837
- { source, details: error, severity: "error" }
838
- )
839
- ]
840
- ]
841
- ]);
757
+ function carveTextLineSlots(base, blocked, minSlotWidth = 0) {
758
+ let slots = [base];
759
+ for (const block of blocked) {
760
+ const next = [];
761
+ for (const slot of slots) {
762
+ if (block.right <= slot.left || block.left >= slot.right) {
763
+ next.push(slot);
764
+ continue;
842
765
  }
843
- },
844
- { name }
845
- );
846
- }
847
- function analyzeAndMeasure(text, font, adapter, cache, stats, segmentAdapter) {
848
- const normalized = normalizeWhitespace(text);
849
- if (normalized.length === 0) {
850
- return [];
851
- }
852
- const segAdapter = segmentAdapter ?? getDefaultSegmentAdapter();
853
- const pieces = segmentText(normalized, segAdapter);
854
- const rawTexts = [];
855
- const rawKinds = [];
856
- const rawWordLike = [];
857
- for (const piece of pieces) {
858
- for (let i = 0; i < piece.texts.length; i += 1) {
859
- rawTexts.push(piece.texts[i]);
860
- rawKinds.push(piece.kinds[i]);
861
- rawWordLike.push(piece.isWordLike[i]);
766
+ if (block.left > slot.left) next.push({ left: slot.left, right: block.left });
767
+ if (block.right < slot.right) next.push({ left: block.right, right: slot.right });
862
768
  }
769
+ slots = next;
863
770
  }
864
- const mergedTexts = [];
865
- const mergedKinds = [];
866
- const mergedWordLike = [];
867
- for (let i = 0; i < rawTexts.length; i += 1) {
868
- const t = rawTexts[i];
869
- const k = rawKinds[i];
870
- const wl = rawWordLike[i];
871
- if (k === "text" && !wl && mergedTexts.length > 0 && mergedKinds[mergedTexts.length - 1] === "text") {
872
- const isSticky = t.length === 1 && (leftStickyPunctuation.has(t) || kinsokuStart.has(t));
873
- if (isSticky) {
874
- mergedTexts[mergedTexts.length - 1] += t;
771
+ if (minSlotWidth > 0) return slots.filter((slot) => slot.right - slot.left >= minSlotWidth);
772
+ return slots;
773
+ }
774
+ function computeCharPositions(lineBreaks, segments, lineHeight, segmentAdapter) {
775
+ const positions = [];
776
+ const segAdapter = segmentAdapter ?? getDefaultSegmentAdapter();
777
+ for (let lineIdx = 0; lineIdx < lineBreaks.lines.length; lineIdx += 1) {
778
+ const line = lineBreaks.lines[lineIdx];
779
+ const y = lineIdx * lineHeight;
780
+ let x = 0;
781
+ for (let si = line.startSegment; si < segments.length; si += 1) {
782
+ const seg = segments[si];
783
+ if (seg.kind === "soft-hyphen" || seg.kind === "hard-break") {
784
+ if (si >= line.endSegment && line.endGrapheme === 0) break;
875
785
  continue;
876
786
  }
787
+ const graphemes = [...segAdapter.segmentGraphemes(seg.text)].map((g) => g.segment);
788
+ if (graphemes.length === 0) continue;
789
+ const startGrapheme = si === line.startSegment ? line.startGrapheme : 0;
790
+ let endGrapheme;
791
+ if (si < line.endSegment) {
792
+ endGrapheme = graphemes.length;
793
+ } else if (si === line.endSegment && line.endGrapheme > 0) {
794
+ endGrapheme = line.endGrapheme;
795
+ } else {
796
+ break;
797
+ }
798
+ for (let g = startGrapheme; g < endGrapheme; g += 1) {
799
+ const width = seg.graphemeWidths ? seg.graphemeWidths[g] : seg.width / graphemes.length;
800
+ positions.push({ x, y, width, height: lineHeight, line: lineIdx });
801
+ x += width;
802
+ }
877
803
  }
878
- if (t === "-" && mergedTexts.length > 0 && mergedKinds[mergedKinds.length - 1] === "text" && mergedWordLike[mergedWordLike.length - 1]) {
879
- mergedTexts[mergedTexts.length - 1] += t;
880
- continue;
881
- }
882
- mergedTexts.push(t);
883
- mergedKinds.push(k);
884
- mergedWordLike.push(wl);
885
804
  }
886
- const fontCache = cache.get(font) ?? /* @__PURE__ */ new Map();
887
- if (!cache.has(font)) cache.set(font, fontCache);
888
- function measureCached(segment) {
889
- const cached = fontCache.get(segment);
890
- if (cached === void 0) {
891
- if (stats) stats.misses += 1;
892
- const measured = adapter.measureSegment(segment, font).width;
893
- const width = Number.isFinite(measured) && measured >= 0 ? measured : 0;
894
- fontCache.set(segment, width);
895
- return width;
805
+ return positions;
806
+ }
807
+
808
+ // src/solutions/reactive-layout/types.ts
809
+ var TEXT_SEGMENTS_MEASUREMENT_KIND = "text-segments";
810
+ var BLOCKS_MEASUREMENT_KIND = "blocks";
811
+ var READINESS_MEASUREMENT_KIND = "readiness";
812
+ var IMAGE_SIZE_MEASUREMENT_KIND = "image-size";
813
+ var SVG_BOUNDS_MEASUREMENT_KIND = "svg-bounds";
814
+
815
+ // src/solutions/reactive-layout/measurements.ts
816
+ function measurementIssue(code, message, targetId, measurementKind, opts = {}) {
817
+ return {
818
+ kind: "issue",
819
+ code,
820
+ message,
821
+ severity: opts.severity ?? "warning",
822
+ source: opts.source,
823
+ subjectId: targetId,
824
+ measurementKind,
825
+ details: opts.details,
826
+ metadata: opts.metadata
827
+ };
828
+ }
829
+ function measurementOk(targetId, measurementKind, value, opts = {}) {
830
+ return {
831
+ kind: "ok",
832
+ targetId,
833
+ measurementKind,
834
+ value,
835
+ source: opts.source,
836
+ metadata: opts.metadata
837
+ };
838
+ }
839
+ function latestMeasurementValue(measurements, targetId, measurementKind) {
840
+ let value;
841
+ for (const fact of measurements) {
842
+ if (fact.kind === "ok" && fact.targetId === targetId && fact.measurementKind === measurementKind) {
843
+ value = fact.value;
896
844
  }
897
- if (stats) stats.hits += 1;
898
- return cached;
899
845
  }
900
- const out = [];
901
- for (let i = 0; i < mergedTexts.length; i += 1) {
902
- const t = mergedTexts[i];
903
- const kind = mergedKinds[i];
904
- if (kind !== "text") {
905
- out.push({
906
- text: t,
907
- width: kind === "space" ? measureCached(" ") * t.length : 0,
908
- kind,
909
- graphemeWidths: null
910
- });
911
- continue;
846
+ return value;
847
+ }
848
+ function tryMeasureHyphenWidth(adapter, font) {
849
+ try {
850
+ return nonNegativeFinite(adapter.measureSegment("-", font).width, 0);
851
+ } catch {
852
+ return void 0;
853
+ }
854
+ }
855
+ function validMeasurementSize(size, label) {
856
+ if (!Number.isFinite(size.width) || !Number.isFinite(size.height) || size.width < 0 || size.height < 0) {
857
+ throw new Error(`Invalid ${label} measurement size`);
858
+ }
859
+ return size;
860
+ }
861
+ function textMeasurementFacts(text, font, adapter, cache, segmentAdapter, targetId, source) {
862
+ try {
863
+ const segments = analyzeAndMeasure(text, font, adapter, cache, void 0, segmentAdapter);
864
+ const hyphenWidth = tryMeasureHyphenWidth(adapter, font);
865
+ const facts = [
866
+ measurementOk(
867
+ targetId,
868
+ TEXT_SEGMENTS_MEASUREMENT_KIND,
869
+ hyphenWidth === void 0 ? { segments } : { segments, hyphenWidth },
870
+ { source }
871
+ )
872
+ ];
873
+ if (hyphenWidth === void 0) {
874
+ facts.push(
875
+ measurementIssue(
876
+ "measurement.hyphen.failed",
877
+ `Hyphen measurement failed for '${targetId}'`,
878
+ targetId,
879
+ TEXT_SEGMENTS_MEASUREMENT_KIND,
880
+ { source, severity: "warning" }
881
+ )
882
+ );
912
883
  }
913
- if (isCJK(t)) {
914
- let unitText = "";
915
- for (const graphemeSegment of segAdapter.segmentGraphemes(t)) {
916
- const grapheme = graphemeSegment.segment;
917
- if (unitText.length > 0 && kinsokuStart.has(grapheme)) {
918
- unitText += grapheme;
919
- continue;
920
- }
921
- if (unitText.length > 0) {
922
- out.push({
923
- text: unitText,
924
- width: measureCached(unitText),
925
- kind: "text",
926
- graphemeWidths: null
927
- });
884
+ return facts;
885
+ } catch (error) {
886
+ return [
887
+ measurementIssue(
888
+ "measurement.failed",
889
+ `Text measurement failed for '${targetId}'`,
890
+ targetId,
891
+ TEXT_SEGMENTS_MEASUREMENT_KIND,
892
+ { source, details: error, severity: "error" }
893
+ )
894
+ ];
895
+ }
896
+ }
897
+ function inputNode(g, input, fallback, name) {
898
+ if (input instanceof Node) {
899
+ return {
900
+ node: input,
901
+ set(value) {
902
+ const maybeState = input;
903
+ if (typeof maybeState.set !== "function") {
904
+ throw new TypeError(`reactive-layout input '${name}' is not a writable state node`);
928
905
  }
929
- unitText = grapheme;
930
- }
931
- if (unitText.length > 0) {
932
- out.push({
933
- text: unitText,
934
- width: measureCached(unitText),
935
- kind: "text",
936
- graphemeWidths: null
937
- });
938
- }
939
- continue;
940
- }
941
- const textWidth = measureCached(t);
942
- let graphemeWidths = null;
943
- if (mergedWordLike[i] && t.length > 1) {
944
- const widths = [];
945
- for (const grapheme of segAdapter.segmentGraphemes(t)) {
946
- widths.push(measureCached(grapheme.segment));
906
+ maybeState.set(value);
947
907
  }
948
- if (widths.length > 1) graphemeWidths = widths;
949
- }
950
- out.push({
951
- text: t,
952
- width: textWidth,
953
- kind: "text",
954
- graphemeWidths
955
- });
908
+ };
956
909
  }
957
- return out;
910
+ const state = g.state(input ?? fallback, { name });
911
+ return { node: state, set: (value) => state.set(value) };
958
912
  }
959
- function computeLineBreaks(segments, maxWidth, opts = {}) {
960
- if (segments.length === 0) return { lines: [], lineCount: 0 };
961
- const segAdapter = opts.segmentAdapter ?? getDefaultSegmentAdapter();
962
- const lines = [];
963
- let cursor = { segmentIndex: 0, graphemeIndex: 0 };
964
- while (cursor.segmentIndex < segments.length) {
965
- const next = layoutNextLine(segments, cursor, maxWidth, {
966
- hyphenWidth: opts.hyphenWidth,
967
- segmentAdapter: segAdapter
968
- });
969
- if (next === null) break;
970
- lines.push({
971
- text: next.text,
972
- width: next.width,
973
- startSegment: next.start.segmentIndex,
974
- startGrapheme: next.start.graphemeIndex,
975
- endSegment: next.end.segmentIndex,
976
- endGrapheme: next.end.graphemeIndex
977
- });
978
- if (next.end.segmentIndex === cursor.segmentIndex && next.end.graphemeIndex === cursor.graphemeIndex) {
979
- break;
980
- }
981
- cursor = next.end;
982
- }
983
- return { lines, lineCount: lines.length };
913
+ function scopedName(scope, local) {
914
+ return scope === local ? local : `${scope}:${local}`;
984
915
  }
985
- function canBreakAfter(kind) {
986
- return kind === "space" || kind === "zero-width-break" || kind === "soft-hyphen";
916
+ function textMeasurementProvider(opts) {
917
+ const targetId = opts.targetId ?? "text";
918
+ const name = opts.name ?? `${targetId}-measurements`;
919
+ const source = opts.source ?? name;
920
+ const cache = /* @__PURE__ */ new Map();
921
+ let activeAdapter = null;
922
+ return opts.graph.node(
923
+ opts.segmentAdapter ? [opts.text, opts.font, opts.adapter, opts.segmentAdapter] : [opts.text, opts.font, opts.adapter],
924
+ (ctx) => {
925
+ const flush = () => {
926
+ cache.clear();
927
+ depLatest(ctx, 2).clearCache?.();
928
+ };
929
+ ctx.onDeactivation(flush);
930
+ ctx.onInvalidate(flush);
931
+ const text = depLatest(ctx, 0);
932
+ const font = depLatest(ctx, 1);
933
+ const adapter = depLatest(ctx, 2);
934
+ if (adapter !== activeAdapter) {
935
+ cache.clear();
936
+ activeAdapter = adapter;
937
+ }
938
+ const segmentAdapter = opts.segmentAdapter === void 0 ? getDefaultSegmentAdapter() : depLatest(ctx, 3);
939
+ ctx.down([
940
+ [
941
+ "DATA",
942
+ textMeasurementFacts(text, font, adapter, cache, segmentAdapter, targetId, source)
943
+ ]
944
+ ]);
945
+ },
946
+ { name }
947
+ );
948
+ }
949
+ function injectedTextMeasurements(opts) {
950
+ const targetId = opts.targetId ?? "text";
951
+ const adapter = opts.graph.state(
952
+ new InjectedMeasureAdapter(opts.measure, { cache: opts.cache }),
953
+ {
954
+ name: opts.name ? scopedName(opts.name, "measure-capability") : `${targetId}-measure-capability`
955
+ }
956
+ );
957
+ return textMeasurementProvider({
958
+ ...opts,
959
+ adapter,
960
+ source: opts.source ?? "injectedTextMeasurements"
961
+ });
987
962
  }
988
- function sliceSegmentText(seg, startGrapheme, endGrapheme, segmentAdapter) {
989
- if (startGrapheme === 0 && endGrapheme < 0) return seg.text;
990
- const graphemes = [...segmentAdapter.segmentGraphemes(seg.text)].map((g) => g.segment);
991
- const stop = endGrapheme < 0 ? graphemes.length : endGrapheme;
992
- return graphemes.slice(startGrapheme, stop).join("");
963
+ function precomputedTextMeasurements(opts) {
964
+ const targetId = opts.targetId ?? "text";
965
+ const adapter = opts.graph.state(new PrecomputedMeasureAdapter(opts), {
966
+ name: opts.name ? scopedName(opts.name, "measure-capability") : `${targetId}-measure-capability`
967
+ });
968
+ return textMeasurementProvider({
969
+ ...opts,
970
+ adapter,
971
+ source: opts.source ?? "precomputedTextMeasurements"
972
+ });
993
973
  }
994
- function buildLineText(segments, startSegment, startGrapheme, endSegment, endGrapheme, appendHyphen, segmentAdapter) {
995
- let text = "";
996
- for (let i = startSegment; i < endSegment; i += 1) {
997
- const seg = segments[i];
998
- if (seg.kind === "soft-hyphen" || seg.kind === "hard-break") continue;
999
- if (i === startSegment && startGrapheme > 0) {
1000
- text += sliceSegmentText(seg, startGrapheme, -1, segmentAdapter);
1001
- } else {
1002
- text += seg.text;
1003
- }
1004
- }
1005
- if (endGrapheme > 0 && endSegment < segments.length) {
1006
- const seg = segments[endSegment];
1007
- const from = startSegment === endSegment ? startGrapheme : 0;
1008
- text += sliceSegmentText(seg, from, endGrapheme, segmentAdapter);
1009
- }
1010
- if (appendHyphen) text += "-";
1011
- return text;
974
+ function cellTextMeasurements(opts) {
975
+ const targetId = opts.targetId ?? "text";
976
+ const adapter = opts.graph.state(new CellMeasureAdapter(opts), {
977
+ name: opts.name ? scopedName(opts.name, "measure-capability") : `${targetId}-measure-capability`
978
+ });
979
+ return textMeasurementProvider({
980
+ ...opts,
981
+ adapter,
982
+ source: opts.source ?? "cellTextMeasurements"
983
+ });
1012
984
  }
1013
- function resolveHyphenWidth(ctx) {
1014
- if (ctx?.hyphenWidth !== void 0) return nonNegativeFinite(ctx.hyphenWidth, 0);
1015
- if (ctx?.adapter === void 0 || ctx.font === void 0) return 0;
1016
- const cache = ctx.cache;
1017
- if (cache) {
1018
- let fontCache = cache.get(ctx.font);
1019
- if (fontCache === void 0) {
1020
- fontCache = /* @__PURE__ */ new Map();
1021
- cache.set(ctx.font, fontCache);
1022
- }
1023
- let width = fontCache.get("-");
1024
- if (width === void 0) {
1025
- width = ctx.adapter.measureSegment("-", ctx.font).width;
1026
- fontCache.set("-", width);
985
+ function capabilityTextMeasurements(opts) {
986
+ const targetId = opts.targetId ?? "text";
987
+ const adapter = opts.graph.node(
988
+ [opts.capability],
989
+ (ctx) => {
990
+ ctx.down([
991
+ ["DATA", new CapabilityMeasureAdapter(depLatest(ctx, 0))]
992
+ ]);
993
+ },
994
+ {
995
+ name: opts.name ? scopedName(opts.name, "measure-capability") : `${targetId}-measure-capability`
1027
996
  }
1028
- return width;
1029
- }
1030
- return ctx.adapter.measureSegment("-", ctx.font).width;
997
+ );
998
+ return textMeasurementProvider({
999
+ ...opts,
1000
+ adapter,
1001
+ source: opts.source ?? "capabilityTextMeasurements"
1002
+ });
1031
1003
  }
1032
- function layoutNextLine(segments, cursor, slotWidth, ctx) {
1033
- let i = cursor.segmentIndex;
1034
- const initialGrapheme = cursor.graphemeIndex;
1035
- const segmentAdapter = ctx?.segmentAdapter ?? getDefaultSegmentAdapter();
1036
- if (i >= segments.length) return null;
1037
- if (initialGrapheme === 0) {
1038
- while (i < segments.length) {
1039
- const seg = segments[i];
1040
- if (seg.kind === "hard-break") {
1041
- return {
1042
- text: "",
1043
- width: 0,
1044
- start: { segmentIndex: cursor.segmentIndex, graphemeIndex: 0 },
1045
- end: { segmentIndex: i + 1, graphemeIndex: 0 }
1046
- };
1047
- }
1048
- if (seg.kind === "space" || seg.kind === "zero-width-break" || seg.kind === "soft-hyphen") {
1049
- i += 1;
1050
- continue;
1051
- }
1052
- break;
1053
- }
1054
- if (i >= segments.length) return null;
1055
- }
1056
- const hyphenWidth = resolveHyphenWidth(ctx);
1057
- const startSegment = i;
1058
- const startGrapheme = i === cursor.segmentIndex ? initialGrapheme : 0;
1059
- let lineW = 0;
1060
- let lineEndSegment = startSegment;
1061
- let lineEndGrapheme = 0;
1062
- let hasContent = false;
1063
- let pendingBreakSegment = -1;
1064
- let pendingBreakGrapheme = 0;
1065
- let pendingBreakWidth = 0;
1066
- let pendingBreakSoftHyphen = false;
1067
- const recordPending = (sIdx, gIdx, width, kind) => {
1068
- pendingBreakSegment = sIdx;
1069
- pendingBreakGrapheme = gIdx;
1070
- pendingBreakWidth = width;
1071
- pendingBreakSoftHyphen = kind === "soft-hyphen";
1072
- };
1073
- const consumeBreakable = (segIdx, startG, widths) => {
1074
- for (let g = startG; g < widths.length; g += 1) {
1075
- const gw = widths[g];
1076
- if (!hasContent) {
1077
- lineW = gw;
1078
- lineEndSegment = segIdx;
1079
- lineEndGrapheme = g + 1;
1080
- hasContent = true;
1081
- continue;
1004
+ function readinessTextMeasurements(opts) {
1005
+ const targetId = opts.targetId ?? "text";
1006
+ const name = opts.name ?? `${targetId}-measurements`;
1007
+ const source = opts.source ?? name;
1008
+ const cache = /* @__PURE__ */ new Map();
1009
+ let activeAdapter = null;
1010
+ let activeReadiness = null;
1011
+ const deps = opts.segmentAdapter ? [opts.text, opts.font, opts.adapter, opts.readiness, opts.segmentAdapter] : [opts.text, opts.font, opts.adapter, opts.readiness];
1012
+ return opts.graph.node(
1013
+ deps,
1014
+ (ctx) => {
1015
+ const flush = () => {
1016
+ cache.clear();
1017
+ depLatest(ctx, 2).clearCache?.();
1018
+ };
1019
+ ctx.onDeactivation(flush);
1020
+ ctx.onInvalidate(flush);
1021
+ const text = depLatest(ctx, 0);
1022
+ const font = depLatest(ctx, 1);
1023
+ const adapter = depLatest(ctx, 2);
1024
+ if (adapter !== activeAdapter) {
1025
+ cache.clear();
1026
+ activeAdapter = adapter;
1082
1027
  }
1083
- if (lineW + gw > slotWidth + 1e-3) {
1084
- return true;
1028
+ const readiness = depLatest(ctx, 3);
1029
+ if (readiness !== activeReadiness) {
1030
+ cache.clear();
1031
+ activeReadiness = readiness;
1085
1032
  }
1086
- lineW += gw;
1087
- lineEndSegment = segIdx;
1088
- lineEndGrapheme = g + 1;
1089
- }
1090
- if (lineEndSegment === segIdx && lineEndGrapheme === widths.length) {
1091
- lineEndSegment = segIdx + 1;
1092
- lineEndGrapheme = 0;
1093
- }
1094
- return false;
1095
- };
1096
- if (startGrapheme > 0 && startSegment < segments.length) {
1097
- const seg = segments[startSegment];
1098
- if (seg.graphemeWidths) {
1099
- const overflow = consumeBreakable(startSegment, startGrapheme, seg.graphemeWidths);
1100
- if (overflow) {
1101
- const text2 = buildLineText(
1102
- segments,
1103
- startSegment,
1104
- startGrapheme,
1105
- lineEndSegment,
1106
- lineEndGrapheme,
1107
- false,
1108
- segmentAdapter
1109
- );
1110
- return {
1111
- text: text2,
1112
- width: lineW,
1113
- start: { segmentIndex: startSegment, graphemeIndex: startGrapheme },
1114
- end: { segmentIndex: lineEndSegment, graphemeIndex: lineEndGrapheme }
1115
- };
1033
+ if (!readiness.ready) {
1034
+ ctx.down([
1035
+ [
1036
+ "DATA",
1037
+ [
1038
+ measurementIssue(
1039
+ readiness.code ?? "measurement.not-ready",
1040
+ readiness.message ?? `Measurement readiness blocked '${targetId}'`,
1041
+ targetId,
1042
+ TEXT_SEGMENTS_MEASUREMENT_KIND,
1043
+ {
1044
+ source: readiness.source ?? source,
1045
+ details: readiness.details,
1046
+ metadata: readiness.metadata,
1047
+ severity: "warning"
1048
+ }
1049
+ )
1050
+ ]
1051
+ ]
1052
+ ]);
1053
+ return;
1116
1054
  }
1117
- i = lineEndSegment;
1118
- }
1119
- }
1120
- for (; i < segments.length; i += 1) {
1121
- const seg = segments[i];
1122
- if (seg.kind === "hard-break") {
1123
- if (hasContent) {
1124
- const endsAtSoftHyphen2 = lineEndSegment > 0 && segments[lineEndSegment - 1]?.kind === "soft-hyphen";
1125
- const text2 = buildLineText(
1126
- segments,
1127
- startSegment,
1128
- startGrapheme,
1129
- lineEndSegment,
1130
- lineEndGrapheme,
1131
- endsAtSoftHyphen2,
1132
- segmentAdapter
1133
- );
1134
- return {
1135
- text: text2,
1136
- width: lineW + (endsAtSoftHyphen2 ? hyphenWidth : 0),
1137
- start: { segmentIndex: startSegment, graphemeIndex: startGrapheme },
1138
- end: { segmentIndex: i + 1, graphemeIndex: 0 }
1139
- };
1055
+ const segmentAdapter = opts.segmentAdapter === void 0 ? getDefaultSegmentAdapter() : depLatest(ctx, 4);
1056
+ ctx.down([
1057
+ [
1058
+ "DATA",
1059
+ textMeasurementFacts(text, font, adapter, cache, segmentAdapter, targetId, source)
1060
+ ]
1061
+ ]);
1062
+ },
1063
+ { name }
1064
+ );
1065
+ }
1066
+ function readinessMeasurements(opts) {
1067
+ const targetId = opts.targetId ?? "measurement-readiness";
1068
+ const measurementKind = opts.measurementKind ?? READINESS_MEASUREMENT_KIND;
1069
+ const name = opts.name ?? `${targetId}-measurements`;
1070
+ const source = opts.source ?? name;
1071
+ return opts.graph.node(
1072
+ [opts.readiness],
1073
+ (ctx) => {
1074
+ const readiness = depLatest(ctx, 0);
1075
+ if (!readiness.ready) {
1076
+ ctx.down([
1077
+ [
1078
+ "DATA",
1079
+ [
1080
+ measurementIssue(
1081
+ readiness.code ?? "measurement.not-ready",
1082
+ readiness.message ?? `Measurement readiness blocked '${targetId}'`,
1083
+ targetId,
1084
+ measurementKind,
1085
+ {
1086
+ source: readiness.source ?? source,
1087
+ details: readiness.details,
1088
+ metadata: readiness.metadata,
1089
+ severity: "warning"
1090
+ }
1091
+ )
1092
+ ]
1093
+ ]
1094
+ ]);
1095
+ return;
1140
1096
  }
1141
- return {
1142
- text: "",
1143
- width: 0,
1144
- start: { segmentIndex: startSegment, graphemeIndex: startGrapheme },
1145
- end: { segmentIndex: i + 1, graphemeIndex: 0 }
1146
- };
1147
- }
1148
- const w = seg.width;
1149
- if (!hasContent) {
1150
- if (w > slotWidth && seg.graphemeWidths) {
1151
- const overflow = consumeBreakable(i, 0, seg.graphemeWidths);
1152
- if (overflow) {
1153
- const text2 = buildLineText(
1154
- segments,
1155
- startSegment,
1156
- startGrapheme,
1157
- lineEndSegment,
1158
- lineEndGrapheme,
1159
- false,
1160
- segmentAdapter
1097
+ ctx.down([
1098
+ [
1099
+ "DATA",
1100
+ [
1101
+ measurementOk(targetId, measurementKind, readiness, {
1102
+ source: readiness.source ?? source,
1103
+ metadata: readiness.metadata
1104
+ })
1105
+ ]
1106
+ ]
1107
+ ]);
1108
+ },
1109
+ { name }
1110
+ );
1111
+ }
1112
+ function imageSizeMeasurements(opts) {
1113
+ const measurementKind = opts.measurementKind ?? IMAGE_SIZE_MEASUREMENT_KIND;
1114
+ const name = opts.name ?? "image-size-measurements";
1115
+ const source = opts.source ?? name;
1116
+ return opts.graph.node(
1117
+ [opts.images, opts.measurer],
1118
+ (ctx) => {
1119
+ const images = depLatest(ctx, 0);
1120
+ const measurer = depLatest(ctx, 1);
1121
+ const facts = [];
1122
+ for (let i = 0; i < images.length; i += 1) {
1123
+ const image = images[i];
1124
+ const subjectId = image?.id ?? image?.src ?? `image:${i}`;
1125
+ try {
1126
+ if (image === void 0) throw new Error(`Missing image target at index ${i}`);
1127
+ facts.push(
1128
+ measurementOk(
1129
+ subjectId,
1130
+ measurementKind,
1131
+ validMeasurementSize(measurer.measureImage(image.src), "image"),
1132
+ {
1133
+ source,
1134
+ metadata: image.metadata
1135
+ }
1136
+ )
1137
+ );
1138
+ } catch (error) {
1139
+ facts.push(
1140
+ measurementIssue(
1141
+ "measurement.image-size.failed",
1142
+ `Image size measurement failed for '${subjectId}'`,
1143
+ subjectId,
1144
+ measurementKind,
1145
+ {
1146
+ source,
1147
+ details: { error, index: i, src: image?.src },
1148
+ metadata: image?.metadata,
1149
+ severity: "error"
1150
+ }
1151
+ )
1161
1152
  );
1162
- return {
1163
- text: text2,
1164
- width: lineW,
1165
- start: { segmentIndex: startSegment, graphemeIndex: startGrapheme },
1166
- end: { segmentIndex: lineEndSegment, graphemeIndex: lineEndGrapheme }
1167
- };
1168
1153
  }
1169
- i = lineEndSegment - 1;
1170
- continue;
1171
- }
1172
- lineW = w;
1173
- lineEndSegment = i + 1;
1174
- lineEndGrapheme = 0;
1175
- hasContent = true;
1176
- if (canBreakAfter(seg.kind)) {
1177
- recordPending(i + 1, 0, seg.kind === "space" ? lineW - w : lineW, seg.kind);
1178
- }
1179
- continue;
1180
- }
1181
- const projectedWidth = lineW + w;
1182
- if (projectedWidth > slotWidth + 1e-3) {
1183
- if (canBreakAfter(seg.kind)) {
1184
- lineEndSegment = i + 1;
1185
- lineEndGrapheme = 0;
1186
- const endsAtSoftHyphen2 = seg.kind === "soft-hyphen";
1187
- const text3 = buildLineText(
1188
- segments,
1189
- startSegment,
1190
- startGrapheme,
1191
- lineEndSegment,
1192
- lineEndGrapheme,
1193
- endsAtSoftHyphen2,
1194
- segmentAdapter
1195
- );
1196
- return {
1197
- text: text3,
1198
- width: seg.kind === "space" ? lineW : lineW + (endsAtSoftHyphen2 ? hyphenWidth : 0),
1199
- start: { segmentIndex: startSegment, graphemeIndex: startGrapheme },
1200
- end: { segmentIndex: lineEndSegment, graphemeIndex: lineEndGrapheme }
1201
- };
1202
- }
1203
- if (pendingBreakSegment >= 0) {
1204
- const text3 = buildLineText(
1205
- segments,
1206
- startSegment,
1207
- startGrapheme,
1208
- pendingBreakSegment,
1209
- pendingBreakGrapheme,
1210
- pendingBreakSoftHyphen,
1211
- segmentAdapter
1212
- );
1213
- return {
1214
- text: text3,
1215
- width: pendingBreakWidth + (pendingBreakSoftHyphen ? hyphenWidth : 0),
1216
- start: { segmentIndex: startSegment, graphemeIndex: startGrapheme },
1217
- end: { segmentIndex: pendingBreakSegment, graphemeIndex: pendingBreakGrapheme }
1218
- };
1219
- }
1220
- if (w > slotWidth && seg.graphemeWidths) {
1221
- const text3 = buildLineText(
1222
- segments,
1223
- startSegment,
1224
- startGrapheme,
1225
- lineEndSegment,
1226
- lineEndGrapheme,
1227
- false,
1228
- segmentAdapter
1229
- );
1230
- return {
1231
- text: text3,
1232
- width: lineW,
1233
- start: { segmentIndex: startSegment, graphemeIndex: startGrapheme },
1234
- end: { segmentIndex: lineEndSegment, graphemeIndex: lineEndGrapheme }
1235
- };
1236
1154
  }
1237
- const text2 = buildLineText(
1238
- segments,
1239
- startSegment,
1240
- startGrapheme,
1241
- lineEndSegment,
1242
- lineEndGrapheme,
1243
- false,
1244
- segmentAdapter
1245
- );
1246
- return {
1247
- text: text2,
1248
- width: lineW,
1249
- start: { segmentIndex: startSegment, graphemeIndex: startGrapheme },
1250
- end: { segmentIndex: lineEndSegment, graphemeIndex: lineEndGrapheme }
1251
- };
1252
- }
1253
- lineW = projectedWidth;
1254
- lineEndSegment = i + 1;
1255
- lineEndGrapheme = 0;
1256
- if (canBreakAfter(seg.kind)) {
1257
- recordPending(i + 1, 0, seg.kind === "space" ? lineW - w : lineW, seg.kind);
1258
- }
1259
- }
1260
- if (!hasContent) return null;
1261
- const endsAtSoftHyphen = lineEndSegment > 0 && segments[lineEndSegment - 1]?.kind === "soft-hyphen";
1262
- const text = buildLineText(
1263
- segments,
1264
- startSegment,
1265
- startGrapheme,
1266
- lineEndSegment,
1267
- lineEndGrapheme,
1268
- endsAtSoftHyphen,
1269
- segmentAdapter
1155
+ ctx.down([["DATA", facts]]);
1156
+ },
1157
+ { name }
1270
1158
  );
1271
- return {
1272
- text,
1273
- width: lineW + (endsAtSoftHyphen ? hyphenWidth : 0),
1274
- start: { segmentIndex: startSegment, graphemeIndex: startGrapheme },
1275
- end: { segmentIndex: lineEndSegment, graphemeIndex: lineEndGrapheme }
1276
- };
1277
1159
  }
1278
- function carveTextLineSlots(base, blocked, minSlotWidth = 0) {
1279
- let slots = [base];
1280
- for (const block of blocked) {
1281
- const next = [];
1282
- for (const slot of slots) {
1283
- if (block.right <= slot.left || block.left >= slot.right) {
1284
- next.push(slot);
1285
- continue;
1160
+ function svgBoundsMeasurements(opts) {
1161
+ const measurementKind = opts.measurementKind ?? SVG_BOUNDS_MEASUREMENT_KIND;
1162
+ const name = opts.name ?? "svg-bounds-measurements";
1163
+ const source = opts.source ?? name;
1164
+ return opts.graph.node(
1165
+ [opts.svgs, opts.measurer],
1166
+ (ctx) => {
1167
+ const svgs = depLatest(ctx, 0);
1168
+ const measurer = depLatest(ctx, 1);
1169
+ const facts = [];
1170
+ for (let i = 0; i < svgs.length; i += 1) {
1171
+ const svg = svgs[i];
1172
+ const subjectId = svg?.id ?? `svg:${i}`;
1173
+ try {
1174
+ if (svg === void 0) throw new Error(`Missing SVG target at index ${i}`);
1175
+ facts.push(
1176
+ measurementOk(
1177
+ subjectId,
1178
+ measurementKind,
1179
+ validMeasurementSize(measurer.measureSvg(svg.svg), "SVG"),
1180
+ {
1181
+ source,
1182
+ metadata: svg.metadata
1183
+ }
1184
+ )
1185
+ );
1186
+ } catch (error) {
1187
+ facts.push(
1188
+ measurementIssue(
1189
+ "measurement.svg-bounds.failed",
1190
+ `SVG bounds measurement failed for '${subjectId}'`,
1191
+ subjectId,
1192
+ measurementKind,
1193
+ {
1194
+ source,
1195
+ details: { error, index: i },
1196
+ metadata: svg?.metadata,
1197
+ severity: "error"
1198
+ }
1199
+ )
1200
+ );
1201
+ }
1286
1202
  }
1287
- if (block.left > slot.left) next.push({ left: slot.left, right: block.left });
1288
- if (block.right < slot.right) next.push({ left: block.right, right: slot.right });
1289
- }
1290
- slots = next;
1291
- }
1292
- if (minSlotWidth > 0) return slots.filter((slot) => slot.right - slot.left >= minSlotWidth);
1293
- return slots;
1203
+ ctx.down([["DATA", facts]]);
1204
+ },
1205
+ { name }
1206
+ );
1294
1207
  }
1295
- function computeCharPositions(lineBreaks, segments, lineHeight, segmentAdapter) {
1296
- const positions = [];
1297
- const segAdapter = segmentAdapter ?? getDefaultSegmentAdapter();
1298
- for (let lineIdx = 0; lineIdx < lineBreaks.lines.length; lineIdx += 1) {
1299
- const line = lineBreaks.lines[lineIdx];
1300
- const y = lineIdx * lineHeight;
1301
- let x = 0;
1302
- for (let si = line.startSegment; si < segments.length; si += 1) {
1303
- const seg = segments[si];
1304
- if (seg.kind === "soft-hyphen" || seg.kind === "hard-break") {
1305
- if (si >= line.endSegment && line.endGrapheme === 0) break;
1306
- continue;
1307
- }
1308
- const graphemes = [...segAdapter.segmentGraphemes(seg.text)].map((g) => g.segment);
1309
- if (graphemes.length === 0) continue;
1310
- const startGrapheme = si === line.startSegment ? line.startGrapheme : 0;
1311
- let endGrapheme;
1312
- if (si < line.endSegment) {
1313
- endGrapheme = graphemes.length;
1314
- } else if (si === line.endSegment && line.endGrapheme > 0) {
1315
- endGrapheme = line.endGrapheme;
1316
- } else {
1317
- break;
1318
- }
1319
- for (let g = startGrapheme; g < endGrapheme; g += 1) {
1320
- const width = seg.graphemeWidths ? seg.graphemeWidths[g] : seg.width / graphemes.length;
1321
- positions.push({ x, y, width, height: lineHeight, line: lineIdx });
1322
- x += width;
1208
+ function mergeMeasurements(opts) {
1209
+ const sources = [...opts.sources];
1210
+ return opts.graph.node(
1211
+ sources,
1212
+ (ctx) => {
1213
+ const facts = [];
1214
+ for (let i = 0; i < sources.length; i += 1) {
1215
+ facts.push(...depLatest(ctx, i));
1323
1216
  }
1324
- }
1325
- }
1326
- return positions;
1327
- }
1328
- function nonNegativeFinite(value, fallback) {
1329
- return Number.isFinite(value) ? Math.max(0, value) : fallback;
1330
- }
1331
- function finiteNumber(value, fallback) {
1332
- return Number.isFinite(value) ? value : fallback;
1333
- }
1334
- function emitLayoutError(ctx, error, fallback) {
1335
- ctx.down([["ERROR", errorPayload(error, fallback)]]);
1336
- }
1337
- function positiveFinite(value, fallback) {
1338
- return Number.isFinite(value) && value > 0 ? value : fallback;
1339
- }
1340
- function clampDimension(value) {
1341
- return nonNegativeFinite(value ?? 0, 0);
1342
- }
1343
- function fitSize(size, maxWidth) {
1344
- const width = nonNegativeFinite(size.width, 0);
1345
- const height = nonNegativeFinite(size.height, 0);
1346
- if (width === 0 || maxWidth <= 0 || width <= maxWidth) return { width, height };
1347
- const scale = maxWidth / width;
1348
- return { width: maxWidth, height: height * scale };
1217
+ ctx.down([["DATA", facts]]);
1218
+ },
1219
+ { name: opts.name ?? "measurements" }
1220
+ );
1349
1221
  }
1350
- function blockMaxWidth(blockMaxWidth2, maxWidth) {
1351
- const own = blockMaxWidth2 === void 0 ? maxWidth : nonNegativeFinite(blockMaxWidth2, maxWidth);
1352
- if (maxWidth <= 0) return own;
1353
- if (own <= 0) return maxWidth;
1354
- return Math.min(own, maxWidth);
1222
+ function blockAdaptersProvider(opts) {
1223
+ const deps = [];
1224
+ const positions = {};
1225
+ if (opts.text) {
1226
+ positions.text = deps.length;
1227
+ deps.push(opts.text);
1228
+ }
1229
+ if (opts.svg) {
1230
+ positions.svg = deps.length;
1231
+ deps.push(opts.svg);
1232
+ }
1233
+ if (opts.image) {
1234
+ positions.image = deps.length;
1235
+ deps.push(opts.image);
1236
+ }
1237
+ return opts.graph.node(
1238
+ deps,
1239
+ (ctx) => {
1240
+ const adapters = {
1241
+ text: positions.text === void 0 ? void 0 : depLatest(ctx, positions.text),
1242
+ svg: positions.svg === void 0 ? void 0 : depLatest(ctx, positions.svg),
1243
+ image: positions.image === void 0 ? void 0 : depLatest(ctx, positions.image)
1244
+ };
1245
+ ctx.down([["DATA", adapters]]);
1246
+ },
1247
+ { name: opts.name ?? "block-adapters" }
1248
+ );
1355
1249
  }
1356
- function resolveTextAdapter(opts) {
1357
- const adapter = opts.adapters?.text ?? opts.adapter;
1358
- if (!adapter) throw new Error("Text blocks require a MeasurementAdapter");
1359
- return adapter;
1250
+ function blockMeasurementProvider(opts) {
1251
+ const targetId = opts.targetId ?? "blocks";
1252
+ const name = opts.name ?? `${targetId}-measurements`;
1253
+ const source = opts.source ?? name;
1254
+ const cache = /* @__PURE__ */ new Map();
1255
+ let activeTextAdapter;
1256
+ const deps = [opts.blocks, opts.maxWidth, opts.adapters];
1257
+ if (opts.font) deps.push(opts.font);
1258
+ if (opts.lineHeight) deps.push(opts.lineHeight);
1259
+ if (opts.segmentAdapter) deps.push(opts.segmentAdapter);
1260
+ return opts.graph.node(
1261
+ deps,
1262
+ (ctx) => {
1263
+ const flush = () => {
1264
+ cache.clear();
1265
+ const adapters = depLatest(ctx, 2);
1266
+ adapters.text?.clearCache?.();
1267
+ };
1268
+ ctx.onDeactivation(flush);
1269
+ ctx.onInvalidate(flush);
1270
+ try {
1271
+ const blocks = depLatest(ctx, 0);
1272
+ const maxWidth = nonNegativeFinite(depLatest(ctx, 1), 0);
1273
+ const adapters = depLatest(ctx, 2);
1274
+ if (adapters.text !== activeTextAdapter) {
1275
+ cache.clear();
1276
+ activeTextAdapter = adapters.text;
1277
+ }
1278
+ let depIndex = 3;
1279
+ const font = opts.font ? depLatest(ctx, depIndex++) : void 0;
1280
+ const lineHeight = opts.lineHeight ? nonNegativeFinite(depLatest(ctx, depIndex++), 0) : void 0;
1281
+ const segmentAdapter = opts.segmentAdapter ? depLatest(ctx, depIndex) : getDefaultSegmentAdapter();
1282
+ const measured = [];
1283
+ const issues = [];
1284
+ for (let i = 0; i < blocks.length; i += 1) {
1285
+ const block = blocks[i];
1286
+ const subjectId = block?.id ?? `${targetId}:${i}`;
1287
+ try {
1288
+ if (block === void 0) {
1289
+ throw new Error(`Missing content block at index ${i}`);
1290
+ }
1291
+ const blockFont = block.kind === "text" ? block.font ?? font ?? "16px sans-serif" : void 0;
1292
+ const hyphenWidth = block.kind === "text" && adapters.text ? tryMeasureHyphenWidth(adapters.text, blockFont ?? "16px sans-serif") : void 0;
1293
+ measured.push(
1294
+ measureBlock(block, {
1295
+ adapters,
1296
+ font,
1297
+ hyphenWidth,
1298
+ lineHeight,
1299
+ maxWidth,
1300
+ cache,
1301
+ segmentAdapter
1302
+ })
1303
+ );
1304
+ if (block.kind === "text" && adapters.text) {
1305
+ if (hyphenWidth === void 0) {
1306
+ issues.push(
1307
+ measurementIssue(
1308
+ "measurement.hyphen.failed",
1309
+ `Hyphen measurement failed for '${subjectId}'`,
1310
+ subjectId,
1311
+ BLOCKS_MEASUREMENT_KIND,
1312
+ {
1313
+ source,
1314
+ details: { targetId, index: i },
1315
+ severity: "warning"
1316
+ }
1317
+ )
1318
+ );
1319
+ }
1320
+ }
1321
+ } catch (error) {
1322
+ issues.push(
1323
+ measurementIssue(
1324
+ "measurement.block.failed",
1325
+ `Block measurement failed for '${subjectId}'`,
1326
+ subjectId,
1327
+ BLOCKS_MEASUREMENT_KIND,
1328
+ {
1329
+ source,
1330
+ details: { error, targetId, index: i, blockKind: block?.kind },
1331
+ severity: "error"
1332
+ }
1333
+ )
1334
+ );
1335
+ }
1336
+ }
1337
+ ctx.down([
1338
+ [
1339
+ "DATA",
1340
+ [
1341
+ measurementOk(
1342
+ targetId,
1343
+ BLOCKS_MEASUREMENT_KIND,
1344
+ { blocks: measured },
1345
+ { source }
1346
+ ),
1347
+ ...issues
1348
+ ]
1349
+ ]
1350
+ ]);
1351
+ } catch (error) {
1352
+ ctx.down([
1353
+ [
1354
+ "DATA",
1355
+ [
1356
+ measurementIssue(
1357
+ "measurement.failed",
1358
+ `Block measurement failed for '${targetId}'`,
1359
+ targetId,
1360
+ BLOCKS_MEASUREMENT_KIND,
1361
+ { source, details: error, severity: "error" }
1362
+ )
1363
+ ]
1364
+ ]
1365
+ ]);
1366
+ }
1367
+ },
1368
+ { name }
1369
+ );
1360
1370
  }
1371
+
1372
+ // src/solutions/reactive-layout/block.ts
1361
1373
  function measureBlock(block, opts) {
1362
1374
  const maxWidth = nonNegativeFinite(opts.maxWidth ?? 800, 800);
1363
1375
  const marginTop = nonNegativeFinite(block.marginTop ?? 0, 0);
@@ -1449,6 +1461,8 @@ function computeTotalHeight(blocks) {
1449
1461
  }
1450
1462
  return bottom;
1451
1463
  }
1464
+
1465
+ // src/solutions/reactive-layout/flow.ts
1452
1466
  function columnGeometry(container, columns) {
1453
1467
  const paddingX = nonNegativeFinite(container.paddingX ?? 0, 0);
1454
1468
  const paddingY = nonNegativeFinite(container.paddingY ?? 0, 0);
@@ -1574,6 +1588,8 @@ function computeFlowLines(segments, opts) {
1574
1588
  done: cursor.segmentIndex >= segments.length
1575
1589
  };
1576
1590
  }
1591
+
1592
+ // src/solutions/reactive-layout/bundles.ts
1577
1593
  function reactiveLayout(opts) {
1578
1594
  const { measurements, segmentAdapter: segmentAdapterOpt, name = "reactive-layout" } = opts;
1579
1595
  const targetId = opts.targetId ?? "text";
@@ -1842,17 +1858,47 @@ function reactiveFlowLayout(opts) {
1842
1858
  }
1843
1859
 
1844
1860
  export {
1845
- TEXT_SEGMENTS_MEASUREMENT_KIND,
1846
- BLOCKS_MEASUREMENT_KIND,
1847
- READINESS_MEASUREMENT_KIND,
1848
- IMAGE_SIZE_MEASUREMENT_KIND,
1849
- SVG_BOUNDS_MEASUREMENT_KIND,
1861
+ kinsokuStart,
1862
+ leftStickyPunctuation,
1863
+ isCJK,
1864
+ normalizeWhitespace,
1865
+ segmentText,
1866
+ createDefaultSegmentAdapter,
1867
+ getDefaultSegmentAdapter,
1868
+ measuredWidth,
1869
+ metricKey,
1870
+ nonNegativeFinite,
1871
+ finiteNumber,
1872
+ emitLayoutError,
1873
+ positiveFinite,
1874
+ clampDimension,
1875
+ fitSize,
1876
+ blockMaxWidth,
1877
+ resolveTextAdapter,
1850
1878
  InjectedMeasureAdapter,
1851
1879
  PrecomputedMeasureAdapter,
1852
1880
  CellMeasureAdapter,
1853
1881
  CapabilityMeasureAdapter,
1854
1882
  SvgBoundsAdapter,
1855
1883
  ImageSizeAdapter,
1884
+ analyzeAndMeasure,
1885
+ computeLineBreaks,
1886
+ layoutNextLine,
1887
+ carveTextLineSlots,
1888
+ computeCharPositions,
1889
+ TEXT_SEGMENTS_MEASUREMENT_KIND,
1890
+ BLOCKS_MEASUREMENT_KIND,
1891
+ READINESS_MEASUREMENT_KIND,
1892
+ IMAGE_SIZE_MEASUREMENT_KIND,
1893
+ SVG_BOUNDS_MEASUREMENT_KIND,
1894
+ measurementIssue,
1895
+ measurementOk,
1896
+ latestMeasurementValue,
1897
+ tryMeasureHyphenWidth,
1898
+ validMeasurementSize,
1899
+ textMeasurementFacts,
1900
+ inputNode,
1901
+ scopedName,
1856
1902
  textMeasurementProvider,
1857
1903
  injectedTextMeasurements,
1858
1904
  precomputedTextMeasurements,
@@ -1865,20 +1911,20 @@ export {
1865
1911
  mergeMeasurements,
1866
1912
  blockAdaptersProvider,
1867
1913
  blockMeasurementProvider,
1868
- analyzeAndMeasure,
1869
- computeLineBreaks,
1870
- layoutNextLine,
1871
- carveTextLineSlots,
1872
- computeCharPositions,
1873
1914
  measureBlock,
1874
1915
  measureBlocks,
1875
1916
  computeBlockFlow,
1876
1917
  computeTotalHeight,
1918
+ columnGeometry,
1919
+ sanitizeFlowContainer,
1920
+ sanitizeFlowColumns,
1921
+ sanitizeObstacles,
1877
1922
  circleIntervalForBand,
1878
1923
  rectIntervalForBand,
1924
+ blockedIntervalsForBand,
1879
1925
  computeFlowLines,
1880
1926
  reactiveLayout,
1881
1927
  reactiveBlockLayout,
1882
1928
  reactiveFlowLayout
1883
1929
  };
1884
- //# sourceMappingURL=chunk-YXMZ2N6J.js.map
1930
+ //# sourceMappingURL=chunk-M7J6Z4IJ.js.map