@react-x11/components 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (788) hide show
  1. package/README.md +979 -21
  2. package/dist/ansi/cast.d.ts +48 -0
  3. package/dist/ansi/cast.d.ts.map +1 -0
  4. package/dist/ansi/cast.js +135 -0
  5. package/dist/ansi/cast.js.map +1 -0
  6. package/dist/ansi/index.d.ts +10 -0
  7. package/dist/ansi/index.d.ts.map +1 -0
  8. package/dist/ansi/index.js +27 -0
  9. package/dist/ansi/index.js.map +1 -0
  10. package/dist/ansi/palette.d.ts +79 -0
  11. package/dist/ansi/palette.d.ts.map +1 -0
  12. package/dist/ansi/palette.js +155 -0
  13. package/dist/ansi/palette.js.map +1 -0
  14. package/dist/ansi/parse.d.ts +114 -0
  15. package/dist/ansi/parse.d.ts.map +1 -0
  16. package/dist/ansi/parse.js +687 -0
  17. package/dist/ansi/parse.js.map +1 -0
  18. package/dist/ansi/sgr.d.ts +87 -0
  19. package/dist/ansi/sgr.d.ts.map +1 -0
  20. package/dist/ansi/sgr.js +302 -0
  21. package/dist/ansi/sgr.js.map +1 -0
  22. package/dist/ansi/utf8.d.ts +15 -0
  23. package/dist/ansi/utf8.d.ts.map +1 -0
  24. package/dist/ansi/utf8.js +82 -0
  25. package/dist/ansi/utf8.js.map +1 -0
  26. package/dist/calendar/Calendar.d.ts +136 -0
  27. package/dist/calendar/Calendar.d.ts.map +1 -0
  28. package/dist/calendar/Calendar.js +460 -0
  29. package/dist/calendar/Calendar.js.map +1 -0
  30. package/dist/calendar/DatePicker.d.ts +52 -0
  31. package/dist/calendar/DatePicker.d.ts.map +1 -0
  32. package/dist/calendar/DatePicker.js +257 -0
  33. package/dist/calendar/DatePicker.js.map +1 -0
  34. package/dist/calendar/dates.d.ts +90 -0
  35. package/dist/calendar/dates.d.ts.map +1 -0
  36. package/dist/calendar/dates.js +236 -0
  37. package/dist/calendar/dates.js.map +1 -0
  38. package/dist/calendar/index.d.ts +8 -0
  39. package/dist/calendar/index.d.ts.map +1 -0
  40. package/dist/calendar/index.js +15 -0
  41. package/dist/calendar/index.js.map +1 -0
  42. package/dist/charts/components.d.ts +141 -0
  43. package/dist/charts/components.d.ts.map +1 -0
  44. package/dist/charts/components.js +580 -0
  45. package/dist/charts/components.js.map +1 -0
  46. package/dist/charts/data.d.ts +198 -0
  47. package/dist/charts/data.d.ts.map +1 -0
  48. package/dist/charts/data.js +616 -0
  49. package/dist/charts/data.js.map +1 -0
  50. package/dist/charts/hx.d.ts +21 -0
  51. package/dist/charts/hx.d.ts.map +1 -0
  52. package/dist/charts/hx.js +15 -0
  53. package/dist/charts/hx.js.map +1 -0
  54. package/dist/charts/index.d.ts +27 -0
  55. package/dist/charts/index.d.ts.map +1 -0
  56. package/dist/charts/index.js +38 -0
  57. package/dist/charts/index.js.map +1 -0
  58. package/dist/charts/node.d.ts +96 -0
  59. package/dist/charts/node.d.ts.map +1 -0
  60. package/dist/charts/node.js +720 -0
  61. package/dist/charts/node.js.map +1 -0
  62. package/dist/charts/render.d.ts +153 -0
  63. package/dist/charts/render.d.ts.map +1 -0
  64. package/dist/charts/render.js +762 -0
  65. package/dist/charts/render.js.map +1 -0
  66. package/dist/charts/scale.d.ts +42 -0
  67. package/dist/charts/scale.d.ts.map +1 -0
  68. package/dist/charts/scale.js +173 -0
  69. package/dist/charts/scale.js.map +1 -0
  70. package/dist/charts/spec.d.ts +91 -0
  71. package/dist/charts/spec.d.ts.map +1 -0
  72. package/dist/charts/spec.js +33 -0
  73. package/dist/charts/spec.js.map +1 -0
  74. package/dist/charts/timers.d.ts +6 -0
  75. package/dist/charts/timers.d.ts.map +1 -0
  76. package/dist/charts/timers.js +14 -0
  77. package/dist/charts/timers.js.map +1 -0
  78. package/dist/code/hx.d.ts +24 -0
  79. package/dist/code/hx.d.ts.map +1 -0
  80. package/dist/code/hx.js +25 -0
  81. package/dist/code/hx.js.map +1 -0
  82. package/dist/code/index.d.ts +45 -0
  83. package/dist/code/index.d.ts.map +1 -0
  84. package/dist/code/index.js +93 -0
  85. package/dist/code/index.js.map +1 -0
  86. package/dist/code-editor/completion.d.ts +26 -0
  87. package/dist/code-editor/completion.d.ts.map +1 -0
  88. package/dist/code-editor/completion.js +129 -0
  89. package/dist/code-editor/completion.js.map +1 -0
  90. package/dist/code-editor/doc.d.ts +35 -0
  91. package/dist/code-editor/doc.d.ts.map +1 -0
  92. package/dist/code-editor/doc.js +162 -0
  93. package/dist/code-editor/doc.js.map +1 -0
  94. package/dist/code-editor/hx.d.ts +13 -0
  95. package/dist/code-editor/hx.d.ts.map +1 -0
  96. package/dist/code-editor/hx.js +10 -0
  97. package/dist/code-editor/hx.js.map +1 -0
  98. package/dist/code-editor/index.d.ts +88 -0
  99. package/dist/code-editor/index.d.ts.map +1 -0
  100. package/dist/code-editor/index.js +401 -0
  101. package/dist/code-editor/index.js.map +1 -0
  102. package/dist/code-editor/node.d.ts +343 -0
  103. package/dist/code-editor/node.d.ts.map +1 -0
  104. package/dist/code-editor/node.js +1521 -0
  105. package/dist/code-editor/node.js.map +1 -0
  106. package/dist/code-language/hljs.d.ts +47 -0
  107. package/dist/code-language/hljs.d.ts.map +1 -0
  108. package/dist/code-language/hljs.js +211 -0
  109. package/dist/code-language/hljs.js.map +1 -0
  110. package/dist/code-language/index.d.ts +22 -0
  111. package/dist/code-language/index.d.ts.map +1 -0
  112. package/dist/code-language/index.js +20 -0
  113. package/dist/code-language/index.js.map +1 -0
  114. package/dist/code-language/languages/glsl.d.ts +4 -0
  115. package/dist/code-language/languages/glsl.d.ts.map +1 -0
  116. package/dist/code-language/languages/glsl.js +99 -0
  117. package/dist/code-language/languages/glsl.js.map +1 -0
  118. package/dist/code-language/languages/javascript.d.ts +10 -0
  119. package/dist/code-language/languages/javascript.d.ts.map +1 -0
  120. package/dist/code-language/languages/javascript.js +360 -0
  121. package/dist/code-language/languages/javascript.js.map +1 -0
  122. package/dist/code-language/languages/json.d.ts +4 -0
  123. package/dist/code-language/languages/json.d.ts.map +1 -0
  124. package/dist/code-language/languages/json.js +68 -0
  125. package/dist/code-language/languages/json.js.map +1 -0
  126. package/dist/code-language/languages/shell.d.ts +4 -0
  127. package/dist/code-language/languages/shell.d.ts.map +1 -0
  128. package/dist/code-language/languages/shell.js +189 -0
  129. package/dist/code-language/languages/shell.js.map +1 -0
  130. package/dist/code-language/languages/sql.d.ts +11 -0
  131. package/dist/code-language/languages/sql.d.ts.map +1 -0
  132. package/dist/code-language/languages/sql.js +133 -0
  133. package/dist/code-language/languages/sql.js.map +1 -0
  134. package/dist/code-language/lezer.d.ts +24 -0
  135. package/dist/code-language/lezer.d.ts.map +1 -0
  136. package/dist/code-language/lezer.js +148 -0
  137. package/dist/code-language/lezer.js.map +1 -0
  138. package/dist/code-language/registry.d.ts +19 -0
  139. package/dist/code-language/registry.d.ts.map +1 -0
  140. package/dist/code-language/registry.js +56 -0
  141. package/dist/code-language/registry.js.map +1 -0
  142. package/dist/code-language/runs.d.ts +35 -0
  143. package/dist/code-language/runs.d.ts.map +1 -0
  144. package/dist/code-language/runs.js +88 -0
  145. package/dist/code-language/runs.js.map +1 -0
  146. package/dist/code-language/stream.d.ts +70 -0
  147. package/dist/code-language/stream.d.ts.map +1 -0
  148. package/dist/code-language/stream.js +243 -0
  149. package/dist/code-language/stream.js.map +1 -0
  150. package/dist/code-language/textmate.d.ts +27 -0
  151. package/dist/code-language/textmate.d.ts.map +1 -0
  152. package/dist/code-language/textmate.js +86 -0
  153. package/dist/code-language/textmate.js.map +1 -0
  154. package/dist/code-language/theme.d.ts +26 -0
  155. package/dist/code-language/theme.d.ts.map +1 -0
  156. package/dist/code-language/theme.js +108 -0
  157. package/dist/code-language/theme.js.map +1 -0
  158. package/dist/code-language/timers.d.ts +7 -0
  159. package/dist/code-language/timers.d.ts.map +1 -0
  160. package/dist/code-language/timers.js +22 -0
  161. package/dist/code-language/timers.js.map +1 -0
  162. package/dist/code-language/types.d.ts +173 -0
  163. package/dist/code-language/types.d.ts.map +1 -0
  164. package/dist/code-language/types.js +41 -0
  165. package/dist/code-language/types.js.map +1 -0
  166. package/dist/codeblock/index.d.ts +69 -0
  167. package/dist/codeblock/index.d.ts.map +1 -0
  168. package/dist/codeblock/index.js +85 -0
  169. package/dist/codeblock/index.js.map +1 -0
  170. package/dist/color-picker/ColorField.d.ts +39 -0
  171. package/dist/color-picker/ColorField.d.ts.map +1 -0
  172. package/dist/color-picker/ColorField.js +239 -0
  173. package/dist/color-picker/ColorField.js.map +1 -0
  174. package/dist/color-picker/ColorPicker.d.ts +109 -0
  175. package/dist/color-picker/ColorPicker.d.ts.map +1 -0
  176. package/dist/color-picker/ColorPicker.js +757 -0
  177. package/dist/color-picker/ColorPicker.js.map +1 -0
  178. package/dist/color-picker/color.d.ts +105 -0
  179. package/dist/color-picker/color.d.ts.map +1 -0
  180. package/dist/color-picker/color.js +313 -0
  181. package/dist/color-picker/color.js.map +1 -0
  182. package/dist/color-picker/index.d.ts +8 -0
  183. package/dist/color-picker/index.d.ts.map +1 -0
  184. package/dist/color-picker/index.js +19 -0
  185. package/dist/color-picker/index.js.map +1 -0
  186. package/dist/desktop-calendar/eds.d.ts +102 -0
  187. package/dist/desktop-calendar/eds.d.ts.map +1 -0
  188. package/dist/desktop-calendar/eds.js +356 -0
  189. package/dist/desktop-calendar/eds.js.map +1 -0
  190. package/dist/desktop-calendar/ical.d.ts +63 -0
  191. package/dist/desktop-calendar/ical.d.ts.map +1 -0
  192. package/dist/desktop-calendar/ical.js +57 -0
  193. package/dist/desktop-calendar/ical.js.map +1 -0
  194. package/dist/desktop-calendar/index.d.ts +72 -0
  195. package/dist/desktop-calendar/index.d.ts.map +1 -0
  196. package/dist/desktop-calendar/index.js +213 -0
  197. package/dist/desktop-calendar/index.js.map +1 -0
  198. package/dist/embed/client.d.ts +121 -0
  199. package/dist/embed/client.d.ts.map +1 -0
  200. package/dist/embed/client.js +203 -0
  201. package/dist/embed/client.js.map +1 -0
  202. package/dist/embed/host.d.ts +96 -0
  203. package/dist/embed/host.d.ts.map +1 -0
  204. package/dist/embed/host.js +266 -0
  205. package/dist/embed/host.js.map +1 -0
  206. package/dist/embed/index.d.ts +5 -0
  207. package/dist/embed/index.d.ts.map +1 -0
  208. package/dist/embed/index.js +13 -0
  209. package/dist/embed/index.js.map +1 -0
  210. package/dist/embed/timers.d.ts +6 -0
  211. package/dist/embed/timers.d.ts.map +1 -0
  212. package/dist/embed/timers.js +16 -0
  213. package/dist/embed/timers.js.map +1 -0
  214. package/dist/flow/draw.d.ts +45 -0
  215. package/dist/flow/draw.d.ts.map +1 -0
  216. package/dist/flow/draw.js +295 -0
  217. package/dist/flow/draw.js.map +1 -0
  218. package/dist/flow/index.d.ts +64 -0
  219. package/dist/flow/index.d.ts.map +1 -0
  220. package/dist/flow/index.js +306 -0
  221. package/dist/flow/index.js.map +1 -0
  222. package/dist/flow/model.d.ts +158 -0
  223. package/dist/flow/model.d.ts.map +1 -0
  224. package/dist/flow/model.js +566 -0
  225. package/dist/flow/model.js.map +1 -0
  226. package/dist/flow/node.d.ts +429 -0
  227. package/dist/flow/node.d.ts.map +1 -0
  228. package/dist/flow/node.js +3025 -0
  229. package/dist/flow/node.js.map +1 -0
  230. package/dist/flow/paths.d.ts +43 -0
  231. package/dist/flow/paths.d.ts.map +1 -0
  232. package/dist/flow/paths.js +327 -0
  233. package/dist/flow/paths.js.map +1 -0
  234. package/dist/flow/types.d.ts +561 -0
  235. package/dist/flow/types.d.ts.map +1 -0
  236. package/dist/flow/types.js +2 -0
  237. package/dist/flow/types.js.map +1 -0
  238. package/dist/formula/hx.d.ts +24 -0
  239. package/dist/formula/hx.d.ts.map +1 -0
  240. package/dist/formula/hx.js +25 -0
  241. package/dist/formula/hx.js.map +1 -0
  242. package/dist/formula/index.d.ts +74 -0
  243. package/dist/formula/index.d.ts.map +1 -0
  244. package/dist/formula/index.js +155 -0
  245. package/dist/formula/index.js.map +1 -0
  246. package/dist/formula/katex.d.ts +78 -0
  247. package/dist/formula/katex.d.ts.map +1 -0
  248. package/dist/formula/katex.js +130 -0
  249. package/dist/formula/katex.js.map +1 -0
  250. package/dist/formula/layout.d.ts +103 -0
  251. package/dist/formula/layout.d.ts.map +1 -0
  252. package/dist/formula/layout.js +716 -0
  253. package/dist/formula/layout.js.map +1 -0
  254. package/dist/formula/node.d.ts +50 -0
  255. package/dist/formula/node.d.ts.map +1 -0
  256. package/dist/formula/node.js +351 -0
  257. package/dist/formula/node.js.map +1 -0
  258. package/dist/html/controls.d.ts +48 -0
  259. package/dist/html/controls.d.ts.map +1 -0
  260. package/dist/html/controls.js +195 -0
  261. package/dist/html/controls.js.map +1 -0
  262. package/dist/html/css/cascade.d.ts +51 -0
  263. package/dist/html/css/cascade.d.ts.map +1 -0
  264. package/dist/html/css/cascade.js +552 -0
  265. package/dist/html/css/cascade.js.map +1 -0
  266. package/dist/html/css/parse.d.ts +74 -0
  267. package/dist/html/css/parse.d.ts.map +1 -0
  268. package/dist/html/css/parse.js +464 -0
  269. package/dist/html/css/parse.js.map +1 -0
  270. package/dist/html/css/style.d.ts +142 -0
  271. package/dist/html/css/style.d.ts.map +1 -0
  272. package/dist/html/css/style.js +1145 -0
  273. package/dist/html/css/style.js.map +1 -0
  274. package/dist/html/css/ua.d.ts +5 -0
  275. package/dist/html/css/ua.d.ts.map +1 -0
  276. package/dist/html/css/ua.js +171 -0
  277. package/dist/html/css/ua.js.map +1 -0
  278. package/dist/html/css/values.d.ts +78 -0
  279. package/dist/html/css/values.d.ts.map +1 -0
  280. package/dist/html/css/values.js +330 -0
  281. package/dist/html/css/values.js.map +1 -0
  282. package/dist/html/dom.d.ts +112 -0
  283. package/dist/html/dom.d.ts.map +1 -0
  284. package/dist/html/dom.js +374 -0
  285. package/dist/html/dom.js.map +1 -0
  286. package/dist/html/hx.d.ts +24 -0
  287. package/dist/html/hx.d.ts.map +1 -0
  288. package/dist/html/hx.js +29 -0
  289. package/dist/html/hx.js.map +1 -0
  290. package/dist/html/index.d.ts +137 -0
  291. package/dist/html/index.d.ts.map +1 -0
  292. package/dist/html/index.js +339 -0
  293. package/dist/html/index.js.map +1 -0
  294. package/dist/html/layout/block.d.ts +58 -0
  295. package/dist/html/layout/block.d.ts.map +1 -0
  296. package/dist/html/layout/block.js +724 -0
  297. package/dist/html/layout/block.js.map +1 -0
  298. package/dist/html/layout/boxes.d.ts +261 -0
  299. package/dist/html/layout/boxes.d.ts.map +1 -0
  300. package/dist/html/layout/boxes.js +725 -0
  301. package/dist/html/layout/boxes.js.map +1 -0
  302. package/dist/html/layout/flex.d.ts +16 -0
  303. package/dist/html/layout/flex.d.ts.map +1 -0
  304. package/dist/html/layout/flex.js +242 -0
  305. package/dist/html/layout/flex.js.map +1 -0
  306. package/dist/html/layout/floats.d.ts +50 -0
  307. package/dist/html/layout/floats.d.ts.map +1 -0
  308. package/dist/html/layout/floats.js +110 -0
  309. package/dist/html/layout/floats.js.map +1 -0
  310. package/dist/html/layout/inline.d.ts +44 -0
  311. package/dist/html/layout/inline.d.ts.map +1 -0
  312. package/dist/html/layout/inline.js +700 -0
  313. package/dist/html/layout/inline.js.map +1 -0
  314. package/dist/html/layout/table.d.ts +5 -0
  315. package/dist/html/layout/table.d.ts.map +1 -0
  316. package/dist/html/layout/table.js +340 -0
  317. package/dist/html/layout/table.js.map +1 -0
  318. package/dist/html/node.d.ts +149 -0
  319. package/dist/html/node.d.ts.map +1 -0
  320. package/dist/html/node.js +861 -0
  321. package/dist/html/node.js.map +1 -0
  322. package/dist/html/paint.d.ts +48 -0
  323. package/dist/html/paint.d.ts.map +1 -0
  324. package/dist/html/paint.js +495 -0
  325. package/dist/html/paint.js.map +1 -0
  326. package/dist/html/resources.d.ts +48 -0
  327. package/dist/html/resources.d.ts.map +1 -0
  328. package/dist/html/resources.js +156 -0
  329. package/dist/html/resources.js.map +1 -0
  330. package/dist/index.d.ts +48 -0
  331. package/dist/index.d.ts.map +1 -0
  332. package/dist/index.js +92 -0
  333. package/dist/index.js.map +1 -0
  334. package/dist/internal/heights.d.ts +88 -0
  335. package/dist/internal/heights.d.ts.map +1 -0
  336. package/dist/internal/heights.js +203 -0
  337. package/dist/internal/heights.js.map +1 -0
  338. package/dist/internal/hx.d.ts +24 -0
  339. package/dist/internal/hx.d.ts.map +1 -0
  340. package/dist/internal/hx.js +27 -0
  341. package/dist/internal/hx.js.map +1 -0
  342. package/dist/internal/scroll.d.ts +62 -0
  343. package/dist/internal/scroll.d.ts.map +1 -0
  344. package/dist/internal/scroll.js +224 -0
  345. package/dist/internal/scroll.js.map +1 -0
  346. package/dist/internal/text.d.ts +6 -0
  347. package/dist/internal/text.d.ts.map +1 -0
  348. package/dist/internal/text.js +44 -0
  349. package/dist/internal/text.js.map +1 -0
  350. package/dist/internal/timers.d.ts +8 -0
  351. package/dist/internal/timers.d.ts.map +1 -0
  352. package/dist/internal/timers.js +22 -0
  353. package/dist/internal/timers.js.map +1 -0
  354. package/dist/internal/widget.d.ts +40 -0
  355. package/dist/internal/widget.d.ts.map +1 -0
  356. package/dist/internal/widget.js +44 -0
  357. package/dist/internal/widget.js.map +1 -0
  358. package/dist/markdown/ast.d.ts +126 -0
  359. package/dist/markdown/ast.d.ts.map +1 -0
  360. package/dist/markdown/ast.js +8 -0
  361. package/dist/markdown/ast.js.map +1 -0
  362. package/dist/markdown/hx.d.ts +24 -0
  363. package/dist/markdown/hx.d.ts.map +1 -0
  364. package/dist/markdown/hx.js +25 -0
  365. package/dist/markdown/hx.js.map +1 -0
  366. package/dist/markdown/index.d.ts +90 -0
  367. package/dist/markdown/index.d.ts.map +1 -0
  368. package/dist/markdown/index.js +413 -0
  369. package/dist/markdown/index.js.map +1 -0
  370. package/dist/markdown/parse.d.ts +8 -0
  371. package/dist/markdown/parse.d.ts.map +1 -0
  372. package/dist/markdown/parse.js +911 -0
  373. package/dist/markdown/parse.js.map +1 -0
  374. package/dist/markdown/spans.d.ts +20 -0
  375. package/dist/markdown/spans.d.ts.map +1 -0
  376. package/dist/markdown/spans.js +96 -0
  377. package/dist/markdown/spans.js.map +1 -0
  378. package/dist/media-player/backends.d.ts +64 -0
  379. package/dist/media-player/backends.d.ts.map +1 -0
  380. package/dist/media-player/backends.js +110 -0
  381. package/dist/media-player/backends.js.map +1 -0
  382. package/dist/media-player/control.d.ts +40 -0
  383. package/dist/media-player/control.d.ts.map +1 -0
  384. package/dist/media-player/control.js +44 -0
  385. package/dist/media-player/control.js.map +1 -0
  386. package/dist/media-player/hx.d.ts +24 -0
  387. package/dist/media-player/hx.d.ts.map +1 -0
  388. package/dist/media-player/hx.js +25 -0
  389. package/dist/media-player/hx.js.map +1 -0
  390. package/dist/media-player/index.d.ts +107 -0
  391. package/dist/media-player/index.d.ts.map +1 -0
  392. package/dist/media-player/index.js +219 -0
  393. package/dist/media-player/index.js.map +1 -0
  394. package/dist/media-player/mpv.d.ts +4 -0
  395. package/dist/media-player/mpv.d.ts.map +1 -0
  396. package/dist/media-player/mpv.js +120 -0
  397. package/dist/media-player/mpv.js.map +1 -0
  398. package/dist/media-player/vlc.d.ts +8 -0
  399. package/dist/media-player/vlc.d.ts.map +1 -0
  400. package/dist/media-player/vlc.js +83 -0
  401. package/dist/media-player/vlc.js.map +1 -0
  402. package/dist/richtext/index.d.ts +19 -0
  403. package/dist/richtext/index.d.ts.map +1 -0
  404. package/dist/richtext/index.js +4 -0
  405. package/dist/richtext/index.js.map +1 -0
  406. package/dist/richtext/links.d.ts +12 -0
  407. package/dist/richtext/links.d.ts.map +1 -0
  408. package/dist/richtext/links.js +64 -0
  409. package/dist/richtext/links.js.map +1 -0
  410. package/dist/richtext/menu.d.ts +11 -0
  411. package/dist/richtext/menu.d.ts.map +1 -0
  412. package/dist/richtext/menu.js +43 -0
  413. package/dist/richtext/menu.js.map +1 -0
  414. package/dist/richtext/node.d.ts +151 -0
  415. package/dist/richtext/node.d.ts.map +1 -0
  416. package/dist/richtext/node.js +255 -0
  417. package/dist/richtext/node.js.map +1 -0
  418. package/dist/richtext/runs.d.ts +92 -0
  419. package/dist/richtext/runs.d.ts.map +1 -0
  420. package/dist/richtext/runs.js +158 -0
  421. package/dist/richtext/runs.js.map +1 -0
  422. package/dist/table/hx.d.ts +24 -0
  423. package/dist/table/hx.d.ts.map +1 -0
  424. package/dist/table/hx.js +25 -0
  425. package/dist/table/hx.js.map +1 -0
  426. package/dist/table/index.d.ts +169 -0
  427. package/dist/table/index.d.ts.map +1 -0
  428. package/dist/table/index.js +890 -0
  429. package/dist/table/index.js.map +1 -0
  430. package/dist/table/rows.d.ts +136 -0
  431. package/dist/table/rows.d.ts.map +1 -0
  432. package/dist/table/rows.js +146 -0
  433. package/dist/table/rows.js.map +1 -0
  434. package/dist/terminal/backends.d.ts +105 -0
  435. package/dist/terminal/backends.d.ts.map +1 -0
  436. package/dist/terminal/backends.js +185 -0
  437. package/dist/terminal/backends.js.map +1 -0
  438. package/dist/terminal/hx.d.ts +24 -0
  439. package/dist/terminal/hx.d.ts.map +1 -0
  440. package/dist/terminal/hx.js +25 -0
  441. package/dist/terminal/hx.js.map +1 -0
  442. package/dist/terminal/index.d.ts +160 -0
  443. package/dist/terminal/index.d.ts.map +1 -0
  444. package/dist/terminal/index.js +344 -0
  445. package/dist/terminal/index.js.map +1 -0
  446. package/dist/terminal/title.d.ts +24 -0
  447. package/dist/terminal/title.d.ts.map +1 -0
  448. package/dist/terminal/title.js +129 -0
  449. package/dist/terminal/title.js.map +1 -0
  450. package/dist/terminal/vt/colors.d.ts +63 -0
  451. package/dist/terminal/vt/colors.d.ts.map +1 -0
  452. package/dist/terminal/vt/colors.js +203 -0
  453. package/dist/terminal/vt/colors.js.map +1 -0
  454. package/dist/terminal/vt/diff.d.ts +117 -0
  455. package/dist/terminal/vt/diff.d.ts.map +1 -0
  456. package/dist/terminal/vt/diff.js +358 -0
  457. package/dist/terminal/vt/diff.js.map +1 -0
  458. package/dist/terminal/vt/fonts.d.ts +92 -0
  459. package/dist/terminal/vt/fonts.d.ts.map +1 -0
  460. package/dist/terminal/vt/fonts.js +178 -0
  461. package/dist/terminal/vt/fonts.js.map +1 -0
  462. package/dist/terminal/vt/index.d.ts +78 -0
  463. package/dist/terminal/vt/index.d.ts.map +1 -0
  464. package/dist/terminal/vt/index.js +312 -0
  465. package/dist/terminal/vt/index.js.map +1 -0
  466. package/dist/terminal/vt/keys.d.ts +74 -0
  467. package/dist/terminal/vt/keys.d.ts.map +1 -0
  468. package/dist/terminal/vt/keys.js +309 -0
  469. package/dist/terminal/vt/keys.js.map +1 -0
  470. package/dist/terminal/vt/mouse.d.ts +44 -0
  471. package/dist/terminal/vt/mouse.d.ts.map +1 -0
  472. package/dist/terminal/vt/mouse.js +106 -0
  473. package/dist/terminal/vt/mouse.js.map +1 -0
  474. package/dist/terminal/vt/node.d.ts +246 -0
  475. package/dist/terminal/vt/node.d.ts.map +1 -0
  476. package/dist/terminal/vt/node.js +1068 -0
  477. package/dist/terminal/vt/node.js.map +1 -0
  478. package/dist/terminal/vt/pty.d.ts +81 -0
  479. package/dist/terminal/vt/pty.d.ts.map +1 -0
  480. package/dist/terminal/vt/pty.js +201 -0
  481. package/dist/terminal/vt/pty.js.map +1 -0
  482. package/dist/terminal/vt/renderer.d.ts +179 -0
  483. package/dist/terminal/vt/renderer.d.ts.map +1 -0
  484. package/dist/terminal/vt/renderer.js +357 -0
  485. package/dist/terminal/vt/renderer.js.map +1 -0
  486. package/dist/terminal/vt/timers.d.ts +6 -0
  487. package/dist/terminal/vt/timers.d.ts.map +1 -0
  488. package/dist/terminal/vt/timers.js +16 -0
  489. package/dist/terminal/vt/timers.js.map +1 -0
  490. package/dist/terminal/vt/xterm.d.ts +142 -0
  491. package/dist/terminal/vt/xterm.d.ts.map +1 -0
  492. package/dist/terminal/vt/xterm.js +32 -0
  493. package/dist/terminal/vt/xterm.js.map +1 -0
  494. package/dist/terminal-output/hx.d.ts +24 -0
  495. package/dist/terminal-output/hx.d.ts.map +1 -0
  496. package/dist/terminal-output/hx.js +25 -0
  497. package/dist/terminal-output/hx.js.map +1 -0
  498. package/dist/terminal-output/index.d.ts +92 -0
  499. package/dist/terminal-output/index.d.ts.map +1 -0
  500. package/dist/terminal-output/index.js +179 -0
  501. package/dist/terminal-output/index.js.map +1 -0
  502. package/dist/terminal-output/runs.d.ts +27 -0
  503. package/dist/terminal-output/runs.d.ts.map +1 -0
  504. package/dist/terminal-output/runs.js +66 -0
  505. package/dist/terminal-output/runs.js.map +1 -0
  506. package/dist/three/canvas.d.ts +46 -0
  507. package/dist/three/canvas.d.ts.map +1 -0
  508. package/dist/three/canvas.js +305 -0
  509. package/dist/three/canvas.js.map +1 -0
  510. package/dist/three/events.d.ts +64 -0
  511. package/dist/three/events.d.ts.map +1 -0
  512. package/dist/three/events.js +146 -0
  513. package/dist/three/events.js.map +1 -0
  514. package/dist/three/geometries.d.ts +89 -0
  515. package/dist/three/geometries.d.ts.map +1 -0
  516. package/dist/three/geometries.js +345 -0
  517. package/dist/three/geometries.js.map +1 -0
  518. package/dist/three/globals.d.ts +7 -0
  519. package/dist/three/globals.d.ts.map +1 -0
  520. package/dist/three/globals.js +20 -0
  521. package/dist/three/globals.js.map +1 -0
  522. package/dist/three/hx.d.ts +9 -0
  523. package/dist/three/hx.d.ts.map +1 -0
  524. package/dist/three/hx.js +10 -0
  525. package/dist/three/hx.js.map +1 -0
  526. package/dist/three/index.d.ts +22 -0
  527. package/dist/three/index.d.ts.map +1 -0
  528. package/dist/three/index.js +24 -0
  529. package/dist/three/index.js.map +1 -0
  530. package/dist/three/jsx-dev-runtime.d.ts +19 -0
  531. package/dist/three/jsx-dev-runtime.d.ts.map +1 -0
  532. package/dist/three/jsx-dev-runtime.js +2 -0
  533. package/dist/three/jsx-dev-runtime.js.map +1 -0
  534. package/dist/three/jsx-runtime.d.ts +19 -0
  535. package/dist/three/jsx-runtime.d.ts.map +1 -0
  536. package/dist/three/jsx-runtime.js +2 -0
  537. package/dist/three/jsx-runtime.js.map +1 -0
  538. package/dist/three/jsx.d.ts +198 -0
  539. package/dist/three/jsx.d.ts.map +1 -0
  540. package/dist/three/jsx.js +2 -0
  541. package/dist/three/jsx.js.map +1 -0
  542. package/dist/three/materials.d.ts +125 -0
  543. package/dist/three/materials.d.ts.map +1 -0
  544. package/dist/three/materials.js +229 -0
  545. package/dist/three/materials.js.map +1 -0
  546. package/dist/three/math.d.ts +146 -0
  547. package/dist/three/math.d.ts.map +1 -0
  548. package/dist/three/math.js +464 -0
  549. package/dist/three/math.js.map +1 -0
  550. package/dist/three/objects.d.ts +185 -0
  551. package/dist/three/objects.d.ts.map +1 -0
  552. package/dist/three/objects.js +309 -0
  553. package/dist/three/objects.js.map +1 -0
  554. package/dist/three/passes.d.ts +54 -0
  555. package/dist/three/passes.d.ts.map +1 -0
  556. package/dist/three/passes.js +78 -0
  557. package/dist/three/passes.js.map +1 -0
  558. package/dist/three/postprocess.d.ts +85 -0
  559. package/dist/three/postprocess.d.ts.map +1 -0
  560. package/dist/three/postprocess.js +503 -0
  561. package/dist/three/postprocess.js.map +1 -0
  562. package/dist/three/raycast.d.ts +24 -0
  563. package/dist/three/raycast.d.ts.map +1 -0
  564. package/dist/three/raycast.js +138 -0
  565. package/dist/three/raycast.js.map +1 -0
  566. package/dist/three/reconciler.d.ts +48 -0
  567. package/dist/three/reconciler.d.ts.map +1 -0
  568. package/dist/three/reconciler.js +416 -0
  569. package/dist/three/reconciler.js.map +1 -0
  570. package/dist/three/renderer-direct.d.ts +102 -0
  571. package/dist/three/renderer-direct.d.ts.map +1 -0
  572. package/dist/three/renderer-direct.js +782 -0
  573. package/dist/three/renderer-direct.js.map +1 -0
  574. package/dist/three/renderer-indirect.d.ts +68 -0
  575. package/dist/three/renderer-indirect.d.ts.map +1 -0
  576. package/dist/three/renderer-indirect.js +438 -0
  577. package/dist/three/renderer-indirect.js.map +1 -0
  578. package/dist/three/store.d.ts +81 -0
  579. package/dist/three/store.d.ts.map +1 -0
  580. package/dist/three/store.js +110 -0
  581. package/dist/three/store.js.map +1 -0
  582. package/dist/timeline/hx.d.ts +18 -0
  583. package/dist/timeline/hx.d.ts.map +1 -0
  584. package/dist/timeline/hx.js +10 -0
  585. package/dist/timeline/hx.js.map +1 -0
  586. package/dist/timeline/index.d.ts +152 -0
  587. package/dist/timeline/index.d.ts.map +1 -0
  588. package/dist/timeline/index.js +383 -0
  589. package/dist/timeline/index.js.map +1 -0
  590. package/dist/tray-host/hx.d.ts +24 -0
  591. package/dist/tray-host/hx.d.ts.map +1 -0
  592. package/dist/tray-host/hx.js +25 -0
  593. package/dist/tray-host/hx.js.map +1 -0
  594. package/dist/tray-host/index.d.ts +110 -0
  595. package/dist/tray-host/index.d.ts.map +1 -0
  596. package/dist/tray-host/index.js +191 -0
  597. package/dist/tray-host/index.js.map +1 -0
  598. package/dist/tray-host/manager.d.ts +137 -0
  599. package/dist/tray-host/manager.d.ts.map +1 -0
  600. package/dist/tray-host/manager.js +462 -0
  601. package/dist/tray-host/manager.js.map +1 -0
  602. package/dist/tray-host/notify.d.ts +22 -0
  603. package/dist/tray-host/notify.d.ts.map +1 -0
  604. package/dist/tray-host/notify.js +74 -0
  605. package/dist/tray-host/notify.js.map +1 -0
  606. package/dist/tray-host/protocol.d.ts +106 -0
  607. package/dist/tray-host/protocol.d.ts.map +1 -0
  608. package/dist/tray-host/protocol.js +191 -0
  609. package/dist/tray-host/protocol.js.map +1 -0
  610. package/dist/tree/hx.d.ts +24 -0
  611. package/dist/tree/hx.d.ts.map +1 -0
  612. package/dist/tree/hx.js +25 -0
  613. package/dist/tree/hx.js.map +1 -0
  614. package/dist/tree/index.d.ts +221 -0
  615. package/dist/tree/index.d.ts.map +1 -0
  616. package/dist/tree/index.js +751 -0
  617. package/dist/tree/index.js.map +1 -0
  618. package/dist/tree/internal.d.ts +18 -0
  619. package/dist/tree/internal.d.ts.map +1 -0
  620. package/dist/tree/internal.js +66 -0
  621. package/dist/tree/internal.js.map +1 -0
  622. package/dist/tree/rows.d.ts +177 -0
  623. package/dist/tree/rows.d.ts.map +1 -0
  624. package/dist/tree/rows.js +179 -0
  625. package/dist/tree/rows.js.map +1 -0
  626. package/package.json +166 -12
  627. package/src/ansi/cast.ts +159 -0
  628. package/src/ansi/index.ts +53 -0
  629. package/src/ansi/palette.ts +226 -0
  630. package/src/ansi/parse.ts +780 -0
  631. package/src/ansi/sgr.ts +380 -0
  632. package/src/ansi/utf8.ts +84 -0
  633. package/src/calendar/Calendar.ts +744 -0
  634. package/src/calendar/DatePicker.ts +368 -0
  635. package/src/calendar/dates.ts +307 -0
  636. package/src/calendar/index.ts +51 -0
  637. package/src/charts/components.ts +864 -0
  638. package/src/charts/data.ts +776 -0
  639. package/src/charts/hx.ts +39 -0
  640. package/src/charts/index.ts +99 -0
  641. package/src/charts/node.ts +932 -0
  642. package/src/charts/render.ts +982 -0
  643. package/src/charts/scale.ts +214 -0
  644. package/src/charts/spec.ts +122 -0
  645. package/src/charts/timers.ts +24 -0
  646. package/src/code/hx.ts +51 -0
  647. package/src/code/index.ts +174 -0
  648. package/src/code-editor/completion.ts +161 -0
  649. package/src/code-editor/doc.ts +198 -0
  650. package/src/code-editor/hx.ts +26 -0
  651. package/src/code-editor/index.ts +615 -0
  652. package/src/code-editor/node.ts +1926 -0
  653. package/src/code-language/hljs.ts +302 -0
  654. package/src/code-language/index.ts +51 -0
  655. package/src/code-language/languages/glsl.ts +120 -0
  656. package/src/code-language/languages/javascript.ts +419 -0
  657. package/src/code-language/languages/json.ts +72 -0
  658. package/src/code-language/languages/shell.ts +221 -0
  659. package/src/code-language/languages/sql.ts +165 -0
  660. package/src/code-language/lezer.ts +190 -0
  661. package/src/code-language/registry.ts +66 -0
  662. package/src/code-language/runs.ts +128 -0
  663. package/src/code-language/stream.ts +306 -0
  664. package/src/code-language/textmate.ts +134 -0
  665. package/src/code-language/theme.ts +124 -0
  666. package/src/code-language/timers.ts +36 -0
  667. package/src/code-language/types.ts +252 -0
  668. package/src/codeblock/index.ts +146 -0
  669. package/src/color-picker/ColorField.ts +333 -0
  670. package/src/color-picker/ColorPicker.ts +1069 -0
  671. package/src/color-picker/color.ts +399 -0
  672. package/src/color-picker/index.ts +50 -0
  673. package/src/desktop-calendar/eds.ts +484 -0
  674. package/src/desktop-calendar/ical.ts +119 -0
  675. package/src/desktop-calendar/index.ts +287 -0
  676. package/src/embed/client.ts +311 -0
  677. package/src/embed/host.ts +432 -0
  678. package/src/embed/index.ts +33 -0
  679. package/src/embed/timers.ts +32 -0
  680. package/src/flow/draw.ts +418 -0
  681. package/src/flow/index.ts +473 -0
  682. package/src/flow/model.ts +687 -0
  683. package/src/flow/node.ts +3694 -0
  684. package/src/flow/paths.ts +403 -0
  685. package/src/flow/types.ts +634 -0
  686. package/src/formula/hx.ts +51 -0
  687. package/src/formula/index.ts +243 -0
  688. package/src/formula/katex.ts +209 -0
  689. package/src/formula/layout.ts +876 -0
  690. package/src/formula/node.ts +467 -0
  691. package/src/html/controls.ts +244 -0
  692. package/src/html/css/cascade.ts +606 -0
  693. package/src/html/css/parse.ts +500 -0
  694. package/src/html/css/style.ts +1371 -0
  695. package/src/html/css/ua.ts +174 -0
  696. package/src/html/css/values.ts +358 -0
  697. package/src/html/dom.ts +410 -0
  698. package/src/html/hx.ts +55 -0
  699. package/src/html/index.ts +545 -0
  700. package/src/html/layout/block.ts +876 -0
  701. package/src/html/layout/boxes.ts +981 -0
  702. package/src/html/layout/flex.ts +297 -0
  703. package/src/html/layout/floats.ts +125 -0
  704. package/src/html/layout/inline.ts +870 -0
  705. package/src/html/layout/table.ts +380 -0
  706. package/src/html/node.ts +967 -0
  707. package/src/html/paint.ts +605 -0
  708. package/src/html/resources.ts +214 -0
  709. package/src/index.ts +638 -0
  710. package/src/internal/heights.ts +222 -0
  711. package/src/internal/hx.ts +53 -0
  712. package/src/internal/scroll.ts +288 -0
  713. package/src/internal/text.ts +44 -0
  714. package/src/internal/timers.ts +44 -0
  715. package/src/internal/widget.ts +92 -0
  716. package/src/markdown/ast.ts +163 -0
  717. package/src/markdown/hx.ts +51 -0
  718. package/src/markdown/index.ts +686 -0
  719. package/src/markdown/parse.ts +1037 -0
  720. package/src/markdown/spans.ts +143 -0
  721. package/src/media-player/backends.ts +155 -0
  722. package/src/media-player/control.ts +70 -0
  723. package/src/media-player/hx.ts +51 -0
  724. package/src/media-player/index.ts +378 -0
  725. package/src/media-player/mpv.ts +146 -0
  726. package/src/media-player/vlc.ts +97 -0
  727. package/src/richtext/index.ts +42 -0
  728. package/src/richtext/links.ts +78 -0
  729. package/src/richtext/menu.ts +49 -0
  730. package/src/richtext/node.ts +406 -0
  731. package/src/richtext/runs.ts +253 -0
  732. package/src/table/hx.ts +51 -0
  733. package/src/table/index.ts +1270 -0
  734. package/src/table/rows.ts +275 -0
  735. package/src/terminal/backends.ts +242 -0
  736. package/src/terminal/hx.ts +51 -0
  737. package/src/terminal/index.ts +574 -0
  738. package/src/terminal/title.ts +172 -0
  739. package/src/terminal/vt/colors.ts +247 -0
  740. package/src/terminal/vt/diff.ts +467 -0
  741. package/src/terminal/vt/fonts.ts +233 -0
  742. package/src/terminal/vt/index.ts +443 -0
  743. package/src/terminal/vt/keys.ts +369 -0
  744. package/src/terminal/vt/mouse.ts +144 -0
  745. package/src/terminal/vt/node.ts +1242 -0
  746. package/src/terminal/vt/pty.ts +334 -0
  747. package/src/terminal/vt/renderer.ts +555 -0
  748. package/src/terminal/vt/timers.ts +31 -0
  749. package/src/terminal/vt/xterm.ts +193 -0
  750. package/src/terminal-output/hx.ts +51 -0
  751. package/src/terminal-output/index.ts +340 -0
  752. package/src/terminal-output/runs.ts +79 -0
  753. package/src/three/canvas.ts +451 -0
  754. package/src/three/events.ts +197 -0
  755. package/src/three/geometries.ts +429 -0
  756. package/src/three/globals.ts +34 -0
  757. package/src/three/hx.ts +22 -0
  758. package/src/three/index.ts +98 -0
  759. package/src/three/jsx-dev-runtime.ts +27 -0
  760. package/src/three/jsx-runtime.ts +38 -0
  761. package/src/three/jsx.ts +275 -0
  762. package/src/three/materials.ts +270 -0
  763. package/src/three/math.ts +585 -0
  764. package/src/three/objects.ts +397 -0
  765. package/src/three/passes.ts +90 -0
  766. package/src/three/postprocess.ts +677 -0
  767. package/src/three/raycast.ts +189 -0
  768. package/src/three/react-reconciler.d.ts +50 -0
  769. package/src/three/reconciler.ts +624 -0
  770. package/src/three/renderer-direct.ts +1055 -0
  771. package/src/three/renderer-indirect.ts +570 -0
  772. package/src/three/store.ts +207 -0
  773. package/src/timeline/hx.ts +31 -0
  774. package/src/timeline/index.ts +603 -0
  775. package/src/tray-host/hx.ts +51 -0
  776. package/src/tray-host/index.ts +331 -0
  777. package/src/tray-host/manager.ts +639 -0
  778. package/src/tray-host/notify.ts +102 -0
  779. package/src/tray-host/protocol.ts +235 -0
  780. package/src/tree/hx.ts +51 -0
  781. package/src/tree/index.ts +1127 -0
  782. package/src/tree/internal.ts +87 -0
  783. package/src/tree/rows.ts +334 -0
  784. package/src/index.d.ts +0 -2
  785. package/src/index.js +0 -9
  786. package/src/sparkline/index.d.ts +0 -29
  787. package/src/sparkline/index.js +0 -50
  788. package/src/sparkline/node.js +0 -72
