nastech-tui 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (424) hide show
  1. package/.prettierrc +11 -0
  2. package/README.md +346 -0
  3. package/eslint.config.mjs +111 -0
  4. package/package.json +51 -0
  5. package/packages/nastech-ink/ambient.d.ts +83 -0
  6. package/packages/nastech-ink/index.d.ts +40 -0
  7. package/packages/nastech-ink/index.js +1 -0
  8. package/packages/nastech-ink/nastech-ink/ambient.d.ts +83 -0
  9. package/packages/nastech-ink/nastech-ink/index.d.ts +40 -0
  10. package/packages/nastech-ink/nastech-ink/index.js +1 -0
  11. package/packages/nastech-ink/nastech-ink/package.json +54 -0
  12. package/packages/nastech-ink/nastech-ink/src/bootstrap/state.ts +9 -0
  13. package/packages/nastech-ink/nastech-ink/src/entry-exports.ts +32 -0
  14. package/packages/nastech-ink/nastech-ink/src/hooks/use-stderr.ts +15 -0
  15. package/packages/nastech-ink/nastech-ink/src/hooks/use-stdout.ts +15 -0
  16. package/packages/nastech-ink/nastech-ink/src/ink/Ansi.tsx +435 -0
  17. package/packages/nastech-ink/nastech-ink/src/ink/app-mouse.test.ts +123 -0
  18. package/packages/nastech-ink/nastech-ink/src/ink/bidi.ts +145 -0
  19. package/packages/nastech-ink/nastech-ink/src/ink/cache-eviction.ts +45 -0
  20. package/packages/nastech-ink/nastech-ink/src/ink/clearTerminal.ts +68 -0
  21. package/packages/nastech-ink/nastech-ink/src/ink/colorize.test.ts +60 -0
  22. package/packages/nastech-ink/nastech-ink/src/ink/colorize.ts +277 -0
  23. package/packages/nastech-ink/nastech-ink/src/ink/components/AlternateScreen.tsx +133 -0
  24. package/packages/nastech-ink/nastech-ink/src/ink/components/App.tsx +830 -0
  25. package/packages/nastech-ink/nastech-ink/src/ink/components/AppContext.ts +20 -0
  26. package/packages/nastech-ink/nastech-ink/src/ink/components/Box.tsx +294 -0
  27. package/packages/nastech-ink/nastech-ink/src/ink/components/Button.tsx +236 -0
  28. package/packages/nastech-ink/nastech-ink/src/ink/components/ClockContext.tsx +133 -0
  29. package/packages/nastech-ink/nastech-ink/src/ink/components/CursorAdvanceContext.ts +35 -0
  30. package/packages/nastech-ink/nastech-ink/src/ink/components/CursorDeclarationContext.ts +28 -0
  31. package/packages/nastech-ink/nastech-ink/src/ink/components/ErrorOverview.tsx +130 -0
  32. package/packages/nastech-ink/nastech-ink/src/ink/components/Link.tsx +38 -0
  33. package/packages/nastech-ink/nastech-ink/src/ink/components/Newline.tsx +43 -0
  34. package/packages/nastech-ink/nastech-ink/src/ink/components/NoSelect.tsx +73 -0
  35. package/packages/nastech-ink/nastech-ink/src/ink/components/RawAnsi.tsx +61 -0
  36. package/packages/nastech-ink/nastech-ink/src/ink/components/ScrollBox.tsx +290 -0
  37. package/packages/nastech-ink/nastech-ink/src/ink/components/Spacer.tsx +23 -0
  38. package/packages/nastech-ink/nastech-ink/src/ink/components/StdinContext.ts +25 -0
  39. package/packages/nastech-ink/nastech-ink/src/ink/components/TerminalFocusContext.tsx +63 -0
  40. package/packages/nastech-ink/nastech-ink/src/ink/components/TerminalSizeContext.tsx +7 -0
  41. package/packages/nastech-ink/nastech-ink/src/ink/components/Text.test.ts +38 -0
  42. package/packages/nastech-ink/nastech-ink/src/ink/components/Text.tsx +336 -0
  43. package/packages/nastech-ink/nastech-ink/src/ink/constants.ts +6 -0
  44. package/packages/nastech-ink/nastech-ink/src/ink/cursor.ts +5 -0
  45. package/packages/nastech-ink/nastech-ink/src/ink/devtools.ts +2 -0
  46. package/packages/nastech-ink/nastech-ink/src/ink/dom.ts +495 -0
  47. package/packages/nastech-ink/nastech-ink/src/ink/events/click-event.ts +38 -0
  48. package/packages/nastech-ink/nastech-ink/src/ink/events/cmd-shortcuts.test.ts +65 -0
  49. package/packages/nastech-ink/nastech-ink/src/ink/events/dispatcher.ts +242 -0
  50. package/packages/nastech-ink/nastech-ink/src/ink/events/emitter.ts +40 -0
  51. package/packages/nastech-ink/nastech-ink/src/ink/events/event-handlers.ts +84 -0
  52. package/packages/nastech-ink/nastech-ink/src/ink/events/event.ts +11 -0
  53. package/packages/nastech-ink/nastech-ink/src/ink/events/focus-event.ts +18 -0
  54. package/packages/nastech-ink/nastech-ink/src/ink/events/input-event.ts +176 -0
  55. package/packages/nastech-ink/nastech-ink/src/ink/events/keyboard-event.ts +57 -0
  56. package/packages/nastech-ink/nastech-ink/src/ink/events/mouse-event.ts +18 -0
  57. package/packages/nastech-ink/nastech-ink/src/ink/events/paste-event.ts +10 -0
  58. package/packages/nastech-ink/nastech-ink/src/ink/events/resize-event.ts +12 -0
  59. package/packages/nastech-ink/nastech-ink/src/ink/events/terminal-event.ts +107 -0
  60. package/packages/nastech-ink/nastech-ink/src/ink/events/terminal-focus-event.ts +19 -0
  61. package/packages/nastech-ink/nastech-ink/src/ink/focus.ts +219 -0
  62. package/packages/nastech-ink/nastech-ink/src/ink/frame.ts +124 -0
  63. package/packages/nastech-ink/nastech-ink/src/ink/get-max-width.ts +27 -0
  64. package/packages/nastech-ink/nastech-ink/src/ink/global.d.ts +1 -0
  65. package/packages/nastech-ink/nastech-ink/src/ink/hit-test.test.ts +38 -0
  66. package/packages/nastech-ink/nastech-ink/src/ink/hit-test.ts +224 -0
  67. package/packages/nastech-ink/nastech-ink/src/ink/hooks/use-animation-frame.ts +62 -0
  68. package/packages/nastech-ink/nastech-ink/src/ink/hooks/use-app.ts +9 -0
  69. package/packages/nastech-ink/nastech-ink/src/ink/hooks/use-cursor-advance.ts +33 -0
  70. package/packages/nastech-ink/nastech-ink/src/ink/hooks/use-declared-cursor.ts +75 -0
  71. package/packages/nastech-ink/nastech-ink/src/ink/hooks/use-external-process.ts +27 -0
  72. package/packages/nastech-ink/nastech-ink/src/ink/hooks/use-input.ts +95 -0
  73. package/packages/nastech-ink/nastech-ink/src/ink/hooks/use-interval.ts +71 -0
  74. package/packages/nastech-ink/package.json +57 -0
  75. package/packages/nastech-ink/src/bootstrap/state.ts +9 -0
  76. package/packages/nastech-ink/src/entry-exports.ts +32 -0
  77. package/packages/nastech-ink/src/hooks/use-stderr.ts +15 -0
  78. package/packages/nastech-ink/src/hooks/use-stdout.ts +15 -0
  79. package/packages/nastech-ink/src/ink/Ansi.tsx +435 -0
  80. package/packages/nastech-ink/src/ink/app-mouse.test.ts +123 -0
  81. package/packages/nastech-ink/src/ink/app-rawmode-mouse.test.ts +91 -0
  82. package/packages/nastech-ink/src/ink/bidi.ts +145 -0
  83. package/packages/nastech-ink/src/ink/cache-eviction.ts +45 -0
  84. package/packages/nastech-ink/src/ink/clearTerminal.ts +68 -0
  85. package/packages/nastech-ink/src/ink/colorize.test.ts +60 -0
  86. package/packages/nastech-ink/src/ink/colorize.ts +277 -0
  87. package/packages/nastech-ink/src/ink/components/AlternateScreen.tsx +133 -0
  88. package/packages/nastech-ink/src/ink/components/App.tsx +855 -0
  89. package/packages/nastech-ink/src/ink/components/AppContext.ts +20 -0
  90. package/packages/nastech-ink/src/ink/components/Box.tsx +294 -0
  91. package/packages/nastech-ink/src/ink/components/Button.tsx +236 -0
  92. package/packages/nastech-ink/src/ink/components/ClockContext.tsx +133 -0
  93. package/packages/nastech-ink/src/ink/components/CursorAdvanceContext.ts +35 -0
  94. package/packages/nastech-ink/src/ink/components/CursorDeclarationContext.ts +28 -0
  95. package/packages/nastech-ink/src/ink/components/ErrorOverview.tsx +130 -0
  96. package/packages/nastech-ink/src/ink/components/Link.tsx +38 -0
  97. package/packages/nastech-ink/src/ink/components/Newline.tsx +43 -0
  98. package/packages/nastech-ink/src/ink/components/NoSelect.tsx +73 -0
  99. package/packages/nastech-ink/src/ink/components/RawAnsi.tsx +61 -0
  100. package/packages/nastech-ink/src/ink/components/ScrollBox.tsx +290 -0
  101. package/packages/nastech-ink/src/ink/components/Spacer.tsx +23 -0
  102. package/packages/nastech-ink/src/ink/components/StdinContext.ts +25 -0
  103. package/packages/nastech-ink/src/ink/components/TerminalFocusContext.tsx +63 -0
  104. package/packages/nastech-ink/src/ink/components/TerminalSizeContext.tsx +7 -0
  105. package/packages/nastech-ink/src/ink/components/Text.test.ts +38 -0
  106. package/packages/nastech-ink/src/ink/components/Text.tsx +336 -0
  107. package/packages/nastech-ink/src/ink/constants.ts +6 -0
  108. package/packages/nastech-ink/src/ink/cursor.ts +5 -0
  109. package/packages/nastech-ink/src/ink/devtools.ts +2 -0
  110. package/packages/nastech-ink/src/ink/dom.ts +495 -0
  111. package/packages/nastech-ink/src/ink/events/click-event.ts +38 -0
  112. package/packages/nastech-ink/src/ink/events/cmd-shortcuts.test.ts +65 -0
  113. package/packages/nastech-ink/src/ink/events/dispatcher.ts +242 -0
  114. package/packages/nastech-ink/src/ink/events/emitter.ts +40 -0
  115. package/packages/nastech-ink/src/ink/events/event-handlers.ts +84 -0
  116. package/packages/nastech-ink/src/ink/events/event.ts +11 -0
  117. package/packages/nastech-ink/src/ink/events/focus-event.ts +18 -0
  118. package/packages/nastech-ink/src/ink/events/input-event.ts +176 -0
  119. package/packages/nastech-ink/src/ink/events/keyboard-event.ts +57 -0
  120. package/packages/nastech-ink/src/ink/events/mouse-event.ts +18 -0
  121. package/packages/nastech-ink/src/ink/events/paste-event.ts +10 -0
  122. package/packages/nastech-ink/src/ink/events/resize-event.ts +12 -0
  123. package/packages/nastech-ink/src/ink/events/terminal-event.ts +107 -0
  124. package/packages/nastech-ink/src/ink/events/terminal-focus-event.ts +19 -0
  125. package/packages/nastech-ink/src/ink/focus.ts +219 -0
  126. package/packages/nastech-ink/src/ink/frame.ts +124 -0
  127. package/packages/nastech-ink/src/ink/get-max-width.ts +27 -0
  128. package/packages/nastech-ink/src/ink/global.d.ts +1 -0
  129. package/packages/nastech-ink/src/ink/hit-test.test.ts +38 -0
  130. package/packages/nastech-ink/src/ink/hit-test.ts +224 -0
  131. package/packages/nastech-ink/src/ink/hooks/use-animation-frame.ts +62 -0
  132. package/packages/nastech-ink/src/ink/hooks/use-app.ts +9 -0
  133. package/packages/nastech-ink/src/ink/hooks/use-cursor-advance.ts +33 -0
  134. package/packages/nastech-ink/src/ink/hooks/use-declared-cursor.ts +75 -0
  135. package/packages/nastech-ink/src/ink/hooks/use-external-process.ts +27 -0
  136. package/packages/nastech-ink/src/ink/hooks/use-input.ts +95 -0
  137. package/packages/nastech-ink/src/ink/hooks/use-interval.ts +71 -0
  138. package/packages/nastech-ink/src/ink/hooks/use-search-highlight.ts +56 -0
  139. package/packages/nastech-ink/src/ink/hooks/use-selection.ts +101 -0
  140. package/packages/nastech-ink/src/ink/hooks/use-stdin.ts +9 -0
  141. package/packages/nastech-ink/src/ink/hooks/use-tab-status.ts +71 -0
  142. package/packages/nastech-ink/src/ink/hooks/use-terminal-focus.ts +18 -0
  143. package/packages/nastech-ink/src/ink/hooks/use-terminal-title.ts +34 -0
  144. package/packages/nastech-ink/src/ink/hooks/use-terminal-viewport.ts +100 -0
  145. package/packages/nastech-ink/src/ink/hyperlinkHover.ts +52 -0
  146. package/packages/nastech-ink/src/ink/ink-cursor-advance.test.ts +234 -0
  147. package/packages/nastech-ink/src/ink/ink-resize.test.ts +50 -0
  148. package/packages/nastech-ink/src/ink/ink.tsx +2705 -0
  149. package/packages/nastech-ink/src/ink/instances.ts +10 -0
  150. package/packages/nastech-ink/src/ink/layout/engine.ts +6 -0
  151. package/packages/nastech-ink/src/ink/layout/geometry.ts +98 -0
  152. package/packages/nastech-ink/src/ink/layout/node.ts +145 -0
  153. package/packages/nastech-ink/src/ink/layout/yoga.ts +313 -0
  154. package/packages/nastech-ink/src/ink/line-width-cache.ts +38 -0
  155. package/packages/nastech-ink/src/ink/log-update.test.ts +223 -0
  156. package/packages/nastech-ink/src/ink/log-update.ts +752 -0
  157. package/packages/nastech-ink/src/ink/lru.ts +14 -0
  158. package/packages/nastech-ink/src/ink/measure-element.ts +23 -0
  159. package/packages/nastech-ink/src/ink/measure-text.ts +50 -0
  160. package/packages/nastech-ink/src/ink/node-cache.ts +53 -0
  161. package/packages/nastech-ink/src/ink/optimizer.ts +99 -0
  162. package/packages/nastech-ink/src/ink/output.ts +845 -0
  163. package/packages/nastech-ink/src/ink/parse-keypress.test.ts +133 -0
  164. package/packages/nastech-ink/src/ink/parse-keypress.ts +848 -0
  165. package/packages/nastech-ink/src/ink/reconciler.ts +382 -0
  166. package/packages/nastech-ink/src/ink/render-border.ts +206 -0
  167. package/packages/nastech-ink/src/ink/render-node-to-output.ts +1582 -0
  168. package/packages/nastech-ink/src/ink/render-to-screen.ts +236 -0
  169. package/packages/nastech-ink/src/ink/renderer.ts +169 -0
  170. package/packages/nastech-ink/src/ink/root.ts +204 -0
  171. package/packages/nastech-ink/src/ink/screen.ts +1590 -0
  172. package/packages/nastech-ink/src/ink/searchHighlight.ts +91 -0
  173. package/packages/nastech-ink/src/ink/selection.test.ts +82 -0
  174. package/packages/nastech-ink/src/ink/selection.ts +1143 -0
  175. package/packages/nastech-ink/src/ink/squash-text-nodes.ts +74 -0
  176. package/packages/nastech-ink/src/ink/stringWidth.ts +341 -0
  177. package/packages/nastech-ink/src/ink/styles.ts +750 -0
  178. package/packages/nastech-ink/src/ink/supports-hyperlinks.ts +51 -0
  179. package/packages/nastech-ink/src/ink/tabstops.ts +44 -0
  180. package/packages/nastech-ink/src/ink/terminal-focus-state.ts +52 -0
  181. package/packages/nastech-ink/src/ink/terminal-querier.ts +222 -0
  182. package/packages/nastech-ink/src/ink/terminal.test.ts +15 -0
  183. package/packages/nastech-ink/src/ink/terminal.ts +299 -0
  184. package/packages/nastech-ink/src/ink/termio/ansi.ts +75 -0
  185. package/packages/nastech-ink/src/ink/termio/csi.ts +334 -0
  186. package/packages/nastech-ink/src/ink/termio/dec.ts +99 -0
  187. package/packages/nastech-ink/src/ink/termio/esc.ts +69 -0
  188. package/packages/nastech-ink/src/ink/termio/osc.test.ts +191 -0
  189. package/packages/nastech-ink/src/ink/termio/osc.ts +724 -0
  190. package/packages/nastech-ink/src/ink/termio/parser.ts +467 -0
  191. package/packages/nastech-ink/src/ink/termio/sgr.ts +362 -0
  192. package/packages/nastech-ink/src/ink/termio/tokenize.test.ts +185 -0
  193. package/packages/nastech-ink/src/ink/termio/tokenize.ts +350 -0
  194. package/packages/nastech-ink/src/ink/termio/types.ts +230 -0
  195. package/packages/nastech-ink/src/ink/termio.ts +42 -0
  196. package/packages/nastech-ink/src/ink/useTerminalNotification.ts +110 -0
  197. package/packages/nastech-ink/src/ink/warn.ts +15 -0
  198. package/packages/nastech-ink/src/ink/widest-line.ts +22 -0
  199. package/packages/nastech-ink/src/ink/wrap-text.test.ts +17 -0
  200. package/packages/nastech-ink/src/ink/wrap-text.ts +144 -0
  201. package/packages/nastech-ink/src/ink/wrapAnsi.ts +13 -0
  202. package/packages/nastech-ink/src/native-ts/yoga-layout/enums.ts +112 -0
  203. package/packages/nastech-ink/src/native-ts/yoga-layout/index.ts +2326 -0
  204. package/packages/nastech-ink/src/utils/debug.ts +6 -0
  205. package/packages/nastech-ink/src/utils/earlyInput.ts +131 -0
  206. package/packages/nastech-ink/src/utils/env.ts +66 -0
  207. package/packages/nastech-ink/src/utils/envUtils.ts +13 -0
  208. package/packages/nastech-ink/src/utils/execFileNoThrow.test.ts +146 -0
  209. package/packages/nastech-ink/src/utils/execFileNoThrow.ts +115 -0
  210. package/packages/nastech-ink/src/utils/fullscreen.ts +3 -0
  211. package/packages/nastech-ink/src/utils/intl.ts +87 -0
  212. package/packages/nastech-ink/src/utils/log.ts +7 -0
  213. package/packages/nastech-ink/src/utils/semver.ts +57 -0
  214. package/packages/nastech-ink/src/utils/sliceAnsi.ts +106 -0
  215. package/packages/nastech-ink/text-input.d.ts +2 -0
  216. package/packages/nastech-ink/text-input.js +1 -0
  217. package/scripts/build.mjs +61 -0
  218. package/scripts/profile-tui.mjs +121 -0
  219. package/src/__tests__/activeSessionSwitcher.test.ts +157 -0
  220. package/src/__tests__/appChromeStatusRule.test.tsx +84 -0
  221. package/src/__tests__/appChromeStatusRuleDevCredits.test.tsx +73 -0
  222. package/src/__tests__/approvalAction.test.ts +50 -0
  223. package/src/__tests__/asCommandDispatch.test.ts +27 -0
  224. package/src/__tests__/blockLayout.test.ts +122 -0
  225. package/src/__tests__/clipboard.test.ts +369 -0
  226. package/src/__tests__/constants.test.ts +53 -0
  227. package/src/__tests__/createGatewayEventHandler.test.ts +1091 -0
  228. package/src/__tests__/createSlashHandler.test.ts +822 -0
  229. package/src/__tests__/creditsCommand.test.ts +144 -0
  230. package/src/__tests__/cursorDriftRegression.test.ts +114 -0
  231. package/src/__tests__/details.test.ts +115 -0
  232. package/src/__tests__/emoji.test.ts +64 -0
  233. package/src/__tests__/externalLink.test.ts +144 -0
  234. package/src/__tests__/forceTruecolor.test.ts +191 -0
  235. package/src/__tests__/gatewayClient.test.ts +394 -0
  236. package/src/__tests__/gatewayRecovery.test.ts +47 -0
  237. package/src/__tests__/markdown.test.ts +331 -0
  238. package/src/__tests__/mathUnicode.test.ts +293 -0
  239. package/src/__tests__/memoryMonitor.test.ts +102 -0
  240. package/src/__tests__/messageLine.test.ts +19 -0
  241. package/src/__tests__/messages.test.ts +92 -0
  242. package/src/__tests__/orchestratorPromptSession.test.ts +64 -0
  243. package/src/__tests__/osc52.test.ts +67 -0
  244. package/src/__tests__/parentLog.test.ts +75 -0
  245. package/src/__tests__/paths.test.ts +70 -0
  246. package/src/__tests__/platform.test.ts +556 -0
  247. package/src/__tests__/precisionWheel.test.ts +44 -0
  248. package/src/__tests__/prompt.test.ts +31 -0
  249. package/src/__tests__/providers.test.ts +65 -0
  250. package/src/__tests__/reasoning.test.ts +76 -0
  251. package/src/__tests__/rpc.test.ts +27 -0
  252. package/src/__tests__/scroll.test.ts +99 -0
  253. package/src/__tests__/slashParity.test.ts +123 -0
  254. package/src/__tests__/spawnHistoryStore.test.ts +46 -0
  255. package/src/__tests__/stateIsolation.test.ts +46 -0
  256. package/src/__tests__/statusBarTicker.test.ts +18 -0
  257. package/src/__tests__/statusRule.test.ts +32 -0
  258. package/src/__tests__/streamingMarkdown.test.ts +121 -0
  259. package/src/__tests__/subagentTree.test.ts +407 -0
  260. package/src/__tests__/syntax.test.ts +45 -0
  261. package/src/__tests__/terminalModes.test.ts +39 -0
  262. package/src/__tests__/terminalParity.test.ts +77 -0
  263. package/src/__tests__/terminalSetup.test.ts +386 -0
  264. package/src/__tests__/termux.test.ts +35 -0
  265. package/src/__tests__/termuxComposerLayout.test.ts +40 -0
  266. package/src/__tests__/text.test.ts +233 -0
  267. package/src/__tests__/textInputBurstInput.test.ts +40 -0
  268. package/src/__tests__/textInputCursorSourceOfTruth.test.ts +50 -0
  269. package/src/__tests__/textInputFastEcho.test.ts +200 -0
  270. package/src/__tests__/textInputLineNav.test.ts +55 -0
  271. package/src/__tests__/textInputPassThrough.test.ts +59 -0
  272. package/src/__tests__/textInputRightClick.test.ts +48 -0
  273. package/src/__tests__/textInputWrap.test.ts +151 -0
  274. package/src/__tests__/theme.test.ts +311 -0
  275. package/src/__tests__/turnControllerNotice.test.ts +43 -0
  276. package/src/__tests__/turnStore.test.ts +66 -0
  277. package/src/__tests__/useCompletion.test.ts +35 -0
  278. package/src/__tests__/useComposerState.test.ts +59 -0
  279. package/src/__tests__/useConfigSync.test.ts +460 -0
  280. package/src/__tests__/useInputHandlers.test.ts +77 -0
  281. package/src/__tests__/useQueue.test.ts +28 -0
  282. package/src/__tests__/useSessionLifecycle.test.ts +60 -0
  283. package/src/__tests__/useVirtualHistoryHeights.test.ts +39 -0
  284. package/src/__tests__/viewport.test.ts +58 -0
  285. package/src/__tests__/viewportStore.test.ts +85 -0
  286. package/src/__tests__/virtualHeights.test.ts +96 -0
  287. package/src/__tests__/virtualHistoryClamp.test.ts +19 -0
  288. package/src/__tests__/virtualHistoryOffsetCache.test.ts +282 -0
  289. package/src/__tests__/wheelAccel.test.ts +138 -0
  290. package/src/app/createGatewayEventHandler.ts +833 -0
  291. package/src/app/createSlashHandler.ts +130 -0
  292. package/src/app/delegationStore.ts +77 -0
  293. package/src/app/gatewayContext.tsx +19 -0
  294. package/src/app/gatewayRecovery.ts +35 -0
  295. package/src/app/inputSelectionStore.ts +15 -0
  296. package/src/app/interfaces.ts +394 -0
  297. package/src/app/overlayStore.ts +53 -0
  298. package/src/app/scroll.ts +71 -0
  299. package/src/app/setupHandoff.ts +54 -0
  300. package/src/app/slash/commands/core.ts +648 -0
  301. package/src/app/slash/commands/credits.ts +57 -0
  302. package/src/app/slash/commands/debug.ts +48 -0
  303. package/src/app/slash/commands/ops.ts +717 -0
  304. package/src/app/slash/commands/session.ts +554 -0
  305. package/src/app/slash/commands/setup.ts +20 -0
  306. package/src/app/slash/registry.ts +20 -0
  307. package/src/app/slash/types.ts +21 -0
  308. package/src/app/spawnHistoryStore.ts +159 -0
  309. package/src/app/turnController.ts +866 -0
  310. package/src/app/turnStore.ts +85 -0
  311. package/src/app/uiStore.ts +44 -0
  312. package/src/app/useComposerState.ts +367 -0
  313. package/src/app/useConfigSync.ts +288 -0
  314. package/src/app/useInputHandlers.ts +576 -0
  315. package/src/app/useLongRunToolCharms.ts +69 -0
  316. package/src/app/useMainApp.ts +1039 -0
  317. package/src/app/useSessionLifecycle.ts +366 -0
  318. package/src/app/useSubmission.ts +429 -0
  319. package/src/app.tsx +25 -0
  320. package/src/banner.ts +93 -0
  321. package/src/components/activeSessionSwitcher.tsx +635 -0
  322. package/src/components/agentsOverlay.tsx +1073 -0
  323. package/src/components/appChrome.tsx +554 -0
  324. package/src/components/appLayout.tsx +444 -0
  325. package/src/components/appOverlays.tsx +254 -0
  326. package/src/components/branding.tsx +466 -0
  327. package/src/components/fpsOverlay.tsx +30 -0
  328. package/src/components/helpHint.tsx +73 -0
  329. package/src/components/markdown.tsx +1119 -0
  330. package/src/components/maskedPrompt.tsx +34 -0
  331. package/src/components/messageLine.tsx +237 -0
  332. package/src/components/modelPicker.tsx +527 -0
  333. package/src/components/overlayControls.tsx +50 -0
  334. package/src/components/pluginsHub.tsx +238 -0
  335. package/src/components/prompts.tsx +276 -0
  336. package/src/components/queuedMessages.tsx +64 -0
  337. package/src/components/sessionPicker.tsx +227 -0
  338. package/src/components/skillsHub.tsx +308 -0
  339. package/src/components/streamingAssistant.tsx +110 -0
  340. package/src/components/streamingMarkdown.tsx +174 -0
  341. package/src/components/textInput.tsx +1340 -0
  342. package/src/components/themed.tsx +30 -0
  343. package/src/components/thinking.tsx +1224 -0
  344. package/src/components/todoPanel.tsx +93 -0
  345. package/src/config/env.ts +64 -0
  346. package/src/config/limits.ts +13 -0
  347. package/src/config/timing.ts +6 -0
  348. package/src/content/charms.ts +1 -0
  349. package/src/content/faces.ts +17 -0
  350. package/src/content/fortunes.ts +30 -0
  351. package/src/content/hotkeys.ts +37 -0
  352. package/src/content/placeholders.ts +13 -0
  353. package/src/content/setup.ts +17 -0
  354. package/src/content/verbs.ts +38 -0
  355. package/src/domain/blockLayout.ts +146 -0
  356. package/src/domain/details.ts +76 -0
  357. package/src/domain/messages.ts +91 -0
  358. package/src/domain/paths.ts +16 -0
  359. package/src/domain/providers.ts +11 -0
  360. package/src/domain/roles.ts +9 -0
  361. package/src/domain/slash.ts +10 -0
  362. package/src/domain/usage.ts +3 -0
  363. package/src/domain/viewport.ts +51 -0
  364. package/src/entry.tsx +104 -0
  365. package/src/gatewayClient.ts +730 -0
  366. package/src/gatewayTypes.ts +568 -0
  367. package/src/hooks/useCompletion.ts +112 -0
  368. package/src/hooks/useGitBranch.ts +72 -0
  369. package/src/hooks/useInputHistory.ts +11 -0
  370. package/src/hooks/useQueue.ts +76 -0
  371. package/src/hooks/useVirtualHistory.ts +554 -0
  372. package/src/lib/circularBuffer.ts +48 -0
  373. package/src/lib/clipboard.ts +182 -0
  374. package/src/lib/editor.test.ts +74 -0
  375. package/src/lib/editor.ts +47 -0
  376. package/src/lib/emoji.ts +55 -0
  377. package/src/lib/externalCli.ts +16 -0
  378. package/src/lib/externalLink.ts +435 -0
  379. package/src/lib/forceTruecolor.ts +60 -0
  380. package/src/lib/fpsStore.ts +51 -0
  381. package/src/lib/fuzzy.test.ts +109 -0
  382. package/src/lib/fuzzy.ts +177 -0
  383. package/src/lib/gracefulExit.ts +47 -0
  384. package/src/lib/history.ts +82 -0
  385. package/src/lib/inputMetrics.ts +203 -0
  386. package/src/lib/liveProgress.test.ts +116 -0
  387. package/src/lib/liveProgress.ts +79 -0
  388. package/src/lib/mathUnicode.ts +770 -0
  389. package/src/lib/memory.test.ts +155 -0
  390. package/src/lib/memory.ts +188 -0
  391. package/src/lib/memoryMonitor.ts +109 -0
  392. package/src/lib/messages.test.ts +29 -0
  393. package/src/lib/messages.ts +8 -0
  394. package/src/lib/openExternalUrl.test.ts +217 -0
  395. package/src/lib/openExternalUrl.ts +158 -0
  396. package/src/lib/osc52.ts +73 -0
  397. package/src/lib/parentLog.ts +57 -0
  398. package/src/lib/perfPane.tsx +107 -0
  399. package/src/lib/platform.ts +409 -0
  400. package/src/lib/precisionWheel.ts +48 -0
  401. package/src/lib/prompt.ts +35 -0
  402. package/src/lib/reasoning.ts +55 -0
  403. package/src/lib/rpc.ts +41 -0
  404. package/src/lib/subagentTree.ts +355 -0
  405. package/src/lib/syntax.ts +117 -0
  406. package/src/lib/terminalModes.ts +51 -0
  407. package/src/lib/terminalParity.ts +78 -0
  408. package/src/lib/terminalSetup.ts +444 -0
  409. package/src/lib/termux.ts +29 -0
  410. package/src/lib/text.test.ts +18 -0
  411. package/src/lib/text.ts +339 -0
  412. package/src/lib/todo.test.ts +21 -0
  413. package/src/lib/todo.ts +9 -0
  414. package/src/lib/viewportStore.ts +124 -0
  415. package/src/lib/virtualHeights.ts +145 -0
  416. package/src/lib/wheelAccel.ts +190 -0
  417. package/src/protocol/interpolation.ts +3 -0
  418. package/src/protocol/paste.ts +1 -0
  419. package/src/theme.ts +589 -0
  420. package/src/types/nastech-ink.d.ts +176 -0
  421. package/src/types.ts +212 -0
  422. package/tsconfig.build.json +9 -0
  423. package/tsconfig.json +19 -0
  424. package/vitest.config.ts +7 -0
@@ -0,0 +1,2326 @@
1
+ import {
2
+ Align,
3
+ BoxSizing,
4
+ Dimension,
5
+ Direction,
6
+ Display,
7
+ Edge,
8
+ Errata,
9
+ ExperimentalFeature,
10
+ FlexDirection,
11
+ Gutter,
12
+ Justify,
13
+ MeasureMode,
14
+ Overflow,
15
+ PositionType,
16
+ Unit,
17
+ Wrap
18
+ } from './enums.js'
19
+ export {
20
+ Align,
21
+ BoxSizing,
22
+ Dimension,
23
+ Direction,
24
+ Display,
25
+ Edge,
26
+ Errata,
27
+ ExperimentalFeature,
28
+ FlexDirection,
29
+ Gutter,
30
+ Justify,
31
+ MeasureMode,
32
+ Overflow,
33
+ PositionType,
34
+ Unit,
35
+ Wrap
36
+ }
37
+ export type Value = {
38
+ unit: Unit
39
+ value: number
40
+ }
41
+ const UNDEFINED_VALUE: Value = { unit: Unit.Undefined, value: NaN }
42
+ const AUTO_VALUE: Value = { unit: Unit.Auto, value: NaN }
43
+
44
+ function pointValue(v: number): Value {
45
+ return { unit: Unit.Point, value: v }
46
+ }
47
+
48
+ function percentValue(v: number): Value {
49
+ return { unit: Unit.Percent, value: v }
50
+ }
51
+
52
+ function resolveValue(v: Value, ownerSize: number): number {
53
+ switch (v.unit) {
54
+ case Unit.Point:
55
+ return v.value
56
+
57
+ case Unit.Percent:
58
+ return isNaN(ownerSize) ? NaN : (v.value * ownerSize) / 100
59
+
60
+ default:
61
+ return NaN
62
+ }
63
+ }
64
+
65
+ function isDefined(n: number): boolean {
66
+ return !isNaN(n)
67
+ }
68
+
69
+ function sameFloat(a: number, b: number): boolean {
70
+ return a === b || (a !== a && b !== b)
71
+ }
72
+
73
+ type Layout = {
74
+ left: number
75
+ top: number
76
+ width: number
77
+ height: number
78
+ border: [number, number, number, number]
79
+ padding: [number, number, number, number]
80
+ margin: [number, number, number, number]
81
+ }
82
+ type Style = {
83
+ direction: Direction
84
+ flexDirection: FlexDirection
85
+ justifyContent: Justify
86
+ alignItems: Align
87
+ alignSelf: Align
88
+ alignContent: Align
89
+ flexWrap: Wrap
90
+ overflow: Overflow
91
+ display: Display
92
+ positionType: PositionType
93
+ flexGrow: number
94
+ flexShrink: number
95
+ flexBasis: Value
96
+ margin: Value[]
97
+ padding: Value[]
98
+ border: Value[]
99
+ position: Value[]
100
+ gap: Value[]
101
+ width: Value
102
+ height: Value
103
+ minWidth: Value
104
+ minHeight: Value
105
+ maxWidth: Value
106
+ maxHeight: Value
107
+ }
108
+
109
+ function defaultStyle(): Style {
110
+ return {
111
+ direction: Direction.Inherit,
112
+ flexDirection: FlexDirection.Column,
113
+ justifyContent: Justify.FlexStart,
114
+ alignItems: Align.Stretch,
115
+ alignSelf: Align.Auto,
116
+ alignContent: Align.FlexStart,
117
+ flexWrap: Wrap.NoWrap,
118
+ overflow: Overflow.Visible,
119
+ display: Display.Flex,
120
+ positionType: PositionType.Relative,
121
+ flexGrow: 0,
122
+ flexShrink: 0,
123
+ flexBasis: AUTO_VALUE,
124
+ margin: new Array(9).fill(UNDEFINED_VALUE),
125
+ padding: new Array(9).fill(UNDEFINED_VALUE),
126
+ border: new Array(9).fill(UNDEFINED_VALUE),
127
+ position: new Array(9).fill(UNDEFINED_VALUE),
128
+ gap: new Array(3).fill(UNDEFINED_VALUE),
129
+ width: AUTO_VALUE,
130
+ height: AUTO_VALUE,
131
+ minWidth: UNDEFINED_VALUE,
132
+ minHeight: UNDEFINED_VALUE,
133
+ maxWidth: UNDEFINED_VALUE,
134
+ maxHeight: UNDEFINED_VALUE
135
+ }
136
+ }
137
+
138
+ const EDGE_LEFT = 0
139
+ const EDGE_TOP = 1
140
+ const EDGE_RIGHT = 2
141
+ const EDGE_BOTTOM = 3
142
+
143
+ function resolveEdge(edges: Value[], physicalEdge: number, ownerSize: number, allowAuto = false): number {
144
+ let v = edges[physicalEdge]!
145
+
146
+ if (v.unit === Unit.Undefined) {
147
+ if (physicalEdge === EDGE_LEFT || physicalEdge === EDGE_RIGHT) {
148
+ v = edges[Edge.Horizontal]!
149
+ } else {
150
+ v = edges[Edge.Vertical]!
151
+ }
152
+ }
153
+
154
+ if (v.unit === Unit.Undefined) {
155
+ v = edges[Edge.All]!
156
+ }
157
+
158
+ if (v.unit === Unit.Undefined) {
159
+ if (physicalEdge === EDGE_LEFT) {
160
+ v = edges[Edge.Start]!
161
+ }
162
+
163
+ if (physicalEdge === EDGE_RIGHT) {
164
+ v = edges[Edge.End]!
165
+ }
166
+ }
167
+
168
+ if (v.unit === Unit.Undefined) {
169
+ return 0
170
+ }
171
+
172
+ if (v.unit === Unit.Auto) {
173
+ return allowAuto ? NaN : 0
174
+ }
175
+
176
+ return resolveValue(v, ownerSize)
177
+ }
178
+
179
+ function resolveEdgeRaw(edges: Value[], physicalEdge: number): Value {
180
+ let v = edges[physicalEdge]!
181
+
182
+ if (v.unit === Unit.Undefined) {
183
+ if (physicalEdge === EDGE_LEFT || physicalEdge === EDGE_RIGHT) {
184
+ v = edges[Edge.Horizontal]!
185
+ } else {
186
+ v = edges[Edge.Vertical]!
187
+ }
188
+ }
189
+
190
+ if (v.unit === Unit.Undefined) {
191
+ v = edges[Edge.All]!
192
+ }
193
+
194
+ if (v.unit === Unit.Undefined) {
195
+ if (physicalEdge === EDGE_LEFT) {
196
+ v = edges[Edge.Start]!
197
+ }
198
+
199
+ if (physicalEdge === EDGE_RIGHT) {
200
+ v = edges[Edge.End]!
201
+ }
202
+ }
203
+
204
+ return v
205
+ }
206
+
207
+ function isMarginAuto(edges: Value[], physicalEdge: number): boolean {
208
+ return resolveEdgeRaw(edges, physicalEdge).unit === Unit.Auto
209
+ }
210
+
211
+ function hasAnyAutoEdge(edges: Value[]): boolean {
212
+ for (let i = 0; i < 9; i++) {
213
+ if (edges[i]!.unit === 3) {
214
+ return true
215
+ }
216
+ }
217
+
218
+ return false
219
+ }
220
+
221
+ function hasAnyDefinedEdge(edges: Value[]): boolean {
222
+ for (let i = 0; i < 9; i++) {
223
+ if (edges[i]!.unit !== 0) {
224
+ return true
225
+ }
226
+ }
227
+
228
+ return false
229
+ }
230
+
231
+ function resolveEdges4Into(edges: Value[], ownerSize: number, out: [number, number, number, number]): void {
232
+ const eH = edges[6]!
233
+ const eV = edges[7]!
234
+ const eA = edges[8]!
235
+ const eS = edges[4]!
236
+ const eE = edges[5]!
237
+ const pctDenom = isNaN(ownerSize) ? NaN : ownerSize / 100
238
+ let v = edges[0]!
239
+
240
+ if (v.unit === 0) {
241
+ v = eH
242
+ }
243
+
244
+ if (v.unit === 0) {
245
+ v = eA
246
+ }
247
+
248
+ if (v.unit === 0) {
249
+ v = eS
250
+ }
251
+
252
+ out[0] = v.unit === 1 ? v.value : v.unit === 2 ? v.value * pctDenom : 0
253
+ v = edges[1]!
254
+
255
+ if (v.unit === 0) {
256
+ v = eV
257
+ }
258
+
259
+ if (v.unit === 0) {
260
+ v = eA
261
+ }
262
+
263
+ out[1] = v.unit === 1 ? v.value : v.unit === 2 ? v.value * pctDenom : 0
264
+ v = edges[2]!
265
+
266
+ if (v.unit === 0) {
267
+ v = eH
268
+ }
269
+
270
+ if (v.unit === 0) {
271
+ v = eA
272
+ }
273
+
274
+ if (v.unit === 0) {
275
+ v = eE
276
+ }
277
+
278
+ out[2] = v.unit === 1 ? v.value : v.unit === 2 ? v.value * pctDenom : 0
279
+ v = edges[3]!
280
+
281
+ if (v.unit === 0) {
282
+ v = eV
283
+ }
284
+
285
+ if (v.unit === 0) {
286
+ v = eA
287
+ }
288
+
289
+ out[3] = v.unit === 1 ? v.value : v.unit === 2 ? v.value * pctDenom : 0
290
+ }
291
+
292
+ function isRow(dir: FlexDirection): boolean {
293
+ return dir === FlexDirection.Row || dir === FlexDirection.RowReverse
294
+ }
295
+
296
+ function isReverse(dir: FlexDirection): boolean {
297
+ return dir === FlexDirection.RowReverse || dir === FlexDirection.ColumnReverse
298
+ }
299
+
300
+ function crossAxis(dir: FlexDirection): FlexDirection {
301
+ return isRow(dir) ? FlexDirection.Column : FlexDirection.Row
302
+ }
303
+
304
+ function leadingEdge(dir: FlexDirection): number {
305
+ switch (dir) {
306
+ case FlexDirection.Row:
307
+ return EDGE_LEFT
308
+
309
+ case FlexDirection.RowReverse:
310
+ return EDGE_RIGHT
311
+
312
+ case FlexDirection.Column:
313
+ return EDGE_TOP
314
+
315
+ case FlexDirection.ColumnReverse:
316
+ return EDGE_BOTTOM
317
+ }
318
+ }
319
+
320
+ function trailingEdge(dir: FlexDirection): number {
321
+ switch (dir) {
322
+ case FlexDirection.Row:
323
+ return EDGE_RIGHT
324
+
325
+ case FlexDirection.RowReverse:
326
+ return EDGE_LEFT
327
+
328
+ case FlexDirection.Column:
329
+ return EDGE_BOTTOM
330
+
331
+ case FlexDirection.ColumnReverse:
332
+ return EDGE_TOP
333
+ }
334
+ }
335
+
336
+ export type MeasureFunction = (
337
+ width: number,
338
+ widthMode: MeasureMode,
339
+ height: number,
340
+ heightMode: MeasureMode
341
+ ) => {
342
+ width: number
343
+ height: number
344
+ }
345
+ export type Size = {
346
+ width: number
347
+ height: number
348
+ }
349
+ export type Config = {
350
+ pointScaleFactor: number
351
+ errata: Errata
352
+ useWebDefaults: boolean
353
+ free(): void
354
+ isExperimentalFeatureEnabled(_: ExperimentalFeature): boolean
355
+ setExperimentalFeatureEnabled(_: ExperimentalFeature, __: boolean): void
356
+ setPointScaleFactor(factor: number): void
357
+ getErrata(): Errata
358
+ setErrata(errata: Errata): void
359
+ setUseWebDefaults(v: boolean): void
360
+ }
361
+
362
+ function createConfig(): Config {
363
+ const config: Config = {
364
+ pointScaleFactor: 1,
365
+ errata: Errata.None,
366
+ useWebDefaults: false,
367
+ free() {},
368
+ isExperimentalFeatureEnabled() {
369
+ return false
370
+ },
371
+ setExperimentalFeatureEnabled() {},
372
+ setPointScaleFactor(f) {
373
+ config.pointScaleFactor = f
374
+ },
375
+ getErrata() {
376
+ return config.errata
377
+ },
378
+ setErrata(e) {
379
+ config.errata = e
380
+ },
381
+ setUseWebDefaults(v) {
382
+ config.useWebDefaults = v
383
+ }
384
+ }
385
+
386
+ return config
387
+ }
388
+
389
+ export class Node {
390
+ style: Style
391
+ layout: Layout
392
+ parent: Node | null
393
+ children: Node[]
394
+ measureFunc: MeasureFunction | null
395
+ config: Config
396
+ isDirty_: boolean
397
+ isReferenceBaseline_: boolean
398
+ _flexBasis = 0
399
+ _mainSize = 0
400
+ _crossSize = 0
401
+ _lineIndex = 0
402
+ _hasAutoMargin = false
403
+ _hasPosition = false
404
+ _hasPadding = false
405
+ _hasBorder = false
406
+ _hasMargin = false
407
+ _lW = NaN
408
+ _lH = NaN
409
+ _lWM: MeasureMode = 0
410
+ _lHM: MeasureMode = 0
411
+ _lOW = NaN
412
+ _lOH = NaN
413
+ _lFW = false
414
+ _lFH = false
415
+ _lOutW = NaN
416
+ _lOutH = NaN
417
+ _hasL = false
418
+ _mW = NaN
419
+ _mH = NaN
420
+ _mWM: MeasureMode = 0
421
+ _mHM: MeasureMode = 0
422
+ _mOW = NaN
423
+ _mOH = NaN
424
+ _mOutW = NaN
425
+ _mOutH = NaN
426
+ _hasM = false
427
+ _fbBasis = NaN
428
+ _fbOwnerW = NaN
429
+ _fbOwnerH = NaN
430
+ _fbAvailMain = NaN
431
+ _fbAvailCross = NaN
432
+ _fbCrossMode: MeasureMode = 0
433
+ _fbGen = -1
434
+ _cIn: Float64Array | null = null
435
+ _cOut: Float64Array | null = null
436
+ _cGen = -1
437
+ _cN = 0
438
+ _cWr = 0
439
+ constructor(config?: Config) {
440
+ this.style = defaultStyle()
441
+ this.layout = {
442
+ left: 0,
443
+ top: 0,
444
+ width: 0,
445
+ height: 0,
446
+ border: [0, 0, 0, 0],
447
+ padding: [0, 0, 0, 0],
448
+ margin: [0, 0, 0, 0]
449
+ }
450
+ this.parent = null
451
+ this.children = []
452
+ this.measureFunc = null
453
+ this.config = config ?? DEFAULT_CONFIG
454
+ this.isDirty_ = true
455
+ this.isReferenceBaseline_ = false
456
+ _yogaLiveNodes++
457
+ }
458
+ insertChild(child: Node, index: number): void {
459
+ child.parent = this
460
+ this.children.splice(index, 0, child)
461
+ this.markDirty()
462
+ }
463
+ removeChild(child: Node): void {
464
+ const idx = this.children.indexOf(child)
465
+
466
+ if (idx >= 0) {
467
+ this.children.splice(idx, 1)
468
+ child.parent = null
469
+ this.markDirty()
470
+ }
471
+ }
472
+ getChild(index: number): Node {
473
+ return this.children[index]!
474
+ }
475
+ getChildCount(): number {
476
+ return this.children.length
477
+ }
478
+ getParent(): Node | null {
479
+ return this.parent
480
+ }
481
+ free(): void {
482
+ this.parent = null
483
+ this.children = []
484
+ this.measureFunc = null
485
+ this._cIn = null
486
+ this._cOut = null
487
+ _yogaLiveNodes--
488
+ }
489
+ freeRecursive(): void {
490
+ for (const c of this.children) {
491
+ c.freeRecursive()
492
+ }
493
+
494
+ this.free()
495
+ }
496
+ reset(): void {
497
+ this.style = defaultStyle()
498
+ this.children = []
499
+ this.parent = null
500
+ this.measureFunc = null
501
+ this.isDirty_ = true
502
+ this._hasAutoMargin = false
503
+ this._hasPosition = false
504
+ this._hasPadding = false
505
+ this._hasBorder = false
506
+ this._hasMargin = false
507
+ this._hasL = false
508
+ this._hasM = false
509
+ this._cN = 0
510
+ this._cWr = 0
511
+ this._fbBasis = NaN
512
+ }
513
+ markDirty(): void {
514
+ this.isDirty_ = true
515
+
516
+ if (this.parent && !this.parent.isDirty_) {
517
+ this.parent.markDirty()
518
+ }
519
+ }
520
+ isDirty(): boolean {
521
+ return this.isDirty_
522
+ }
523
+ hasNewLayout(): boolean {
524
+ return true
525
+ }
526
+ markLayoutSeen(): void {}
527
+ setMeasureFunc(fn: MeasureFunction | null): void {
528
+ this.measureFunc = fn
529
+ this.markDirty()
530
+ }
531
+ unsetMeasureFunc(): void {
532
+ this.measureFunc = null
533
+ this.markDirty()
534
+ }
535
+ getComputedLeft(): number {
536
+ return this.layout.left
537
+ }
538
+ getComputedTop(): number {
539
+ return this.layout.top
540
+ }
541
+ getComputedWidth(): number {
542
+ return this.layout.width
543
+ }
544
+ getComputedHeight(): number {
545
+ return this.layout.height
546
+ }
547
+ getComputedRight(): number {
548
+ const p = this.parent
549
+
550
+ return p ? p.layout.width - this.layout.left - this.layout.width : 0
551
+ }
552
+ getComputedBottom(): number {
553
+ const p = this.parent
554
+
555
+ return p ? p.layout.height - this.layout.top - this.layout.height : 0
556
+ }
557
+ getComputedLayout(): {
558
+ left: number
559
+ top: number
560
+ right: number
561
+ bottom: number
562
+ width: number
563
+ height: number
564
+ } {
565
+ return {
566
+ left: this.layout.left,
567
+ top: this.layout.top,
568
+ right: this.getComputedRight(),
569
+ bottom: this.getComputedBottom(),
570
+ width: this.layout.width,
571
+ height: this.layout.height
572
+ }
573
+ }
574
+ getComputedBorder(edge: Edge): number {
575
+ return this.layout.border[physicalEdge(edge)]!
576
+ }
577
+ getComputedPadding(edge: Edge): number {
578
+ return this.layout.padding[physicalEdge(edge)]!
579
+ }
580
+ getComputedMargin(edge: Edge): number {
581
+ return this.layout.margin[physicalEdge(edge)]!
582
+ }
583
+ setWidth(v: number | 'auto' | string | undefined): void {
584
+ this.style.width = parseDimension(v)
585
+ this.markDirty()
586
+ }
587
+ setWidthPercent(v: number): void {
588
+ this.style.width = percentValue(v)
589
+ this.markDirty()
590
+ }
591
+ setWidthAuto(): void {
592
+ this.style.width = AUTO_VALUE
593
+ this.markDirty()
594
+ }
595
+ setHeight(v: number | 'auto' | string | undefined): void {
596
+ this.style.height = parseDimension(v)
597
+ this.markDirty()
598
+ }
599
+ setHeightPercent(v: number): void {
600
+ this.style.height = percentValue(v)
601
+ this.markDirty()
602
+ }
603
+ setHeightAuto(): void {
604
+ this.style.height = AUTO_VALUE
605
+ this.markDirty()
606
+ }
607
+ setMinWidth(v: number | string | undefined): void {
608
+ this.style.minWidth = parseDimension(v)
609
+ this.markDirty()
610
+ }
611
+ setMinWidthPercent(v: number): void {
612
+ this.style.minWidth = percentValue(v)
613
+ this.markDirty()
614
+ }
615
+ setMinHeight(v: number | string | undefined): void {
616
+ this.style.minHeight = parseDimension(v)
617
+ this.markDirty()
618
+ }
619
+ setMinHeightPercent(v: number): void {
620
+ this.style.minHeight = percentValue(v)
621
+ this.markDirty()
622
+ }
623
+ setMaxWidth(v: number | string | undefined): void {
624
+ this.style.maxWidth = parseDimension(v)
625
+ this.markDirty()
626
+ }
627
+ setMaxWidthPercent(v: number): void {
628
+ this.style.maxWidth = percentValue(v)
629
+ this.markDirty()
630
+ }
631
+ setMaxHeight(v: number | string | undefined): void {
632
+ this.style.maxHeight = parseDimension(v)
633
+ this.markDirty()
634
+ }
635
+ setMaxHeightPercent(v: number): void {
636
+ this.style.maxHeight = percentValue(v)
637
+ this.markDirty()
638
+ }
639
+ setFlexDirection(dir: FlexDirection): void {
640
+ this.style.flexDirection = dir
641
+ this.markDirty()
642
+ }
643
+ setFlexGrow(v: number | undefined): void {
644
+ this.style.flexGrow = v ?? 0
645
+ this.markDirty()
646
+ }
647
+ setFlexShrink(v: number | undefined): void {
648
+ this.style.flexShrink = v ?? 0
649
+ this.markDirty()
650
+ }
651
+ setFlex(v: number | undefined): void {
652
+ if (v === undefined || isNaN(v)) {
653
+ this.style.flexGrow = 0
654
+ this.style.flexShrink = 0
655
+ } else if (v > 0) {
656
+ this.style.flexGrow = v
657
+ this.style.flexShrink = 1
658
+ this.style.flexBasis = pointValue(0)
659
+ } else if (v < 0) {
660
+ this.style.flexGrow = 0
661
+ this.style.flexShrink = -v
662
+ } else {
663
+ this.style.flexGrow = 0
664
+ this.style.flexShrink = 0
665
+ }
666
+
667
+ this.markDirty()
668
+ }
669
+ setFlexBasis(v: number | 'auto' | string | undefined): void {
670
+ this.style.flexBasis = parseDimension(v)
671
+ this.markDirty()
672
+ }
673
+ setFlexBasisPercent(v: number): void {
674
+ this.style.flexBasis = percentValue(v)
675
+ this.markDirty()
676
+ }
677
+ setFlexBasisAuto(): void {
678
+ this.style.flexBasis = AUTO_VALUE
679
+ this.markDirty()
680
+ }
681
+ setFlexWrap(wrap: Wrap): void {
682
+ this.style.flexWrap = wrap
683
+ this.markDirty()
684
+ }
685
+ setAlignItems(a: Align): void {
686
+ this.style.alignItems = a
687
+ this.markDirty()
688
+ }
689
+ setAlignSelf(a: Align): void {
690
+ this.style.alignSelf = a
691
+ this.markDirty()
692
+ }
693
+ setAlignContent(a: Align): void {
694
+ this.style.alignContent = a
695
+ this.markDirty()
696
+ }
697
+ setJustifyContent(j: Justify): void {
698
+ this.style.justifyContent = j
699
+ this.markDirty()
700
+ }
701
+ setDisplay(d: Display): void {
702
+ this.style.display = d
703
+ this.markDirty()
704
+ }
705
+ getDisplay(): Display {
706
+ return this.style.display
707
+ }
708
+ setPositionType(t: PositionType): void {
709
+ this.style.positionType = t
710
+ this.markDirty()
711
+ }
712
+ setPosition(edge: Edge, v: number | string | undefined): void {
713
+ this.style.position[edge] = parseDimension(v)
714
+ this._hasPosition = hasAnyDefinedEdge(this.style.position)
715
+ this.markDirty()
716
+ }
717
+ setPositionPercent(edge: Edge, v: number): void {
718
+ this.style.position[edge] = percentValue(v)
719
+ this._hasPosition = true
720
+ this.markDirty()
721
+ }
722
+ setPositionAuto(edge: Edge): void {
723
+ this.style.position[edge] = AUTO_VALUE
724
+ this._hasPosition = true
725
+ this.markDirty()
726
+ }
727
+ setOverflow(o: Overflow): void {
728
+ this.style.overflow = o
729
+ this.markDirty()
730
+ }
731
+ setDirection(d: Direction): void {
732
+ this.style.direction = d
733
+ this.markDirty()
734
+ }
735
+ setBoxSizing(_: BoxSizing): void {}
736
+ setMargin(edge: Edge, v: number | 'auto' | string | undefined): void {
737
+ const val = parseDimension(v)
738
+ this.style.margin[edge] = val
739
+
740
+ if (val.unit === Unit.Auto) {
741
+ this._hasAutoMargin = true
742
+ } else {
743
+ this._hasAutoMargin = hasAnyAutoEdge(this.style.margin)
744
+ }
745
+
746
+ this._hasMargin = this._hasAutoMargin || hasAnyDefinedEdge(this.style.margin)
747
+ this.markDirty()
748
+ }
749
+ setMarginPercent(edge: Edge, v: number): void {
750
+ this.style.margin[edge] = percentValue(v)
751
+ this._hasAutoMargin = hasAnyAutoEdge(this.style.margin)
752
+ this._hasMargin = true
753
+ this.markDirty()
754
+ }
755
+ setMarginAuto(edge: Edge): void {
756
+ this.style.margin[edge] = AUTO_VALUE
757
+ this._hasAutoMargin = true
758
+ this._hasMargin = true
759
+ this.markDirty()
760
+ }
761
+ setPadding(edge: Edge, v: number | string | undefined): void {
762
+ this.style.padding[edge] = parseDimension(v)
763
+ this._hasPadding = hasAnyDefinedEdge(this.style.padding)
764
+ this.markDirty()
765
+ }
766
+ setPaddingPercent(edge: Edge, v: number): void {
767
+ this.style.padding[edge] = percentValue(v)
768
+ this._hasPadding = true
769
+ this.markDirty()
770
+ }
771
+ setBorder(edge: Edge, v: number | undefined): void {
772
+ this.style.border[edge] = v === undefined ? UNDEFINED_VALUE : pointValue(v)
773
+ this._hasBorder = hasAnyDefinedEdge(this.style.border)
774
+ this.markDirty()
775
+ }
776
+ setGap(gutter: Gutter, v: number | string | undefined): void {
777
+ this.style.gap[gutter] = parseDimension(v)
778
+ this.markDirty()
779
+ }
780
+ setGapPercent(gutter: Gutter, v: number): void {
781
+ this.style.gap[gutter] = percentValue(v)
782
+ this.markDirty()
783
+ }
784
+ getFlexDirection(): FlexDirection {
785
+ return this.style.flexDirection
786
+ }
787
+ getJustifyContent(): Justify {
788
+ return this.style.justifyContent
789
+ }
790
+ getAlignItems(): Align {
791
+ return this.style.alignItems
792
+ }
793
+ getAlignSelf(): Align {
794
+ return this.style.alignSelf
795
+ }
796
+ getAlignContent(): Align {
797
+ return this.style.alignContent
798
+ }
799
+ getFlexGrow(): number {
800
+ return this.style.flexGrow
801
+ }
802
+ getFlexShrink(): number {
803
+ return this.style.flexShrink
804
+ }
805
+ getFlexBasis(): Value {
806
+ return this.style.flexBasis
807
+ }
808
+ getFlexWrap(): Wrap {
809
+ return this.style.flexWrap
810
+ }
811
+ getWidth(): Value {
812
+ return this.style.width
813
+ }
814
+ getHeight(): Value {
815
+ return this.style.height
816
+ }
817
+ getOverflow(): Overflow {
818
+ return this.style.overflow
819
+ }
820
+ getPositionType(): PositionType {
821
+ return this.style.positionType
822
+ }
823
+ getDirection(): Direction {
824
+ return this.style.direction
825
+ }
826
+ copyStyle(_: Node): void {}
827
+ setDirtiedFunc(_: unknown): void {}
828
+ unsetDirtiedFunc(): void {}
829
+ setIsReferenceBaseline(v: boolean): void {
830
+ this.isReferenceBaseline_ = v
831
+ this.markDirty()
832
+ }
833
+ isReferenceBaseline(): boolean {
834
+ return this.isReferenceBaseline_
835
+ }
836
+ setAspectRatio(_: number | undefined): void {}
837
+ getAspectRatio(): number {
838
+ return NaN
839
+ }
840
+ setAlwaysFormsContainingBlock(_: boolean): void {}
841
+ calculateLayout(ownerWidth: number | undefined, ownerHeight: number | undefined, _direction?: Direction): void {
842
+ _yogaNodesVisited = 0
843
+ _yogaMeasureCalls = 0
844
+ _yogaCacheHits = 0
845
+ _generation++
846
+ const w = ownerWidth === undefined ? NaN : ownerWidth
847
+ const h = ownerHeight === undefined ? NaN : ownerHeight
848
+ layoutNode(
849
+ this,
850
+ w,
851
+ h,
852
+ isDefined(w) ? MeasureMode.Exactly : MeasureMode.Undefined,
853
+ isDefined(h) ? MeasureMode.Exactly : MeasureMode.Undefined,
854
+ w,
855
+ h,
856
+ true
857
+ )
858
+ const mar = this.layout.margin
859
+ const posL = resolveValue(resolveEdgeRaw(this.style.position, EDGE_LEFT), isDefined(w) ? w : 0)
860
+ const posT = resolveValue(resolveEdgeRaw(this.style.position, EDGE_TOP), isDefined(w) ? w : 0)
861
+ this.layout.left = mar[EDGE_LEFT] + (isDefined(posL) ? posL : 0)
862
+ this.layout.top = mar[EDGE_TOP] + (isDefined(posT) ? posT : 0)
863
+ roundLayout(this, this.config.pointScaleFactor, 0, 0)
864
+ }
865
+ }
866
+ const DEFAULT_CONFIG = createConfig()
867
+ const CACHE_SLOTS = 4
868
+
869
+ function cacheWrite(
870
+ node: Node,
871
+ aW: number,
872
+ aH: number,
873
+ wM: MeasureMode,
874
+ hM: MeasureMode,
875
+ oW: number,
876
+ oH: number,
877
+ fW: boolean,
878
+ fH: boolean,
879
+ wasDirty: boolean
880
+ ): void {
881
+ if (!node._cIn) {
882
+ node._cIn = new Float64Array(CACHE_SLOTS * 8)
883
+ node._cOut = new Float64Array(CACHE_SLOTS * 2)
884
+ }
885
+
886
+ if (wasDirty && node._cGen !== _generation) {
887
+ node._cN = 0
888
+ node._cWr = 0
889
+ }
890
+
891
+ const i = node._cWr++ % CACHE_SLOTS
892
+
893
+ if (node._cN < CACHE_SLOTS) {
894
+ node._cN = node._cWr
895
+ }
896
+
897
+ const o = i * 8
898
+ const cIn = node._cIn
899
+ cIn[o] = aW
900
+ cIn[o + 1] = aH
901
+ cIn[o + 2] = wM
902
+ cIn[o + 3] = hM
903
+ cIn[o + 4] = oW
904
+ cIn[o + 5] = oH
905
+ cIn[o + 6] = fW ? 1 : 0
906
+ cIn[o + 7] = fH ? 1 : 0
907
+ node._cOut![i * 2] = node.layout.width
908
+ node._cOut![i * 2 + 1] = node.layout.height
909
+ node._cGen = _generation
910
+ }
911
+
912
+ function commitCacheOutputs(node: Node, performLayout: boolean): void {
913
+ if (performLayout) {
914
+ node._lOutW = node.layout.width
915
+ node._lOutH = node.layout.height
916
+ } else {
917
+ node._mOutW = node.layout.width
918
+ node._mOutH = node.layout.height
919
+ }
920
+ }
921
+
922
+ let _generation = 0
923
+ let _yogaNodesVisited = 0
924
+ let _yogaMeasureCalls = 0
925
+ let _yogaCacheHits = 0
926
+ let _yogaLiveNodes = 0
927
+
928
+ export function getYogaCounters(): {
929
+ visited: number
930
+ measured: number
931
+ cacheHits: number
932
+ live: number
933
+ } {
934
+ return {
935
+ visited: _yogaNodesVisited,
936
+ measured: _yogaMeasureCalls,
937
+ cacheHits: _yogaCacheHits,
938
+ live: _yogaLiveNodes
939
+ }
940
+ }
941
+
942
+ function layoutNode(
943
+ node: Node,
944
+ availableWidth: number,
945
+ availableHeight: number,
946
+ widthMode: MeasureMode,
947
+ heightMode: MeasureMode,
948
+ ownerWidth: number,
949
+ ownerHeight: number,
950
+ performLayout: boolean,
951
+ forceWidth = false,
952
+ forceHeight = false
953
+ ): void {
954
+ _yogaNodesVisited++
955
+ const style = node.style
956
+ const layout = node.layout
957
+ const sameGen = node._cGen === _generation && !performLayout
958
+
959
+ if (!node.isDirty_ || sameGen) {
960
+ if (
961
+ !node.isDirty_ &&
962
+ node._hasL &&
963
+ node._lWM === widthMode &&
964
+ node._lHM === heightMode &&
965
+ node._lFW === forceWidth &&
966
+ node._lFH === forceHeight &&
967
+ sameFloat(node._lW, availableWidth) &&
968
+ sameFloat(node._lH, availableHeight) &&
969
+ sameFloat(node._lOW, ownerWidth) &&
970
+ sameFloat(node._lOH, ownerHeight)
971
+ ) {
972
+ _yogaCacheHits++
973
+ layout.width = node._lOutW
974
+ layout.height = node._lOutH
975
+
976
+ return
977
+ }
978
+
979
+ if (node._cN > 0 && (sameGen || !node.isDirty_)) {
980
+ const cIn = node._cIn!
981
+
982
+ for (let i = 0; i < node._cN; i++) {
983
+ const o = i * 8
984
+
985
+ if (
986
+ cIn[o + 2] === widthMode &&
987
+ cIn[o + 3] === heightMode &&
988
+ cIn[o + 6] === (forceWidth ? 1 : 0) &&
989
+ cIn[o + 7] === (forceHeight ? 1 : 0) &&
990
+ sameFloat(cIn[o]!, availableWidth) &&
991
+ sameFloat(cIn[o + 1]!, availableHeight) &&
992
+ sameFloat(cIn[o + 4]!, ownerWidth) &&
993
+ sameFloat(cIn[o + 5]!, ownerHeight)
994
+ ) {
995
+ layout.width = node._cOut![i * 2]!
996
+ layout.height = node._cOut![i * 2 + 1]!
997
+ _yogaCacheHits++
998
+
999
+ return
1000
+ }
1001
+ }
1002
+ }
1003
+
1004
+ if (
1005
+ !node.isDirty_ &&
1006
+ !performLayout &&
1007
+ node._hasM &&
1008
+ node._mWM === widthMode &&
1009
+ node._mHM === heightMode &&
1010
+ sameFloat(node._mW, availableWidth) &&
1011
+ sameFloat(node._mH, availableHeight) &&
1012
+ sameFloat(node._mOW, ownerWidth) &&
1013
+ sameFloat(node._mOH, ownerHeight)
1014
+ ) {
1015
+ layout.width = node._mOutW
1016
+ layout.height = node._mOutH
1017
+ _yogaCacheHits++
1018
+
1019
+ return
1020
+ }
1021
+ }
1022
+
1023
+ const wasDirty = node.isDirty_
1024
+
1025
+ if (performLayout) {
1026
+ node._lW = availableWidth
1027
+ node._lH = availableHeight
1028
+ node._lWM = widthMode
1029
+ node._lHM = heightMode
1030
+ node._lOW = ownerWidth
1031
+ node._lOH = ownerHeight
1032
+ node._lFW = forceWidth
1033
+ node._lFH = forceHeight
1034
+ node._hasL = true
1035
+ node.isDirty_ = false
1036
+
1037
+ if (wasDirty) {
1038
+ node._hasM = false
1039
+ }
1040
+ } else {
1041
+ node._mW = availableWidth
1042
+ node._mH = availableHeight
1043
+ node._mWM = widthMode
1044
+ node._mHM = heightMode
1045
+ node._mOW = ownerWidth
1046
+ node._mOH = ownerHeight
1047
+ node._hasM = true
1048
+
1049
+ if (wasDirty) {
1050
+ node._hasL = false
1051
+ }
1052
+ }
1053
+
1054
+ const pad = layout.padding
1055
+ const bor = layout.border
1056
+ const mar = layout.margin
1057
+
1058
+ if (node._hasPadding) {
1059
+ resolveEdges4Into(style.padding, ownerWidth, pad)
1060
+ } else {
1061
+ pad[0] = pad[1] = pad[2] = pad[3] = 0
1062
+ }
1063
+
1064
+ if (node._hasBorder) {
1065
+ resolveEdges4Into(style.border, ownerWidth, bor)
1066
+ } else {
1067
+ bor[0] = bor[1] = bor[2] = bor[3] = 0
1068
+ }
1069
+
1070
+ if (node._hasMargin) {
1071
+ resolveEdges4Into(style.margin, ownerWidth, mar)
1072
+ } else {
1073
+ mar[0] = mar[1] = mar[2] = mar[3] = 0
1074
+ }
1075
+
1076
+ const paddingBorderWidth = pad[0] + pad[2] + bor[0] + bor[2]
1077
+ const paddingBorderHeight = pad[1] + pad[3] + bor[1] + bor[3]
1078
+ const styleWidth = forceWidth ? NaN : resolveValue(style.width, ownerWidth)
1079
+
1080
+ const styleHeight = forceHeight ? NaN : resolveValue(style.height, ownerHeight)
1081
+
1082
+ let width = availableWidth
1083
+ let height = availableHeight
1084
+ let wMode = widthMode
1085
+ let hMode = heightMode
1086
+
1087
+ if (isDefined(styleWidth)) {
1088
+ width = styleWidth
1089
+ wMode = MeasureMode.Exactly
1090
+ }
1091
+
1092
+ if (isDefined(styleHeight)) {
1093
+ height = styleHeight
1094
+ hMode = MeasureMode.Exactly
1095
+ }
1096
+
1097
+ width = boundAxis(style, true, width, ownerWidth, ownerHeight)
1098
+ height = boundAxis(style, false, height, ownerWidth, ownerHeight)
1099
+
1100
+ if (node.measureFunc && node.children.length === 0) {
1101
+ const innerW = wMode === MeasureMode.Undefined ? NaN : Math.max(0, width - paddingBorderWidth)
1102
+
1103
+ const innerH = hMode === MeasureMode.Undefined ? NaN : Math.max(0, height - paddingBorderHeight)
1104
+
1105
+ _yogaMeasureCalls++
1106
+ const measured = node.measureFunc(innerW, wMode, innerH, hMode)
1107
+ node.layout.width =
1108
+ wMode === MeasureMode.Exactly
1109
+ ? width
1110
+ : boundAxis(style, true, (measured.width ?? 0) + paddingBorderWidth, ownerWidth, ownerHeight)
1111
+ node.layout.height =
1112
+ hMode === MeasureMode.Exactly
1113
+ ? height
1114
+ : boundAxis(style, false, (measured.height ?? 0) + paddingBorderHeight, ownerWidth, ownerHeight)
1115
+ commitCacheOutputs(node, performLayout)
1116
+ cacheWrite(
1117
+ node,
1118
+ availableWidth,
1119
+ availableHeight,
1120
+ widthMode,
1121
+ heightMode,
1122
+ ownerWidth,
1123
+ ownerHeight,
1124
+ forceWidth,
1125
+ forceHeight,
1126
+ wasDirty
1127
+ )
1128
+
1129
+ return
1130
+ }
1131
+
1132
+ if (node.children.length === 0) {
1133
+ node.layout.width =
1134
+ wMode === MeasureMode.Exactly ? width : boundAxis(style, true, paddingBorderWidth, ownerWidth, ownerHeight)
1135
+ node.layout.height =
1136
+ hMode === MeasureMode.Exactly ? height : boundAxis(style, false, paddingBorderHeight, ownerWidth, ownerHeight)
1137
+ commitCacheOutputs(node, performLayout)
1138
+ cacheWrite(
1139
+ node,
1140
+ availableWidth,
1141
+ availableHeight,
1142
+ widthMode,
1143
+ heightMode,
1144
+ ownerWidth,
1145
+ ownerHeight,
1146
+ forceWidth,
1147
+ forceHeight,
1148
+ wasDirty
1149
+ )
1150
+
1151
+ return
1152
+ }
1153
+
1154
+ const mainAxis = style.flexDirection
1155
+ const crossAx = crossAxis(mainAxis)
1156
+ const isMainRow = isRow(mainAxis)
1157
+ const mainSize = isMainRow ? width : height
1158
+ const crossSize = isMainRow ? height : width
1159
+ const mainMode = isMainRow ? wMode : hMode
1160
+ const crossMode = isMainRow ? hMode : wMode
1161
+ const mainPadBorder = isMainRow ? paddingBorderWidth : paddingBorderHeight
1162
+ const crossPadBorder = isMainRow ? paddingBorderHeight : paddingBorderWidth
1163
+
1164
+ const innerMainSize = isDefined(mainSize) ? Math.max(0, mainSize - mainPadBorder) : NaN
1165
+
1166
+ const innerCrossSize = isDefined(crossSize) ? Math.max(0, crossSize - crossPadBorder) : NaN
1167
+
1168
+ const gapMain = resolveGap(style, isMainRow ? Gutter.Column : Gutter.Row, innerMainSize)
1169
+ const flowChildren: Node[] = []
1170
+ const absChildren: Node[] = []
1171
+ collectLayoutChildren(node, flowChildren, absChildren)
1172
+ const ownerW = isDefined(width) ? width : NaN
1173
+ const ownerH = isDefined(height) ? height : NaN
1174
+ const isWrap = style.flexWrap !== Wrap.NoWrap
1175
+ const gapCross = resolveGap(style, isMainRow ? Gutter.Row : Gutter.Column, innerCrossSize)
1176
+
1177
+ for (const c of flowChildren) {
1178
+ c._flexBasis = computeFlexBasis(c, mainAxis, innerMainSize, innerCrossSize, crossMode, ownerW, ownerH)
1179
+ }
1180
+
1181
+ const lines: Node[][] = []
1182
+
1183
+ if (!isWrap || !isDefined(innerMainSize) || flowChildren.length === 0) {
1184
+ for (const c of flowChildren) {
1185
+ c._lineIndex = 0
1186
+ }
1187
+
1188
+ lines.push(flowChildren)
1189
+ } else {
1190
+ let lineStart = 0
1191
+ let lineLen = 0
1192
+
1193
+ for (let i = 0; i < flowChildren.length; i++) {
1194
+ const c = flowChildren[i]!
1195
+ const hypo = boundAxis(c.style, isMainRow, c._flexBasis, ownerW, ownerH)
1196
+ const outer = Math.max(0, hypo) + childMarginForAxis(c, mainAxis, ownerW)
1197
+ const withGap = i > lineStart ? gapMain : 0
1198
+
1199
+ if (i > lineStart && lineLen + withGap + outer > innerMainSize) {
1200
+ lines.push(flowChildren.slice(lineStart, i))
1201
+ lineStart = i
1202
+ lineLen = outer
1203
+ } else {
1204
+ lineLen += withGap + outer
1205
+ }
1206
+
1207
+ c._lineIndex = lines.length
1208
+ }
1209
+
1210
+ lines.push(flowChildren.slice(lineStart))
1211
+ }
1212
+
1213
+ const lineCount = lines.length
1214
+ const isBaseline = isBaselineLayout(node, flowChildren)
1215
+ const lineConsumedMain: number[] = new Array(lineCount)
1216
+ const lineCrossSizes: number[] = new Array(lineCount)
1217
+ const lineMaxAscent: number[] = isBaseline ? new Array(lineCount).fill(0) : []
1218
+ let maxLineMain = 0
1219
+ let totalLinesCross = 0
1220
+
1221
+ for (let li = 0; li < lineCount; li++) {
1222
+ const line = lines[li]!
1223
+ const lineGap = line.length > 1 ? gapMain * (line.length - 1) : 0
1224
+ let lineBasis = lineGap
1225
+
1226
+ for (const c of line) {
1227
+ lineBasis += c._flexBasis + childMarginForAxis(c, mainAxis, ownerW)
1228
+ }
1229
+
1230
+ let availMain = innerMainSize
1231
+
1232
+ if (!isDefined(availMain)) {
1233
+ const mainOwner = isMainRow ? ownerWidth : ownerHeight
1234
+ const minM = resolveValue(isMainRow ? style.minWidth : style.minHeight, mainOwner)
1235
+ const maxM = resolveValue(isMainRow ? style.maxWidth : style.maxHeight, mainOwner)
1236
+
1237
+ if (isDefined(maxM) && lineBasis > maxM - mainPadBorder) {
1238
+ availMain = Math.max(0, maxM - mainPadBorder)
1239
+ } else if (isDefined(minM) && lineBasis < minM - mainPadBorder) {
1240
+ availMain = Math.max(0, minM - mainPadBorder)
1241
+ }
1242
+ }
1243
+
1244
+ resolveFlexibleLengths(line, availMain, lineBasis, isMainRow, ownerW, ownerH)
1245
+ let lineCross = 0
1246
+
1247
+ for (const c of line) {
1248
+ const cStyle = c.style
1249
+ const childAlign = cStyle.alignSelf === Align.Auto ? style.alignItems : cStyle.alignSelf
1250
+ const cMarginCross = childMarginForAxis(c, crossAx, ownerW)
1251
+ let childCrossSize = NaN
1252
+ let childCrossMode: MeasureMode = MeasureMode.Undefined
1253
+ const resolvedCrossStyle = resolveValue(isMainRow ? cStyle.height : cStyle.width, isMainRow ? ownerH : ownerW)
1254
+ const crossLeadE = isMainRow ? EDGE_TOP : EDGE_LEFT
1255
+ const crossTrailE = isMainRow ? EDGE_BOTTOM : EDGE_RIGHT
1256
+
1257
+ const hasCrossAutoMargin =
1258
+ c._hasAutoMargin && (isMarginAuto(cStyle.margin, crossLeadE) || isMarginAuto(cStyle.margin, crossTrailE))
1259
+
1260
+ if (isDefined(resolvedCrossStyle)) {
1261
+ childCrossSize = resolvedCrossStyle
1262
+ childCrossMode = MeasureMode.Exactly
1263
+ } else if (
1264
+ childAlign === Align.Stretch &&
1265
+ !hasCrossAutoMargin &&
1266
+ !isWrap &&
1267
+ isDefined(innerCrossSize) &&
1268
+ crossMode === MeasureMode.Exactly
1269
+ ) {
1270
+ childCrossSize = Math.max(0, innerCrossSize - cMarginCross)
1271
+ childCrossMode = MeasureMode.Exactly
1272
+ } else if (!isWrap && isDefined(innerCrossSize)) {
1273
+ childCrossSize = Math.max(0, innerCrossSize - cMarginCross)
1274
+ childCrossMode = MeasureMode.AtMost
1275
+ }
1276
+
1277
+ const cw = isMainRow ? c._mainSize : childCrossSize
1278
+ const ch = isMainRow ? childCrossSize : c._mainSize
1279
+ layoutNode(
1280
+ c,
1281
+ cw,
1282
+ ch,
1283
+ isMainRow ? MeasureMode.Exactly : childCrossMode,
1284
+ isMainRow ? childCrossMode : MeasureMode.Exactly,
1285
+ ownerW,
1286
+ ownerH,
1287
+ performLayout,
1288
+ isMainRow,
1289
+ !isMainRow
1290
+ )
1291
+ c._crossSize = isMainRow ? c.layout.height : c.layout.width
1292
+ lineCross = Math.max(lineCross, c._crossSize + cMarginCross)
1293
+ }
1294
+
1295
+ if (isBaseline) {
1296
+ let maxAscent = 0
1297
+ let maxDescent = 0
1298
+
1299
+ for (const c of line) {
1300
+ if (resolveChildAlign(node, c) !== Align.Baseline) {
1301
+ continue
1302
+ }
1303
+
1304
+ const mTop = resolveEdge(c.style.margin, EDGE_TOP, ownerW)
1305
+ const mBot = resolveEdge(c.style.margin, EDGE_BOTTOM, ownerW)
1306
+ const ascent = calculateBaseline(c) + mTop
1307
+ const descent = c.layout.height + mTop + mBot - ascent
1308
+
1309
+ if (ascent > maxAscent) {
1310
+ maxAscent = ascent
1311
+ }
1312
+
1313
+ if (descent > maxDescent) {
1314
+ maxDescent = descent
1315
+ }
1316
+ }
1317
+
1318
+ lineMaxAscent[li] = maxAscent
1319
+
1320
+ if (maxAscent + maxDescent > lineCross) {
1321
+ lineCross = maxAscent + maxDescent
1322
+ }
1323
+ }
1324
+
1325
+ const mainLead = leadingEdge(mainAxis)
1326
+ const mainTrail = trailingEdge(mainAxis)
1327
+ let consumed = lineGap
1328
+
1329
+ for (const c of line) {
1330
+ const cm = c.layout.margin
1331
+ consumed += c._mainSize + cm[mainLead]! + cm[mainTrail]!
1332
+ }
1333
+
1334
+ lineConsumedMain[li] = consumed
1335
+ lineCrossSizes[li] = lineCross
1336
+ maxLineMain = Math.max(maxLineMain, consumed)
1337
+ totalLinesCross += lineCross
1338
+ }
1339
+
1340
+ const totalCrossGap = lineCount > 1 ? gapCross * (lineCount - 1) : 0
1341
+ totalLinesCross += totalCrossGap
1342
+ const isScroll = style.overflow === Overflow.Scroll
1343
+ const contentMain = maxLineMain + mainPadBorder
1344
+
1345
+ const finalMainSize =
1346
+ mainMode === MeasureMode.Exactly
1347
+ ? mainSize
1348
+ : mainMode === MeasureMode.AtMost && isScroll
1349
+ ? Math.max(Math.min(mainSize, contentMain), mainPadBorder)
1350
+ : isWrap && lineCount > 1 && mainMode === MeasureMode.AtMost
1351
+ ? mainSize
1352
+ : contentMain
1353
+
1354
+ const contentCross = totalLinesCross + crossPadBorder
1355
+
1356
+ const finalCrossSize =
1357
+ crossMode === MeasureMode.Exactly
1358
+ ? crossSize
1359
+ : crossMode === MeasureMode.AtMost && isScroll
1360
+ ? Math.max(Math.min(crossSize, contentCross), crossPadBorder)
1361
+ : contentCross
1362
+
1363
+ node.layout.width = boundAxis(style, true, isMainRow ? finalMainSize : finalCrossSize, ownerWidth, ownerHeight)
1364
+ node.layout.height = boundAxis(style, false, isMainRow ? finalCrossSize : finalMainSize, ownerWidth, ownerHeight)
1365
+ commitCacheOutputs(node, performLayout)
1366
+ cacheWrite(
1367
+ node,
1368
+ availableWidth,
1369
+ availableHeight,
1370
+ widthMode,
1371
+ heightMode,
1372
+ ownerWidth,
1373
+ ownerHeight,
1374
+ forceWidth,
1375
+ forceHeight,
1376
+ wasDirty
1377
+ )
1378
+
1379
+ if (!performLayout) {
1380
+ return
1381
+ }
1382
+
1383
+ const actualInnerMain = (isMainRow ? node.layout.width : node.layout.height) - mainPadBorder
1384
+ const actualInnerCross = (isMainRow ? node.layout.height : node.layout.width) - crossPadBorder
1385
+ const mainLeadEdgePhys = leadingEdge(mainAxis)
1386
+ const mainTrailEdgePhys = trailingEdge(mainAxis)
1387
+ const crossLeadEdgePhys = isMainRow ? EDGE_TOP : EDGE_LEFT
1388
+ const crossTrailEdgePhys = isMainRow ? EDGE_BOTTOM : EDGE_RIGHT
1389
+ const reversed = isReverse(mainAxis)
1390
+ const mainContainerSize = isMainRow ? node.layout.width : node.layout.height
1391
+ const crossLead = pad[crossLeadEdgePhys]! + bor[crossLeadEdgePhys]!
1392
+ let lineCrossOffset = crossLead
1393
+ let betweenLines = gapCross
1394
+ const freeCross = actualInnerCross - totalLinesCross
1395
+
1396
+ if (lineCount === 1 && !isWrap && !isBaseline) {
1397
+ lineCrossSizes[0] = actualInnerCross
1398
+ } else {
1399
+ const remCross = Math.max(0, freeCross)
1400
+
1401
+ switch (style.alignContent) {
1402
+ case Align.FlexStart:
1403
+ break
1404
+
1405
+ case Align.Center:
1406
+ lineCrossOffset += freeCross / 2
1407
+
1408
+ break
1409
+
1410
+ case Align.FlexEnd:
1411
+ lineCrossOffset += freeCross
1412
+
1413
+ break
1414
+
1415
+ case Align.Stretch:
1416
+ if (lineCount > 0 && remCross > 0) {
1417
+ const add = remCross / lineCount
1418
+
1419
+ for (let i = 0; i < lineCount; i++) {
1420
+ lineCrossSizes[i]! += add
1421
+ }
1422
+ }
1423
+
1424
+ break
1425
+
1426
+ case Align.SpaceBetween:
1427
+ if (lineCount > 1) {
1428
+ betweenLines += remCross / (lineCount - 1)
1429
+ }
1430
+
1431
+ break
1432
+
1433
+ case Align.SpaceAround:
1434
+ if (lineCount > 0) {
1435
+ betweenLines += remCross / lineCount
1436
+ lineCrossOffset += remCross / lineCount / 2
1437
+ }
1438
+
1439
+ break
1440
+
1441
+ case Align.SpaceEvenly:
1442
+ if (lineCount > 0) {
1443
+ betweenLines += remCross / (lineCount + 1)
1444
+ lineCrossOffset += remCross / (lineCount + 1)
1445
+ }
1446
+
1447
+ break
1448
+
1449
+ default:
1450
+ break
1451
+ }
1452
+ }
1453
+
1454
+ const wrapReverse = style.flexWrap === Wrap.WrapReverse
1455
+ const crossContainerSize = isMainRow ? node.layout.height : node.layout.width
1456
+ let lineCrossPos = lineCrossOffset
1457
+
1458
+ for (let li = 0; li < lineCount; li++) {
1459
+ const line = lines[li]!
1460
+ const lineCross = lineCrossSizes[li]!
1461
+ const consumedMain = lineConsumedMain[li]!
1462
+ const n = line.length
1463
+
1464
+ if (isWrap || crossMode !== MeasureMode.Exactly) {
1465
+ for (const c of line) {
1466
+ const cStyle = c.style
1467
+ const childAlign = cStyle.alignSelf === Align.Auto ? style.alignItems : cStyle.alignSelf
1468
+
1469
+ const crossStyleDef = isDefined(
1470
+ resolveValue(isMainRow ? cStyle.height : cStyle.width, isMainRow ? ownerH : ownerW)
1471
+ )
1472
+
1473
+ const hasCrossAutoMargin =
1474
+ c._hasAutoMargin &&
1475
+ (isMarginAuto(cStyle.margin, crossLeadEdgePhys) || isMarginAuto(cStyle.margin, crossTrailEdgePhys))
1476
+
1477
+ if (childAlign === Align.Stretch && !crossStyleDef && !hasCrossAutoMargin) {
1478
+ const cMarginCross = childMarginForAxis(c, crossAx, ownerW)
1479
+ const target = Math.max(0, lineCross - cMarginCross)
1480
+
1481
+ if (c._crossSize !== target) {
1482
+ const cw = isMainRow ? c._mainSize : target
1483
+ const ch = isMainRow ? target : c._mainSize
1484
+ layoutNode(
1485
+ c,
1486
+ cw,
1487
+ ch,
1488
+ MeasureMode.Exactly,
1489
+ MeasureMode.Exactly,
1490
+ ownerW,
1491
+ ownerH,
1492
+ performLayout,
1493
+ isMainRow,
1494
+ !isMainRow
1495
+ )
1496
+ c._crossSize = target
1497
+ }
1498
+ }
1499
+ }
1500
+ }
1501
+
1502
+ let mainOffset = pad[mainLeadEdgePhys]! + bor[mainLeadEdgePhys]!
1503
+ let betweenMain = gapMain
1504
+ let numAutoMarginsMain = 0
1505
+
1506
+ for (const c of line) {
1507
+ if (!c._hasAutoMargin) {
1508
+ continue
1509
+ }
1510
+
1511
+ if (isMarginAuto(c.style.margin, mainLeadEdgePhys)) {
1512
+ numAutoMarginsMain++
1513
+ }
1514
+
1515
+ if (isMarginAuto(c.style.margin, mainTrailEdgePhys)) {
1516
+ numAutoMarginsMain++
1517
+ }
1518
+ }
1519
+
1520
+ const freeMain = actualInnerMain - consumedMain
1521
+ const remainingMain = Math.max(0, freeMain)
1522
+
1523
+ const autoMarginMainSize = numAutoMarginsMain > 0 && remainingMain > 0 ? remainingMain / numAutoMarginsMain : 0
1524
+
1525
+ if (numAutoMarginsMain === 0) {
1526
+ switch (style.justifyContent) {
1527
+ case Justify.FlexStart:
1528
+ break
1529
+
1530
+ case Justify.Center:
1531
+ mainOffset += freeMain / 2
1532
+
1533
+ break
1534
+
1535
+ case Justify.FlexEnd:
1536
+ mainOffset += freeMain
1537
+
1538
+ break
1539
+
1540
+ case Justify.SpaceBetween:
1541
+ if (n > 1) {
1542
+ betweenMain += remainingMain / (n - 1)
1543
+ }
1544
+
1545
+ break
1546
+
1547
+ case Justify.SpaceAround:
1548
+ if (n > 0) {
1549
+ betweenMain += remainingMain / n
1550
+ mainOffset += remainingMain / n / 2
1551
+ }
1552
+
1553
+ break
1554
+
1555
+ case Justify.SpaceEvenly:
1556
+ if (n > 0) {
1557
+ betweenMain += remainingMain / (n + 1)
1558
+ mainOffset += remainingMain / (n + 1)
1559
+ }
1560
+
1561
+ break
1562
+ }
1563
+ }
1564
+
1565
+ const effectiveLineCrossPos = wrapReverse ? crossContainerSize - lineCrossPos - lineCross : lineCrossPos
1566
+
1567
+ let pos = mainOffset
1568
+
1569
+ for (const c of line) {
1570
+ const cMargin = c.style.margin
1571
+ const cLayoutMargin = c.layout.margin
1572
+ let autoMainLead = false
1573
+ let autoMainTrail = false
1574
+ let autoCrossLead = false
1575
+ let autoCrossTrail = false
1576
+ let mMainLead: number
1577
+ let mMainTrail: number
1578
+ let mCrossLead: number
1579
+ let mCrossTrail: number
1580
+
1581
+ if (c._hasAutoMargin) {
1582
+ autoMainLead = isMarginAuto(cMargin, mainLeadEdgePhys)
1583
+ autoMainTrail = isMarginAuto(cMargin, mainTrailEdgePhys)
1584
+ autoCrossLead = isMarginAuto(cMargin, crossLeadEdgePhys)
1585
+ autoCrossTrail = isMarginAuto(cMargin, crossTrailEdgePhys)
1586
+ mMainLead = autoMainLead ? autoMarginMainSize : cLayoutMargin[mainLeadEdgePhys]!
1587
+ mMainTrail = autoMainTrail ? autoMarginMainSize : cLayoutMargin[mainTrailEdgePhys]!
1588
+ mCrossLead = autoCrossLead ? 0 : cLayoutMargin[crossLeadEdgePhys]!
1589
+ mCrossTrail = autoCrossTrail ? 0 : cLayoutMargin[crossTrailEdgePhys]!
1590
+ } else {
1591
+ mMainLead = cLayoutMargin[mainLeadEdgePhys]!
1592
+ mMainTrail = cLayoutMargin[mainTrailEdgePhys]!
1593
+ mCrossLead = cLayoutMargin[crossLeadEdgePhys]!
1594
+ mCrossTrail = cLayoutMargin[crossTrailEdgePhys]!
1595
+ }
1596
+
1597
+ const mainPos = reversed ? mainContainerSize - (pos + mMainLead) - c._mainSize : pos + mMainLead
1598
+
1599
+ const childAlign = c.style.alignSelf === Align.Auto ? style.alignItems : c.style.alignSelf
1600
+ let crossPos = effectiveLineCrossPos + mCrossLead
1601
+ const crossFree = lineCross - c._crossSize - mCrossLead - mCrossTrail
1602
+
1603
+ if (autoCrossLead && autoCrossTrail) {
1604
+ crossPos += Math.max(0, crossFree) / 2
1605
+ } else if (autoCrossLead) {
1606
+ crossPos += Math.max(0, crossFree)
1607
+ } else if (autoCrossTrail) {
1608
+ } else {
1609
+ switch (childAlign) {
1610
+ case Align.FlexStart:
1611
+
1612
+ case Align.Stretch:
1613
+ if (wrapReverse) {
1614
+ crossPos += crossFree
1615
+ }
1616
+
1617
+ break
1618
+
1619
+ case Align.Center:
1620
+ crossPos += crossFree / 2
1621
+
1622
+ break
1623
+
1624
+ case Align.FlexEnd:
1625
+ if (!wrapReverse) {
1626
+ crossPos += crossFree
1627
+ }
1628
+
1629
+ break
1630
+
1631
+ case Align.Baseline:
1632
+ if (isBaseline) {
1633
+ crossPos = effectiveLineCrossPos + lineMaxAscent[li]! - calculateBaseline(c)
1634
+ }
1635
+
1636
+ break
1637
+
1638
+ default:
1639
+ break
1640
+ }
1641
+ }
1642
+
1643
+ let relX = 0
1644
+ let relY = 0
1645
+
1646
+ if (c._hasPosition) {
1647
+ const relLeft = resolveValue(resolveEdgeRaw(c.style.position, EDGE_LEFT), ownerW)
1648
+ const relRight = resolveValue(resolveEdgeRaw(c.style.position, EDGE_RIGHT), ownerW)
1649
+ const relTop = resolveValue(resolveEdgeRaw(c.style.position, EDGE_TOP), ownerW)
1650
+ const relBottom = resolveValue(resolveEdgeRaw(c.style.position, EDGE_BOTTOM), ownerW)
1651
+ relX = isDefined(relLeft) ? relLeft : isDefined(relRight) ? -relRight : 0
1652
+ relY = isDefined(relTop) ? relTop : isDefined(relBottom) ? -relBottom : 0
1653
+ }
1654
+
1655
+ if (isMainRow) {
1656
+ c.layout.left = mainPos + relX
1657
+ c.layout.top = crossPos + relY
1658
+ } else {
1659
+ c.layout.left = crossPos + relX
1660
+ c.layout.top = mainPos + relY
1661
+ }
1662
+
1663
+ pos += c._mainSize + mMainLead + mMainTrail + betweenMain
1664
+ }
1665
+
1666
+ lineCrossPos += lineCross + betweenLines
1667
+ }
1668
+
1669
+ for (const c of absChildren) {
1670
+ layoutAbsoluteChild(node, c, node.layout.width, node.layout.height, pad, bor)
1671
+ }
1672
+ }
1673
+
1674
+ function layoutAbsoluteChild(
1675
+ parent: Node,
1676
+ child: Node,
1677
+ parentWidth: number,
1678
+ parentHeight: number,
1679
+ pad: [number, number, number, number],
1680
+ bor: [number, number, number, number]
1681
+ ): void {
1682
+ const cs = child.style
1683
+ const posLeft = resolveEdgeRaw(cs.position, EDGE_LEFT)
1684
+ const posRight = resolveEdgeRaw(cs.position, EDGE_RIGHT)
1685
+ const posTop = resolveEdgeRaw(cs.position, EDGE_TOP)
1686
+ const posBottom = resolveEdgeRaw(cs.position, EDGE_BOTTOM)
1687
+ const rLeft = resolveValue(posLeft, parentWidth)
1688
+ const rRight = resolveValue(posRight, parentWidth)
1689
+ const rTop = resolveValue(posTop, parentHeight)
1690
+ const rBottom = resolveValue(posBottom, parentHeight)
1691
+ const paddingBoxW = parentWidth - bor[0] - bor[2]
1692
+ const paddingBoxH = parentHeight - bor[1] - bor[3]
1693
+ let cw = resolveValue(cs.width, paddingBoxW)
1694
+ let ch = resolveValue(cs.height, paddingBoxH)
1695
+
1696
+ if (!isDefined(cw) && isDefined(rLeft) && isDefined(rRight)) {
1697
+ cw = paddingBoxW - rLeft - rRight
1698
+ }
1699
+
1700
+ if (!isDefined(ch) && isDefined(rTop) && isDefined(rBottom)) {
1701
+ ch = paddingBoxH - rTop - rBottom
1702
+ }
1703
+
1704
+ layoutNode(
1705
+ child,
1706
+ cw,
1707
+ ch,
1708
+ isDefined(cw) ? MeasureMode.Exactly : MeasureMode.Undefined,
1709
+ isDefined(ch) ? MeasureMode.Exactly : MeasureMode.Undefined,
1710
+ paddingBoxW,
1711
+ paddingBoxH,
1712
+ true
1713
+ )
1714
+ const mL = resolveEdge(cs.margin, EDGE_LEFT, parentWidth)
1715
+ const mT = resolveEdge(cs.margin, EDGE_TOP, parentWidth)
1716
+ const mR = resolveEdge(cs.margin, EDGE_RIGHT, parentWidth)
1717
+ const mB = resolveEdge(cs.margin, EDGE_BOTTOM, parentWidth)
1718
+ const mainAxis = parent.style.flexDirection
1719
+ const reversed = isReverse(mainAxis)
1720
+ const mainRow = isRow(mainAxis)
1721
+ const wrapReverse = parent.style.flexWrap === Wrap.WrapReverse
1722
+ const alignment = cs.alignSelf === Align.Auto ? parent.style.alignItems : cs.alignSelf
1723
+ let left: number
1724
+
1725
+ if (isDefined(rLeft)) {
1726
+ left = bor[0] + rLeft + mL
1727
+ } else if (isDefined(rRight)) {
1728
+ left = parentWidth - bor[2] - rRight - child.layout.width - mR
1729
+ } else if (mainRow) {
1730
+ const lead = pad[0] + bor[0]
1731
+ const trail = parentWidth - pad[2] - bor[2]
1732
+ left = reversed
1733
+ ? trail - child.layout.width - mR
1734
+ : justifyAbsolute(parent.style.justifyContent, lead, trail, child.layout.width) + mL
1735
+ } else {
1736
+ left =
1737
+ alignAbsolute(alignment, pad[0] + bor[0], parentWidth - pad[2] - bor[2], child.layout.width, wrapReverse) + mL
1738
+ }
1739
+
1740
+ let top: number
1741
+
1742
+ if (isDefined(rTop)) {
1743
+ top = bor[1] + rTop + mT
1744
+ } else if (isDefined(rBottom)) {
1745
+ top = parentHeight - bor[3] - rBottom - child.layout.height - mB
1746
+ } else if (mainRow) {
1747
+ top =
1748
+ alignAbsolute(alignment, pad[1] + bor[1], parentHeight - pad[3] - bor[3], child.layout.height, wrapReverse) + mT
1749
+ } else {
1750
+ const lead = pad[1] + bor[1]
1751
+ const trail = parentHeight - pad[3] - bor[3]
1752
+ top = reversed
1753
+ ? trail - child.layout.height - mB
1754
+ : justifyAbsolute(parent.style.justifyContent, lead, trail, child.layout.height) + mT
1755
+ }
1756
+
1757
+ child.layout.left = left
1758
+ child.layout.top = top
1759
+ }
1760
+
1761
+ function justifyAbsolute(justify: Justify, leadEdge: number, trailEdge: number, childSize: number): number {
1762
+ switch (justify) {
1763
+ case Justify.Center:
1764
+ return leadEdge + (trailEdge - leadEdge - childSize) / 2
1765
+
1766
+ case Justify.FlexEnd:
1767
+ return trailEdge - childSize
1768
+
1769
+ default:
1770
+ return leadEdge
1771
+ }
1772
+ }
1773
+
1774
+ function alignAbsolute(
1775
+ align: Align,
1776
+ leadEdge: number,
1777
+ trailEdge: number,
1778
+ childSize: number,
1779
+ wrapReverse: boolean
1780
+ ): number {
1781
+ switch (align) {
1782
+ case Align.Center:
1783
+ return leadEdge + (trailEdge - leadEdge - childSize) / 2
1784
+
1785
+ case Align.FlexEnd:
1786
+ return wrapReverse ? leadEdge : trailEdge - childSize
1787
+
1788
+ default:
1789
+ return wrapReverse ? trailEdge - childSize : leadEdge
1790
+ }
1791
+ }
1792
+
1793
+ function computeFlexBasis(
1794
+ child: Node,
1795
+ mainAxis: FlexDirection,
1796
+ availableMain: number,
1797
+ availableCross: number,
1798
+ crossMode: MeasureMode,
1799
+ ownerWidth: number,
1800
+ ownerHeight: number
1801
+ ): number {
1802
+ const sameGen = child._fbGen === _generation
1803
+
1804
+ if (
1805
+ (sameGen || !child.isDirty_) &&
1806
+ child._fbCrossMode === crossMode &&
1807
+ sameFloat(child._fbOwnerW, ownerWidth) &&
1808
+ sameFloat(child._fbOwnerH, ownerHeight) &&
1809
+ sameFloat(child._fbAvailMain, availableMain) &&
1810
+ sameFloat(child._fbAvailCross, availableCross)
1811
+ ) {
1812
+ return child._fbBasis
1813
+ }
1814
+
1815
+ const cs = child.style
1816
+ const isMainRow = isRow(mainAxis)
1817
+ const basis = resolveValue(cs.flexBasis, availableMain)
1818
+
1819
+ if (isDefined(basis)) {
1820
+ const b = Math.max(0, basis)
1821
+ child._fbBasis = b
1822
+ child._fbOwnerW = ownerWidth
1823
+ child._fbOwnerH = ownerHeight
1824
+ child._fbAvailMain = availableMain
1825
+ child._fbAvailCross = availableCross
1826
+ child._fbCrossMode = crossMode
1827
+ child._fbGen = _generation
1828
+
1829
+ return b
1830
+ }
1831
+
1832
+ const mainStyleDim = isMainRow ? cs.width : cs.height
1833
+ const mainOwner = isMainRow ? ownerWidth : ownerHeight
1834
+ const resolved = resolveValue(mainStyleDim, mainOwner)
1835
+
1836
+ if (isDefined(resolved)) {
1837
+ const b = Math.max(0, resolved)
1838
+ child._fbBasis = b
1839
+ child._fbOwnerW = ownerWidth
1840
+ child._fbOwnerH = ownerHeight
1841
+ child._fbAvailMain = availableMain
1842
+ child._fbAvailCross = availableCross
1843
+ child._fbCrossMode = crossMode
1844
+ child._fbGen = _generation
1845
+
1846
+ return b
1847
+ }
1848
+
1849
+ const crossStyleDim = isMainRow ? cs.height : cs.width
1850
+ const crossOwner = isMainRow ? ownerHeight : ownerWidth
1851
+ let crossConstraint = resolveValue(crossStyleDim, crossOwner)
1852
+
1853
+ let crossConstraintMode: MeasureMode = isDefined(crossConstraint) ? MeasureMode.Exactly : MeasureMode.Undefined
1854
+
1855
+ if (!isDefined(crossConstraint) && isDefined(availableCross)) {
1856
+ crossConstraint = availableCross
1857
+ crossConstraintMode =
1858
+ crossMode === MeasureMode.Exactly && isStretchAlign(child) ? MeasureMode.Exactly : MeasureMode.AtMost
1859
+ }
1860
+
1861
+ let mainConstraint = NaN
1862
+ let mainConstraintMode: MeasureMode = MeasureMode.Undefined
1863
+
1864
+ if (isMainRow && isDefined(availableMain) && hasMeasureFuncInSubtree(child)) {
1865
+ mainConstraint = availableMain
1866
+ mainConstraintMode = MeasureMode.AtMost
1867
+ }
1868
+
1869
+ const mw = isMainRow ? mainConstraint : crossConstraint
1870
+ const mh = isMainRow ? crossConstraint : mainConstraint
1871
+ const mwMode = isMainRow ? mainConstraintMode : crossConstraintMode
1872
+ const mhMode = isMainRow ? crossConstraintMode : mainConstraintMode
1873
+ layoutNode(child, mw, mh, mwMode, mhMode, ownerWidth, ownerHeight, false)
1874
+ const b = isMainRow ? child.layout.width : child.layout.height
1875
+ child._fbBasis = b
1876
+ child._fbOwnerW = ownerWidth
1877
+ child._fbOwnerH = ownerHeight
1878
+ child._fbAvailMain = availableMain
1879
+ child._fbAvailCross = availableCross
1880
+ child._fbCrossMode = crossMode
1881
+ child._fbGen = _generation
1882
+
1883
+ return b
1884
+ }
1885
+
1886
+ function hasMeasureFuncInSubtree(node: Node): boolean {
1887
+ if (node.measureFunc) {
1888
+ return true
1889
+ }
1890
+
1891
+ for (const c of node.children) {
1892
+ if (hasMeasureFuncInSubtree(c)) {
1893
+ return true
1894
+ }
1895
+ }
1896
+
1897
+ return false
1898
+ }
1899
+
1900
+ function resolveFlexibleLengths(
1901
+ children: Node[],
1902
+ availableInnerMain: number,
1903
+ totalFlexBasis: number,
1904
+ isMainRow: boolean,
1905
+ ownerW: number,
1906
+ ownerH: number
1907
+ ): void {
1908
+ const n = children.length
1909
+ const frozen: boolean[] = new Array(n).fill(false)
1910
+
1911
+ const initialFree = isDefined(availableInnerMain) ? availableInnerMain - totalFlexBasis : 0
1912
+
1913
+ for (let i = 0; i < n; i++) {
1914
+ const c = children[i]!
1915
+ const clamped = boundAxis(c.style, isMainRow, c._flexBasis, ownerW, ownerH)
1916
+
1917
+ const inflexible =
1918
+ !isDefined(availableInnerMain) || (initialFree >= 0 ? c.style.flexGrow === 0 : c.style.flexShrink === 0)
1919
+
1920
+ if (inflexible) {
1921
+ c._mainSize = Math.max(0, clamped)
1922
+ frozen[i] = true
1923
+ } else {
1924
+ c._mainSize = c._flexBasis
1925
+ }
1926
+ }
1927
+
1928
+ const unclamped: number[] = new Array(n)
1929
+
1930
+ for (let iter = 0; iter <= n; iter++) {
1931
+ let frozenDelta = 0
1932
+ let totalGrow = 0
1933
+ let totalShrinkScaled = 0
1934
+ let unfrozenCount = 0
1935
+
1936
+ for (let i = 0; i < n; i++) {
1937
+ const c = children[i]!
1938
+
1939
+ if (frozen[i]) {
1940
+ frozenDelta += c._mainSize - c._flexBasis
1941
+ } else {
1942
+ totalGrow += c.style.flexGrow
1943
+ totalShrinkScaled += c.style.flexShrink * c._flexBasis
1944
+ unfrozenCount++
1945
+ }
1946
+ }
1947
+
1948
+ if (unfrozenCount === 0) {
1949
+ break
1950
+ }
1951
+
1952
+ let remaining = initialFree - frozenDelta
1953
+
1954
+ if (remaining > 0 && totalGrow > 0 && totalGrow < 1) {
1955
+ const scaled = initialFree * totalGrow
1956
+
1957
+ if (scaled < remaining) {
1958
+ remaining = scaled
1959
+ }
1960
+ } else if (remaining < 0 && totalShrinkScaled > 0) {
1961
+ let totalShrink = 0
1962
+
1963
+ for (let i = 0; i < n; i++) {
1964
+ if (!frozen[i]) {
1965
+ totalShrink += children[i]!.style.flexShrink
1966
+ }
1967
+ }
1968
+
1969
+ if (totalShrink < 1) {
1970
+ const scaled = initialFree * totalShrink
1971
+
1972
+ if (scaled > remaining) {
1973
+ remaining = scaled
1974
+ }
1975
+ }
1976
+ }
1977
+
1978
+ let totalViolation = 0
1979
+
1980
+ for (let i = 0; i < n; i++) {
1981
+ if (frozen[i]) {
1982
+ continue
1983
+ }
1984
+
1985
+ const c = children[i]!
1986
+ let t = c._flexBasis
1987
+
1988
+ if (remaining > 0 && totalGrow > 0) {
1989
+ t += (remaining * c.style.flexGrow) / totalGrow
1990
+ } else if (remaining < 0 && totalShrinkScaled > 0) {
1991
+ t += (remaining * (c.style.flexShrink * c._flexBasis)) / totalShrinkScaled
1992
+ }
1993
+
1994
+ unclamped[i] = t
1995
+ const clamped = Math.max(0, boundAxis(c.style, isMainRow, t, ownerW, ownerH))
1996
+ c._mainSize = clamped
1997
+ totalViolation += clamped - t
1998
+ }
1999
+
2000
+ if (totalViolation === 0) {
2001
+ break
2002
+ }
2003
+
2004
+ let anyFrozen = false
2005
+
2006
+ for (let i = 0; i < n; i++) {
2007
+ if (frozen[i]) {
2008
+ continue
2009
+ }
2010
+
2011
+ const v = children[i]!._mainSize - unclamped[i]!
2012
+
2013
+ if ((totalViolation > 0 && v > 0) || (totalViolation < 0 && v < 0)) {
2014
+ frozen[i] = true
2015
+ anyFrozen = true
2016
+ }
2017
+ }
2018
+
2019
+ if (!anyFrozen) {
2020
+ break
2021
+ }
2022
+ }
2023
+ }
2024
+
2025
+ function isStretchAlign(child: Node): boolean {
2026
+ const p = child.parent
2027
+
2028
+ if (!p) {
2029
+ return false
2030
+ }
2031
+
2032
+ const align = child.style.alignSelf === Align.Auto ? p.style.alignItems : child.style.alignSelf
2033
+
2034
+ return align === Align.Stretch
2035
+ }
2036
+
2037
+ function resolveChildAlign(parent: Node, child: Node): Align {
2038
+ return child.style.alignSelf === Align.Auto ? parent.style.alignItems : child.style.alignSelf
2039
+ }
2040
+
2041
+ function calculateBaseline(node: Node): number {
2042
+ let baselineChild: Node | null = null
2043
+
2044
+ for (const c of node.children) {
2045
+ if (c._lineIndex > 0) {
2046
+ break
2047
+ }
2048
+
2049
+ if (c.style.positionType === PositionType.Absolute) {
2050
+ continue
2051
+ }
2052
+
2053
+ if (c.style.display === Display.None) {
2054
+ continue
2055
+ }
2056
+
2057
+ if (resolveChildAlign(node, c) === Align.Baseline || c.isReferenceBaseline_) {
2058
+ baselineChild = c
2059
+
2060
+ break
2061
+ }
2062
+
2063
+ if (baselineChild === null) {
2064
+ baselineChild = c
2065
+ }
2066
+ }
2067
+
2068
+ if (baselineChild === null) {
2069
+ return node.layout.height
2070
+ }
2071
+
2072
+ return calculateBaseline(baselineChild) + baselineChild.layout.top
2073
+ }
2074
+
2075
+ function isBaselineLayout(node: Node, flowChildren: Node[]): boolean {
2076
+ if (!isRow(node.style.flexDirection)) {
2077
+ return false
2078
+ }
2079
+
2080
+ if (node.style.alignItems === Align.Baseline) {
2081
+ return true
2082
+ }
2083
+
2084
+ for (const c of flowChildren) {
2085
+ if (c.style.alignSelf === Align.Baseline) {
2086
+ return true
2087
+ }
2088
+ }
2089
+
2090
+ return false
2091
+ }
2092
+
2093
+ function childMarginForAxis(child: Node, axis: FlexDirection, ownerWidth: number): number {
2094
+ if (!child._hasMargin) {
2095
+ return 0
2096
+ }
2097
+
2098
+ const lead = resolveEdge(child.style.margin, leadingEdge(axis), ownerWidth)
2099
+ const trail = resolveEdge(child.style.margin, trailingEdge(axis), ownerWidth)
2100
+
2101
+ return lead + trail
2102
+ }
2103
+
2104
+ function resolveGap(style: Style, gutter: Gutter, ownerSize: number): number {
2105
+ let v = style.gap[gutter]!
2106
+
2107
+ if (v.unit === Unit.Undefined) {
2108
+ v = style.gap[Gutter.All]!
2109
+ }
2110
+
2111
+ const r = resolveValue(v, ownerSize)
2112
+
2113
+ return isDefined(r) ? Math.max(0, r) : 0
2114
+ }
2115
+
2116
+ function boundAxis(style: Style, isWidth: boolean, value: number, ownerWidth: number, ownerHeight: number): number {
2117
+ const minV = isWidth ? style.minWidth : style.minHeight
2118
+ const maxV = isWidth ? style.maxWidth : style.maxHeight
2119
+ const minU = minV.unit
2120
+ const maxU = maxV.unit
2121
+
2122
+ if (minU === 0 && maxU === 0) {
2123
+ return value
2124
+ }
2125
+
2126
+ const owner = isWidth ? ownerWidth : ownerHeight
2127
+ let v = value
2128
+
2129
+ if (maxU === 1) {
2130
+ if (v > maxV.value) {
2131
+ v = maxV.value
2132
+ }
2133
+ } else if (maxU === 2) {
2134
+ const m = (maxV.value * owner) / 100
2135
+
2136
+ if (m === m && v > m) {
2137
+ v = m
2138
+ }
2139
+ }
2140
+
2141
+ if (minU === 1) {
2142
+ if (v < minV.value) {
2143
+ v = minV.value
2144
+ }
2145
+ } else if (minU === 2) {
2146
+ const m = (minV.value * owner) / 100
2147
+
2148
+ if (m === m && v < m) {
2149
+ v = m
2150
+ }
2151
+ }
2152
+
2153
+ return v
2154
+ }
2155
+
2156
+ function zeroLayoutRecursive(node: Node): void {
2157
+ for (const c of node.children) {
2158
+ c.layout.left = 0
2159
+ c.layout.top = 0
2160
+ c.layout.width = 0
2161
+ c.layout.height = 0
2162
+ c.isDirty_ = true
2163
+ c._hasL = false
2164
+ c._hasM = false
2165
+ zeroLayoutRecursive(c)
2166
+ }
2167
+ }
2168
+
2169
+ function collectLayoutChildren(node: Node, flow: Node[], abs: Node[]): void {
2170
+ for (const c of node.children) {
2171
+ const disp = c.style.display
2172
+
2173
+ if (disp === Display.None) {
2174
+ c.layout.left = 0
2175
+ c.layout.top = 0
2176
+ c.layout.width = 0
2177
+ c.layout.height = 0
2178
+ zeroLayoutRecursive(c)
2179
+ } else if (disp === Display.Contents) {
2180
+ c.layout.left = 0
2181
+ c.layout.top = 0
2182
+ c.layout.width = 0
2183
+ c.layout.height = 0
2184
+ collectLayoutChildren(c, flow, abs)
2185
+ } else if (c.style.positionType === PositionType.Absolute) {
2186
+ abs.push(c)
2187
+ } else {
2188
+ flow.push(c)
2189
+ }
2190
+ }
2191
+ }
2192
+
2193
+ function roundLayout(node: Node, scale: number, absLeft: number, absTop: number): void {
2194
+ if (scale === 0) {
2195
+ return
2196
+ }
2197
+
2198
+ const l = node.layout
2199
+ const nodeLeft = l.left
2200
+ const nodeTop = l.top
2201
+ const nodeWidth = l.width
2202
+ const nodeHeight = l.height
2203
+ const absNodeLeft = absLeft + nodeLeft
2204
+ const absNodeTop = absTop + nodeTop
2205
+ const isText = node.measureFunc !== null
2206
+ l.left = roundValue(nodeLeft, scale, false, isText)
2207
+ l.top = roundValue(nodeTop, scale, false, isText)
2208
+ const absRight = absNodeLeft + nodeWidth
2209
+ const absBottom = absNodeTop + nodeHeight
2210
+ const hasFracW = !isWholeNumber(nodeWidth * scale)
2211
+ const hasFracH = !isWholeNumber(nodeHeight * scale)
2212
+ l.width =
2213
+ roundValue(absRight, scale, isText && hasFracW, isText && !hasFracW) - roundValue(absNodeLeft, scale, false, isText)
2214
+ l.height =
2215
+ roundValue(absBottom, scale, isText && hasFracH, isText && !hasFracH) - roundValue(absNodeTop, scale, false, isText)
2216
+
2217
+ for (const c of node.children) {
2218
+ roundLayout(c, scale, absNodeLeft, absNodeTop)
2219
+ }
2220
+ }
2221
+
2222
+ function isWholeNumber(v: number): boolean {
2223
+ const frac = v - Math.floor(v)
2224
+
2225
+ return frac < 0.0001 || frac > 0.9999
2226
+ }
2227
+
2228
+ function roundValue(v: number, scale: number, forceCeil: boolean, forceFloor: boolean): number {
2229
+ let scaled = v * scale
2230
+ let frac = scaled - Math.floor(scaled)
2231
+
2232
+ if (frac < 0) {
2233
+ frac += 1
2234
+ }
2235
+
2236
+ if (frac < 0.0001) {
2237
+ scaled = Math.floor(scaled)
2238
+ } else if (frac > 0.9999) {
2239
+ scaled = Math.ceil(scaled)
2240
+ } else if (forceCeil) {
2241
+ scaled = Math.ceil(scaled)
2242
+ } else if (forceFloor) {
2243
+ scaled = Math.floor(scaled)
2244
+ } else {
2245
+ scaled = Math.floor(scaled) + (frac >= 0.4999 ? 1 : 0)
2246
+ }
2247
+
2248
+ return scaled / scale
2249
+ }
2250
+
2251
+ function parseDimension(v: number | string | undefined): Value {
2252
+ if (v === undefined) {
2253
+ return UNDEFINED_VALUE
2254
+ }
2255
+
2256
+ if (v === 'auto') {
2257
+ return AUTO_VALUE
2258
+ }
2259
+
2260
+ if (typeof v === 'number') {
2261
+ return Number.isFinite(v) ? pointValue(v) : UNDEFINED_VALUE
2262
+ }
2263
+
2264
+ if (typeof v === 'string' && v.endsWith('%')) {
2265
+ return percentValue(parseFloat(v))
2266
+ }
2267
+
2268
+ const n = parseFloat(v)
2269
+
2270
+ return isNaN(n) ? UNDEFINED_VALUE : pointValue(n)
2271
+ }
2272
+
2273
+ function physicalEdge(edge: Edge): number {
2274
+ switch (edge) {
2275
+ case Edge.Left:
2276
+
2277
+ case Edge.Start:
2278
+ return EDGE_LEFT
2279
+
2280
+ case Edge.Top:
2281
+ return EDGE_TOP
2282
+
2283
+ case Edge.Right:
2284
+
2285
+ case Edge.End:
2286
+ return EDGE_RIGHT
2287
+
2288
+ case Edge.Bottom:
2289
+ return EDGE_BOTTOM
2290
+
2291
+ default:
2292
+ return EDGE_LEFT
2293
+ }
2294
+ }
2295
+
2296
+ export type Yoga = {
2297
+ Config: {
2298
+ create(): Config
2299
+ destroy(config: Config): void
2300
+ }
2301
+ Node: {
2302
+ create(config?: Config): Node
2303
+ createDefault(): Node
2304
+ createWithConfig(config: Config): Node
2305
+ destroy(node: Node): void
2306
+ }
2307
+ }
2308
+
2309
+ const YOGA_INSTANCE: Yoga = {
2310
+ Config: {
2311
+ create: createConfig,
2312
+ destroy() {}
2313
+ },
2314
+ Node: {
2315
+ create: (config?: Config) => new Node(config),
2316
+ createDefault: () => new Node(),
2317
+ createWithConfig: (config: Config) => new Node(config),
2318
+ destroy() {}
2319
+ }
2320
+ }
2321
+
2322
+ export function loadYoga(): Promise<Yoga> {
2323
+ return Promise.resolve(YOGA_INSTANCE)
2324
+ }
2325
+
2326
+ export default YOGA_INSTANCE