@@ -0,0 +1,870 @@
1
+ // Inline layout: text, and the atomic things that sit in the middle of it.
2
+ //
3
+ // The whole file turns on one decision — **how many times ntk's `TextLayout`
4
+ // is called per paragraph** — because that is where a document's first paint
5
+ // is won or lost.
6
+ //
7
+ // `TextLayout` does the expensive and difficult half already: UAX#14 break
8
+ // opportunities, OpenType shaping with a memo per inter-break segment, font
9
+ // fallback, bidi, and per-line UAX#9 reordering. Calling it **once** for a
10
+ // whole inline formatting context is therefore both the fastest and the most
11
+ // correct thing this can do, and it is what the common case does: a
12
+ // paragraph, a heading, a list item's line, a table cell.
13
+ //
14
+ // Two things break that. An **atomic** in the middle of the text — an image,
15
+ // an inline-block, a form control — which the text layout knows nothing
16
+ // about; and a **float**, which makes the available width differ line by
17
+ // line while `TextLayout` takes one `maxWidth`. Either drops this into a
18
+ // line-at-a-time loop that re-lays the remaining text per line. That loop is
19
+ // quadratic, and that is fine, because it *leaves* itself the moment nothing
20
+ // ahead can vary the width again: the tail of a long paragraph beside a
21
+ // floated image is one call, not one per line.
22
+ //
23
+ // The runs handed to `TextLayout` are richtext's `TextRun`s, and that is
24
+ // deliberate rather than incidental: ntk lets unknown span fields ride along
25
+ // and hands them back on the laid-out runs, so the decoration a `<span>`
26
+ // carries reaches paint on the same object the glyphs did — which is exactly
27
+ // the trick `<richtext>` is built on, and it is why paint reuses richtext's
28
+ // decoration pass unchanged instead of reimplementing it.
29
+ import type { Element } from 'domhandler';
30
+
31
+ import { codeUnitOffsets } from '../../internal/text.js';
32
+ import type { TextRun } from '../../richtext/index.js';
33
+ import type { ComputedStyle } from '../css/style.js';
34
+ import { inkColor, isTransparent } from '../css/values.js';
35
+ import type {
36
+ AtomicPlacement,
37
+ Box,
38
+ LineBox,
39
+ LineText,
40
+ TextLayoutLike,
41
+ } from './boxes.js';
42
+ import type { FloatContext } from './floats.js';
43
+
44
+ /** The slice of ntk's font manager this needs. Structural, as everywhere. */
45
+ export interface FontsLike {
46
+ layout(
47
+ content: TextRun[],
48
+ style: Record<string, unknown>,
49
+ options: {
50
+ maxWidth?: number;
51
+ lineHeight?: number;
52
+ align?: string;
53
+ direction?: string;
54
+ maxLines?: number;
55
+ },
56
+ ): TextLayoutLike;
57
+ match(
58
+ family: string,
59
+ style: Record<string, unknown>,
60
+ ): {
61
+ metrics(size: number): {
62
+ ascent: number;
63
+ descent: number;
64
+ lineHeight: number;
65
+ };
66
+ };
67
+ }
68
+
69
+ /**
70
+ * The text behind a layout, for the one caller that needs it: a selection
71
+ * band has to turn a document offset into a **code point** index, which is
72
+ * what ntk's caret API speaks, and that conversion needs the string.
73
+ *
74
+ * Kept as the runs rather than the joined text, and joined on demand, because
75
+ * the first paint never asks — only a selection does — and joining every
76
+ * paragraph up front would be a string allocation per block for a feature
77
+ * most documents are read without using.
78
+ */
79
+ const LAYOUT_RUNS = new WeakMap<TextLayoutLike, TextRun[] | number[]>();
80
+
81
+ /** Code-unit → code-point offsets for a layout's text, built once. */
82
+ export function layoutOffsets(layout: TextLayoutLike): number[] {
83
+ const held = LAYOUT_RUNS.get(layout);
84
+ if (!held) return EMPTY_OFFSETS;
85
+ if (typeof held[0] === 'number' || held.length === 0) return held as number[];
86
+ const offsets = codeUnitOffsets(
87
+ (held as TextRun[]).map((r) => r.text).join(''),
88
+ );
89
+ LAYOUT_RUNS.set(layout, offsets);
90
+ return offsets;
91
+ }
92
+
93
+ const EMPTY_OFFSETS: number[] = [0];
94
+
95
+ /** One thing in the inline stream. */
96
+ type Item =
97
+ | { kind: 'text'; run: TextRun; box: Box; length: number }
98
+ | { kind: 'atomic'; box: Box };
99
+
100
+ export interface InlineResult {
101
+ lines: LineBox[];
102
+ height: number;
103
+ /** The widest line — what a shrink-to-fit width takes. */
104
+ width: number;
105
+ }
106
+
107
+ export interface InlineOptions {
108
+ fonts: FontsLike | null;
109
+ /** Content-box width available, before floats narrow it. */
110
+ width: number;
111
+ /** Where the first line starts, in the float context's coordinate space. */
112
+ startY: number;
113
+ floats: FloatContext | null;
114
+ /** The block's content-box left edge, in the float context's space. */
115
+ originX: number;
116
+ }
117
+
118
+ /**
119
+ * Lay out one inline formatting context. Coordinates in the result are
120
+ * relative to the containing block's content box; the caller translates.
121
+ */
122
+ export function layoutInline(block: Box, options: InlineOptions): InlineResult {
123
+ const fonts = options.fonts;
124
+ const items: Item[] = [];
125
+ collect(block, items);
126
+ if (!items.length || !fonts) return EMPTY;
127
+
128
+ const style = block.style;
129
+ const base = {
130
+ family: style.fontFamily,
131
+ size: style.fontSize,
132
+ weight: style.fontWeight,
133
+ style: style.fontStyle,
134
+ color: style.color,
135
+ };
136
+ const lineHeightMul = lineHeightMultiplier(fonts, style);
137
+ const align = alignFor(style);
138
+ const indent = indentOf(style, options.width);
139
+
140
+ const hasAtomics = items.some((i) => i.kind === 'atomic');
141
+ const floated = options.floats?.intersects(options.startY, Infinity) ?? false;
142
+
143
+ // The text-only, float-free, unindented case: one call, every line — or
144
+ // one call per *chunk*, when the text is long and carries hard breaks.
145
+ if (!hasAtomics && !floated && !indent) {
146
+ // `hasAtomics` is false, so every item is text; the cast is that fact.
147
+ const textItems = items as Extract<Item, { kind: 'text' }>[];
148
+ let total = 0;
149
+ let hasNewline = false;
150
+ for (const item of textItems) {
151
+ total += item.length;
152
+ if (!hasNewline && item.run.text.includes('\n')) hasNewline = true;
153
+ }
154
+ if (!total) return EMPTY;
155
+ if (total > CHUNK_TRIGGER_CHARS && hasNewline) {
156
+ return layoutChunked(
157
+ textItems,
158
+ base,
159
+ style,
160
+ options.width,
161
+ lineHeightMul,
162
+ align,
163
+ fonts,
164
+ );
165
+ }
166
+ const runs: TextRun[] = [];
167
+ const spans = new SpanMap();
168
+ for (const item of textItems) {
169
+ spans.add(item.box.textStart, item.run.text.length);
170
+ runs.push(item.run);
171
+ }
172
+ const layout = fonts.layout(runs, base, {
173
+ maxWidth: wraps(style) ? options.width : undefined,
174
+ lineHeight: lineHeightMul,
175
+ align,
176
+ direction: style.direction,
177
+ });
178
+ LAYOUT_RUNS.set(layout, runs);
179
+ const lines: LineBox[] = [];
180
+ const widest = emitLayout(layout, spans, 0, 0, lines);
181
+ return { lines, height: layout.height, width: widest };
182
+ }
183
+
184
+ // --- the general case: line at a time -------------------------------------
185
+ const lines: LineBox[] = [];
186
+ let widest = 0;
187
+ let y = 0;
188
+ let index = 0;
189
+ let offset = 0;
190
+ let open = openLine(indent);
191
+
192
+ const close = (): void => {
193
+ const line = finishLine(open, y);
194
+ if (!line) {
195
+ open = openLine(0);
196
+ return;
197
+ }
198
+ lines.push(line);
199
+ widest = Math.max(widest, line.width);
200
+ y += line.height;
201
+ open = openLine(0);
202
+ };
203
+
204
+ while (index < items.length) {
205
+ const band = bandAt(options, y, style.fontSize * 1.4);
206
+ const available = band.right - band.left;
207
+ const item = items[index];
208
+
209
+ if (item.kind === 'atomic') {
210
+ const box = item.box;
211
+ const outer = box.width + box.marginLeft + box.marginRight;
212
+ if (open.x > 0 && open.x + outer > available) {
213
+ close();
214
+ continue;
215
+ }
216
+ open.atomics.push({ box, x: band.left + open.x + box.marginLeft, y: 0 });
217
+ open.x += outer;
218
+ index += 1;
219
+ continue;
220
+ }
221
+
222
+ const segment = segmentFrom(items, index, offset);
223
+ // `segmentFrom` always passes at least the text item it started on, so
224
+ // this advances even when the slice came out empty — which is what stops
225
+ // a zero-length tail from spinning the loop.
226
+ if (!segment.runs.length) {
227
+ index = segment.nextIndex;
228
+ offset = 0;
229
+ continue;
230
+ }
231
+
232
+ // Once nothing ahead can narrow a line — no atomic left, an empty line
233
+ // in hand, and no float at or below this y — the rest of the segment is
234
+ // one layout, every line of it. This is the exit that keeps the loop
235
+ // below from being quadratic on an ordinary paragraph: it runs line by
236
+ // line only while it has to.
237
+ const tailIsPlain =
238
+ segment.nextIndex >= items.length &&
239
+ open.x === 0 &&
240
+ !open.atomics.length &&
241
+ !(options.floats?.intersects(options.startY + y, Infinity) ?? false);
242
+ if (tailIsPlain) {
243
+ const layout = fonts.layout(segment.runs, base, {
244
+ maxWidth: wraps(style) ? Math.max(1, available) : undefined,
245
+ lineHeight: lineHeightMul,
246
+ align,
247
+ direction: style.direction,
248
+ });
249
+ LAYOUT_RUNS.set(layout, segment.runs);
250
+ for (let i = 0; i < layout.lines.length; i += 1) {
251
+ const natural = layout.lines[i];
252
+ const text: LineText = {
253
+ layout,
254
+ layoutLine: i,
255
+ drawX: band.left,
256
+ drawY: y,
257
+ textStart: segment.spans.documentAt(natural.start),
258
+ textEnd: segment.spans.documentAt(natural.end),
259
+ layoutStart: natural.start,
260
+ };
261
+ lines.push({
262
+ x: band.left + natural.x,
263
+ y: y + natural.y,
264
+ width: natural.width,
265
+ height: natural.height,
266
+ baseline: natural.baseline,
267
+ texts: [text],
268
+ textStart: text.textStart,
269
+ textEnd: text.textEnd,
270
+ atomics: [],
271
+ });
272
+ widest = Math.max(widest, natural.width);
273
+ }
274
+ y += layout.height;
275
+ index = segment.nextIndex;
276
+ offset = 0;
277
+ continue;
278
+ }
279
+
280
+ // One line: `maxLines: 1` cuts the layout at the first break and its
281
+ // `truncated` flag answers "did the segment wrap" — so a line costs one
282
+ // layout of one line, not a layout of the whole remaining tail plus a
283
+ // re-cut (which is what an earlier shape paid, per line, beside every
284
+ // float). ntk's shaping memo makes the successive cuts cheap; only the
285
+ // line breaker re-runs.
286
+ const room = Math.max(1, available - open.x);
287
+ const fragment = fonts.layout(segment.runs, base, {
288
+ maxWidth: wraps(style) ? room : undefined,
289
+ lineHeight: lineHeightMul,
290
+ // A fragment that does not start at the line's left edge cannot be
291
+ // aligned by the text layout: the alignment belongs to the whole line,
292
+ // which only this loop can see.
293
+ align: open.x > 0 ? 'left' : align,
294
+ direction: style.direction,
295
+ maxLines: 1,
296
+ });
297
+ LAYOUT_RUNS.set(fragment, segment.runs);
298
+ const first = fragment.lines[0];
299
+ if (!first) {
300
+ index = segment.nextIndex;
301
+ offset = 0;
302
+ continue;
303
+ }
304
+ open.texts.push({
305
+ layout: fragment,
306
+ layoutLine: 0,
307
+ // The layout's own `first.x` carries the alignment offset, so the
308
+ // origin is the band edge plus the cursor — subtracting `first.x`
309
+ // here would left-align a centred line. Mid-line continuations were
310
+ // laid out `left`, where `first.x` is zero and the two agree.
311
+ drawX: band.left + open.x,
312
+ drawY: 0, // filled in by `finishLine`, which is where the top is known
313
+ textStart: segment.spans.documentAt(first.start),
314
+ textEnd: segment.spans.documentAt(first.end),
315
+ layoutStart: first.start,
316
+ });
317
+ open.x += first.width;
318
+ open.left = band.left;
319
+
320
+ if (!fragment.truncated) {
321
+ // It fitted: the cursor stays on this line for whatever comes next.
322
+ //
323
+ // With one correction first. ntk strips a line's trailing whitespace —
324
+ // right at a real line end, wrong here, where the "line" is only a
325
+ // fragment and an atomic follows on the same one: `Name <input>` laid
326
+ // the space out to width zero and the control sat flush against the
327
+ // label (nbsp included; ntk's whitespace set has U+00A0 in it). The
328
+ // stripped advance is measured back and added to the cursor.
329
+ if (segment.nextIndex < items.length) {
330
+ let trailing = '';
331
+ for (let i = segment.runs.length - 1; i >= 0; i -= 1) {
332
+ const text = segment.runs[i].text;
333
+ const m = /[ \t\u00A0]+$/.exec(text);
334
+ if (!m) break;
335
+ trailing = m[0] + trailing;
336
+ if (m[0].length < text.length) break;
337
+ }
338
+ if (trailing) {
339
+ open.x +=
340
+ spaceAdvance(fonts, segment.runs[segment.runs.length - 1]) *
341
+ trailing.length;
342
+ }
343
+ }
344
+ index = segment.nextIndex;
345
+ offset = 0;
346
+ continue;
347
+ }
348
+ close();
349
+ const advanced = advance(items, index, offset, first.end);
350
+ index = advanced.index;
351
+ offset = advanced.offset;
352
+ }
353
+
354
+ if (open.texts.length || open.atomics.length) close();
355
+
356
+ return { lines, height: y, width: widest };
357
+ }
358
+
359
+ const EMPTY: InlineResult = { lines: [], height: 0, width: 0 };
360
+
361
+ /** Append one layout's lines as LineBoxes at an offset; returns the widest. */
362
+ function emitLayout(
363
+ layout: TextLayoutLike,
364
+ spans: SpanMap,
365
+ xOff: number,
366
+ yOff: number,
367
+ lines: LineBox[],
368
+ ): number {
369
+ let widest = 0;
370
+ for (let i = 0; i < layout.lines.length; i += 1) {
371
+ const natural = layout.lines[i];
372
+ const text: LineText = {
373
+ layout,
374
+ layoutLine: i,
375
+ drawX: xOff,
376
+ drawY: yOff,
377
+ textStart: spans.documentAt(natural.start),
378
+ textEnd: spans.documentAt(natural.end),
379
+ layoutStart: natural.start,
380
+ };
381
+ lines.push({
382
+ x: xOff + natural.x,
383
+ y: yOff + natural.y,
384
+ width: natural.width,
385
+ height: natural.height,
386
+ baseline: natural.baseline,
387
+ texts: [text],
388
+ textStart: text.textStart,
389
+ textEnd: text.textEnd,
390
+ atomics: [],
391
+ });
392
+ widest = Math.max(widest, natural.width);
393
+ }
394
+ return widest;
395
+ }
396
+
397
+ /** Chunking kicks in past this much text (with hard breaks in it). The
398
+ * chunk bounds are sized to the *drawing*, not the layout: a chunk is one
399
+ * glyph batch, an expose submits every batch it touches whole, and a strip
400
+ * two lines tall should not pay for five hundred — 64 hard lines is a
401
+ * couple of viewports, measured at well under a millisecond a batch. */
402
+ const CHUNK_TRIGGER_CHARS = 16384;
403
+ const CHUNK_MAX_CHARS = 8192;
404
+ const CHUNK_MAX_HARD_LINES = 64;
405
+
406
+ /**
407
+ * A long hard-broken text — a `<pre>` holding a log, a wall of `<br>`s — laid
408
+ * out as a sequence of layouts split at newline boundaries.
409
+ *
410
+ * Two reasons, and either would suffice. A single `TextLayout` spanning
411
+ * hundreds of thousands of pixels cannot be *drawn*: ntk emits a layout as
412
+ * one glyph batch, X carries the positions as Int16, and the skip guard that
413
+ * keeps that from crashing would keep the whole thing blank instead. And a
414
+ * monolithic layout defeats viewport culling — every paint would hold the
415
+ * one object every line shares. Splitting at hard breaks is exact (line
416
+ * breaking never crosses a required break), so the chunk seams are
417
+ * invisible; each chunk stays a single batch a viewport can keep whole.
418
+ */
419
+ function layoutChunked(
420
+ items: Extract<Item, { kind: 'text' }>[],
421
+ base: Record<string, unknown>,
422
+ style: ComputedStyle,
423
+ width: number,
424
+ lineHeightMul: number,
425
+ align: string,
426
+ fonts: FontsLike,
427
+ ): InlineResult {
428
+ const lines: LineBox[] = [];
429
+ let widest = 0;
430
+ let y = 0;
431
+
432
+ let chunkRuns: TextRun[] = [];
433
+ let chunkSpans = new SpanMap();
434
+ let chars = 0;
435
+ let hardLines = 0;
436
+
437
+ const flush = (): void => {
438
+ if (!chunkRuns.length) return;
439
+ const layout = fonts.layout(chunkRuns, base, {
440
+ maxWidth: wraps(style) ? width : undefined,
441
+ lineHeight: lineHeightMul,
442
+ align,
443
+ direction: style.direction,
444
+ });
445
+ LAYOUT_RUNS.set(layout, chunkRuns);
446
+ widest = Math.max(widest, emitLayout(layout, chunkSpans, 0, y, lines));
447
+ y += layout.height;
448
+ chunkRuns = [];
449
+ chunkSpans = new SpanMap();
450
+ chars = 0;
451
+ hardLines = 0;
452
+ };
453
+
454
+ for (const item of items) {
455
+ let text = item.run.text;
456
+ let docStart = item.box.textStart;
457
+ while (text.length) {
458
+ // Scan up to the budgets, remembering the last newline: the split has
459
+ // to land just after one for the chunking to be exact.
460
+ let i = 0;
461
+ let lastBreak = -1;
462
+ let lines2 = hardLines;
463
+ let taken = chars;
464
+ while (
465
+ i < text.length &&
466
+ taken < CHUNK_MAX_CHARS &&
467
+ lines2 < CHUNK_MAX_HARD_LINES
468
+ ) {
469
+ if (text.charCodeAt(i) === 10) {
470
+ lines2 += 1;
471
+ lastBreak = i;
472
+ }
473
+ i += 1;
474
+ taken += 1;
475
+ }
476
+ if (i >= text.length) {
477
+ // the rest of this run fits the open chunk
478
+ chunkRuns.push(
479
+ text === item.run.text ? item.run : { ...item.run, text },
480
+ );
481
+ chunkSpans.add(docStart, text.length);
482
+ chars = taken;
483
+ hardLines = lines2;
484
+ break;
485
+ }
486
+ if (lastBreak < 0) {
487
+ if (chunkRuns.length) {
488
+ // no break inside the budget: close the chunk, retry with room
489
+ flush();
490
+ continue;
491
+ }
492
+ // a single unbroken stretch larger than a whole chunk: take it to
493
+ // its next newline (or its end) and let the overflow guard judge it
494
+ const next = text.indexOf('\n', i);
495
+ const end = next < 0 ? text.length : next + 1;
496
+ chunkRuns.push({ ...item.run, text: text.slice(0, end) });
497
+ chunkSpans.add(docStart, end);
498
+ flush();
499
+ docStart += end;
500
+ text = text.slice(end);
501
+ continue;
502
+ }
503
+ const cut = lastBreak + 1;
504
+ chunkRuns.push({ ...item.run, text: text.slice(0, cut) });
505
+ chunkSpans.add(docStart, cut);
506
+ flush();
507
+ docStart += cut;
508
+ text = text.slice(cut);
509
+ }
510
+ }
511
+ flush();
512
+ return { lines, height: y, width: widest };
513
+ }
514
+
515
+ // --- the line under construction --------------------------------------------
516
+
517
+ interface OpenLine {
518
+ /** How much of the line is used, from `left`. */
519
+ x: number;
520
+ left: number;
521
+ texts: LineText[];
522
+ atomics: AtomicPlacement[];
523
+ }
524
+
525
+ function openLine(indent: number): OpenLine {
526
+ return { x: indent, left: 0, texts: [], atomics: [] };
527
+ }
528
+
529
+ function finishLine(open: OpenLine, y: number): LineBox | null {
530
+ if (!open.texts.length && !open.atomics.length) return null;
531
+ let ascent = 0;
532
+ let descent = 0;
533
+ let height = 0;
534
+ for (const text of open.texts) {
535
+ const natural = text.layout.lines[text.layoutLine];
536
+ ascent = Math.max(ascent, natural.baseline);
537
+ descent = Math.max(descent, natural.height - natural.baseline);
538
+ height = Math.max(height, natural.height);
539
+ }
540
+ for (const placed of open.atomics) {
541
+ const h =
542
+ placed.box.height + placed.box.marginTop + placed.box.marginBottom;
543
+ const va = placed.box.style.verticalAlign;
544
+ if (va === 'top' || va === 'bottom' || va === 'middle')
545
+ height = Math.max(height, h);
546
+ else ascent = Math.max(ascent, h);
547
+ }
548
+ height = Math.max(height, ascent + descent);
549
+ const baseline = Math.max(ascent, (height - ascent - descent) / 2 + ascent);
550
+
551
+ let textStart = Infinity;
552
+ let textEnd = 0;
553
+ for (const text of open.texts) {
554
+ textStart = Math.min(textStart, text.textStart);
555
+ textEnd = Math.max(textEnd, text.textEnd);
556
+ }
557
+ const line: LineBox = {
558
+ x: open.left,
559
+ y,
560
+ width: open.x,
561
+ height,
562
+ baseline,
563
+ texts: open.texts,
564
+ textStart: Number.isFinite(textStart) ? textStart : 0,
565
+ textEnd,
566
+ atomics: open.atomics,
567
+ };
568
+ for (const placed of open.atomics)
569
+ placed.y = y + alignAtomic(placed.box, line);
570
+ // Every fragment on this line shares the line's baseline, whatever its own
571
+ // layout thinks: that is what makes a small `<sup>` beside body text sit on
572
+ // the same baseline rather than on its own.
573
+ for (const text of open.texts) {
574
+ const natural = text.layout.lines[text.layoutLine];
575
+ text.drawY = y + baseline - natural.baseline - natural.y;
576
+ }
577
+ return line;
578
+ }
579
+
580
+ /** Where an atomic's top edge sits, relative to the line box top. */
581
+ function alignAtomic(box: Box, line: LineBox): number {
582
+ const h = box.height + box.marginTop + box.marginBottom;
583
+ switch (box.style.verticalAlign) {
584
+ case 'top':
585
+ return 0;
586
+ case 'bottom':
587
+ return line.height - h;
588
+ case 'middle':
589
+ return (line.height - h) / 2;
590
+ case 'sub':
591
+ return line.baseline - h + line.height * 0.1;
592
+ case 'super':
593
+ return line.baseline - h - line.height * 0.25;
594
+ default:
595
+ if (typeof box.style.verticalAlign === 'number') {
596
+ return line.baseline - h - box.style.verticalAlign;
597
+ }
598
+ return line.baseline - h;
599
+ }
600
+ }
601
+
602
+ // --- gathering --------------------------------------------------------------
603
+
604
+ /** Flatten an inline subtree into a stream of runs, atomics and breaks. */
605
+ function collect(box: Box, out: Item[]): void {
606
+ for (const child of box.children) {
607
+ if (child.outOfFlow || child.isFloat) continue;
608
+ switch (child.kind) {
609
+ case 'text':
610
+ if (child.text) {
611
+ out.push({
612
+ kind: 'text',
613
+ run: runFor(child.text, child.style, child.el),
614
+ box: child,
615
+ length: child.text.length,
616
+ });
617
+ }
618
+ break;
619
+ case 'break':
620
+ // A `<br>` is a newline *character* in the stream, not a control
621
+ // item: ntk's breaker treats `\n` as a required break, gives the
622
+ // blank line between two of them real font metrics, and both paths
623
+ // — the one-layout fast path and the line-at-a-time one — then
624
+ // handle it identically. (An earlier shape kept breaks as their own
625
+ // item kind and the fast path, which only reads text items, dropped
626
+ // them: `a<br>b` rendered as one line.) The box builder gave the
627
+ // break its slot in the document index, so the span map lines up.
628
+ out.push({
629
+ kind: 'text',
630
+ run: {
631
+ text: '\n',
632
+ family: child.style.fontFamily,
633
+ size: child.style.fontSize,
634
+ },
635
+ box: child,
636
+ length: 1,
637
+ });
638
+ break;
639
+ case 'inline':
640
+ collect(child, out);
641
+ break;
642
+ default:
643
+ // Everything else that reached an inline context is inline-level and
644
+ // atomic: a replaced element, an `inline-block`, an `inline-table`.
645
+ out.push({ kind: 'atomic', box: child });
646
+ break;
647
+ }
648
+ }
649
+ }
650
+
651
+ /** The `TextRun` one styled piece of text becomes. */
652
+ function runFor(
653
+ text: string,
654
+ style: ComputedStyle,
655
+ owner: Element | null,
656
+ ): TextRun {
657
+ // ntk hands unknown span fields back on the laid-out runs untouched, which
658
+ // is how the element reaches the paint and hit-test passes without a
659
+ // parallel structure to keep in step.
660
+ const run: TextRun & { element?: Element } = {
661
+ text,
662
+ family: style.fontFamily,
663
+ size: style.fontSize,
664
+ weight: style.fontWeight,
665
+ style: style.fontStyle === 'normal' ? 'normal' : 'italic',
666
+ color: style.color,
667
+ };
668
+ // An inline background fills the line box rather than hugging the ink:
669
+ // `<span style="background: yellow">` is a highlighter, and two adjacent
670
+ // highlighted spans must not leave a seam between them. That is exactly
671
+ // what richtext's `bgFill: 'line'` was added for.
672
+ if (!isTransparent(style.backgroundColor)) {
673
+ run.bg = inkColor(style.backgroundColor as string, style.color);
674
+ run.bgFill = 'line';
675
+ }
676
+ if (owner) run.element = owner;
677
+ if (style.textDecorationLine === 'underline') {
678
+ run.underline = inkColor(
679
+ style.textDecorationColor ?? 'currentColor',
680
+ style.color,
681
+ );
682
+ // CSS's five rule styles and SGR 4's five are the same set under two
683
+ // names; richtext speaks SGR's, so `solid` is `single` and `wavy` is
684
+ // `curly`. The other three are spelled identically.
685
+ run.underlineStyle =
686
+ style.textDecorationStyle === 'wavy'
687
+ ? 'curly'
688
+ : style.textDecorationStyle === 'solid'
689
+ ? 'single'
690
+ : style.textDecorationStyle;
691
+ } else if (style.textDecorationLine === 'line-through') {
692
+ run.strike = inkColor(
693
+ style.textDecorationColor ?? 'currentColor',
694
+ style.color,
695
+ );
696
+ }
697
+ return run;
698
+ }
699
+
700
+ /**
701
+ * Maps a code-unit offset in text handed to `TextLayout` back to its offset
702
+ * in the document index. The two differ because a layout covers one segment
703
+ * of the stream while the document index covers all of it.
704
+ */
705
+ class SpanMap {
706
+ private _laid: number[] = [];
707
+ private _doc: number[] = [];
708
+ laidOut = 0;
709
+
710
+ add(documentStart: number, length: number): void {
711
+ this._laid.push(this.laidOut);
712
+ this._doc.push(documentStart);
713
+ this.laidOut += length;
714
+ }
715
+
716
+ documentAt(offset: number): number {
717
+ const laid = this._laid;
718
+ if (!laid.length) return 0;
719
+ let lo = 0;
720
+ let hi = laid.length - 1;
721
+ while (lo < hi) {
722
+ const mid = (lo + hi + 1) >> 1;
723
+ if (laid[mid] <= offset) lo = mid;
724
+ else hi = mid - 1;
725
+ }
726
+ return this._doc[lo] + (offset - laid[lo]);
727
+ }
728
+ }
729
+
730
+ interface Segment {
731
+ runs: TextRun[];
732
+ spans: SpanMap;
733
+ nextIndex: number;
734
+ }
735
+
736
+ /** The maximal run of text items from `(index, offset)` to the next atomic. */
737
+ function segmentFrom(items: Item[], index: number, offset: number): Segment {
738
+ const runs: TextRun[] = [];
739
+ const spans = new SpanMap();
740
+ let i = index;
741
+ let skip = offset;
742
+ for (; i < items.length; i += 1) {
743
+ const item = items[i];
744
+ if (item.kind !== 'text') break;
745
+ const text = skip > 0 ? item.run.text.slice(skip) : item.run.text;
746
+ if (text) {
747
+ spans.add(item.box.textStart + skip, text.length);
748
+ runs.push(skip > 0 ? { ...item.run, text } : item.run);
749
+ }
750
+ skip = 0;
751
+ }
752
+ return { runs, spans, nextIndex: i };
753
+ }
754
+
755
+ /** Move `(index, offset)` forward by `consumed` code units of text. */
756
+ function advance(
757
+ items: Item[],
758
+ index: number,
759
+ offset: number,
760
+ consumed: number,
761
+ ): { index: number; offset: number } {
762
+ let i = index;
763
+ let skip = offset;
764
+ let left = consumed;
765
+ while (i < items.length) {
766
+ const item = items[i];
767
+ if (item.kind !== 'text') break;
768
+ const remaining = item.length - skip;
769
+ if (left < remaining) return { index: i, offset: skip + left };
770
+ left -= remaining;
771
+ skip = 0;
772
+ i += 1;
773
+ }
774
+ return { index: i, offset: 0 };
775
+ }
776
+
777
+ /**
778
+ * One space's advance in a run's style, measured as the difference between
779
+ * `x x` and `xx` — ntk strips a lone trailing space from a line, so it
780
+ * cannot be measured directly. Cached per font manager per style; the
781
+ * measurement itself hits ntk's shaping memo.
782
+ */
783
+ const SPACE_ADVANCE = new WeakMap<FontsLike, Map<string, number>>();
784
+
785
+ function spaceAdvance(fonts: FontsLike, run: TextRun): number {
786
+ let cache = SPACE_ADVANCE.get(fonts);
787
+ if (!cache) {
788
+ cache = new Map();
789
+ SPACE_ADVANCE.set(fonts, cache);
790
+ }
791
+ const key = `${run.family}|${run.size}|${run.weight}|${run.style}`;
792
+ const hit = cache.get(key);
793
+ if (hit !== undefined) return hit;
794
+ const style = {
795
+ family: run.family,
796
+ size: run.size,
797
+ weight: run.weight,
798
+ style: run.style,
799
+ };
800
+ const measure = (text: string): number =>
801
+ fonts.layout([{ ...style, text }], style, {}).lines[0]?.width ?? 0;
802
+ const advance = Math.max(0, measure('x x') - measure('xx'));
803
+ if (cache.size > 64) cache.clear();
804
+ cache.set(key, advance);
805
+ return advance;
806
+ }
807
+
808
+ // --- style questions --------------------------------------------------------
809
+
810
+ function wraps(style: ComputedStyle): boolean {
811
+ return style.whiteSpace !== 'nowrap' && style.whiteSpace !== 'pre';
812
+ }
813
+
814
+ function alignFor(style: ComputedStyle): string {
815
+ // ntk has no justification; `start` is closer than a silent left on an RTL
816
+ // paragraph, and closer than a ragged-right lie about what was drawn.
817
+ return style.textAlign === 'justify' ? 'start' : style.textAlign;
818
+ }
819
+
820
+ function indentOf(style: ComputedStyle, width: number): number {
821
+ const indent = style.textIndent;
822
+ if (typeof indent === 'number') return indent;
823
+ if (indent === 'auto') return 0;
824
+ return Number.isFinite(width) ? (indent.pct / 100) * width : 0;
825
+ }
826
+
827
+ /**
828
+ * CSS's `line-height` expressed as ntk's multiplier.
829
+ *
830
+ * ntk multiplies the **font's natural line height** (metrics, line gap
831
+ * included); CSS's number form multiplies the **font size**. Converting here
832
+ * rather than passing the CSS number through is the difference between
833
+ * `line-height: 1.5` meaning 1.5 × 16px and it meaning 1.5 × 19px, which is
834
+ * a visibly looser document than the author asked for.
835
+ */
836
+ function lineHeightMultiplier(fonts: FontsLike, style: ComputedStyle): number {
837
+ if (style.lineHeight === 'normal') return 1;
838
+ const target = style.lineHeightIsLength
839
+ ? (style.lineHeight as number)
840
+ : (style.lineHeight as number) * style.fontSize;
841
+ const natural = naturalLineHeight(fonts, style);
842
+ if (!natural) return 1;
843
+ return Math.max(0.1, target / natural);
844
+ }
845
+
846
+ function naturalLineHeight(fonts: FontsLike, style: ComputedStyle): number {
847
+ try {
848
+ const font = fonts.match(style.fontFamily, {
849
+ size: style.fontSize,
850
+ weight: style.fontWeight,
851
+ style: style.fontStyle,
852
+ });
853
+ return font.metrics(style.fontSize).lineHeight;
854
+ } catch {
855
+ return style.fontSize * 1.2;
856
+ }
857
+ }
858
+
859
+ function bandAt(
860
+ options: InlineOptions,
861
+ y: number,
862
+ height: number,
863
+ ): { left: number; right: number } {
864
+ if (!options.floats) return { left: 0, right: options.width };
865
+ const band = options.floats.bandAt(options.startY + y, height);
866
+ return {
867
+ left: Math.max(0, band.left - options.originX),
868
+ right: Math.min(options.width, band.right - options.originX),
869
+ };
870
+ }