@jimka/typescript-ui 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/dist/lib/{AbstractBooleanInput-DSwKBAic.js → AbstractBooleanInput-CbW7ZrDT.js} +2 -2
  2. package/dist/lib/{AbstractBooleanInput-DSwKBAic.js.map → AbstractBooleanInput-CbW7ZrDT.js.map} +1 -1
  3. package/dist/lib/{AbstractInput-BmWGJTs1.js → AbstractInput-B10DfLOf.js} +2 -2
  4. package/dist/lib/{AbstractInput-BmWGJTs1.js.map → AbstractInput-B10DfLOf.js.map} +1 -1
  5. package/dist/lib/Anchor-BsblS5it.js +2 -0
  6. package/dist/lib/Anchor-BsblS5it.js.map +1 -0
  7. package/dist/lib/AnchorConstraints-Bfkt8019.js +2 -0
  8. package/dist/lib/AnchorConstraints-Bfkt8019.js.map +1 -0
  9. package/dist/lib/{AnimatedDropdown-DKas40B-.js → AnimatedDropdown-kL47HPGP.js} +2 -2
  10. package/dist/lib/{AnimatedDropdown-DKas40B-.js.map → AnimatedDropdown-kL47HPGP.js.map} +1 -1
  11. package/dist/lib/{Border-Bz29z-_7.js → Border-CNS6aEXB.js} +2 -2
  12. package/dist/lib/Border-CNS6aEXB.js.map +1 -0
  13. package/dist/lib/Button-T16zSZip.js +2 -0
  14. package/dist/lib/Button-T16zSZip.js.map +1 -0
  15. package/dist/lib/{Card-BdfbvOD_.js → Card-CD3jxshU.js} +2 -2
  16. package/dist/lib/{Card-BdfbvOD_.js.map → Card-CD3jxshU.js.map} +1 -1
  17. package/dist/lib/CodeEditor-BGlB232h.js +2 -0
  18. package/dist/lib/CodeEditor-BGlB232h.js.map +1 -0
  19. package/dist/lib/ComboBox-C9FYMuLv.js +2 -0
  20. package/dist/lib/ComboBox-C9FYMuLv.js.map +1 -0
  21. package/dist/lib/Component-w65rPK75.js +2 -0
  22. package/dist/lib/Component-w65rPK75.js.map +1 -0
  23. package/dist/lib/Container-C7RPLQEc.js +2 -0
  24. package/dist/lib/{Container-CAQpj4yb.js.map → Container-C7RPLQEc.js.map} +1 -1
  25. package/dist/lib/DOM-Ba8YRVel.js +2 -0
  26. package/dist/lib/{DOM-67StIm5G.js.map → DOM-Ba8YRVel.js.map} +1 -1
  27. package/dist/lib/DragManager-UvPHSoRm.js +2 -0
  28. package/dist/lib/{DragManager-CHWCe3-8.js.map → DragManager-UvPHSoRm.js.map} +1 -1
  29. package/dist/lib/{FieldDecorator-CgAGcqCk.js → FieldDecorator-HG65hEtk.js} +2 -2
  30. package/dist/lib/{FieldDecorator-CgAGcqCk.js.map → FieldDecorator-HG65hEtk.js.map} +1 -1
  31. package/dist/lib/{Fit-DIYt2aQB.js → Fit-Cg3dPyZg.js} +2 -2
  32. package/dist/lib/{Fit-DIYt2aQB.js.map → Fit-Cg3dPyZg.js.map} +1 -1
  33. package/dist/lib/FloatingPanel-D5buuVrQ.js +2 -0
  34. package/dist/lib/FloatingPanel-D5buuVrQ.js.map +1 -0
  35. package/dist/lib/{Glyph-CeAIWyPB.js → Glyph-DeJF_zsR.js} +2 -2
  36. package/dist/lib/{Glyph-CeAIWyPB.js.map → Glyph-DeJF_zsR.js.map} +1 -1
  37. package/dist/lib/{Grid-ViA0joow.js → Grid-BYBohJIA.js} +2 -2
  38. package/dist/lib/{Grid-ViA0joow.js.map → Grid-BYBohJIA.js.map} +1 -1
  39. package/dist/lib/{GridConstraints-B1rxCw9B.js → GridConstraints-Bts284FI.js} +2 -2
  40. package/dist/lib/{GridConstraints-B1rxCw9B.js.map → GridConstraints-Bts284FI.js.map} +1 -1
  41. package/dist/lib/{Header-mKaqgfat.js → Header-BIFJK9nR.js} +2 -2
  42. package/dist/lib/{Header-mKaqgfat.js.map → Header-BIFJK9nR.js.map} +1 -1
  43. package/dist/lib/{IconText-BqwXA82-.js → IconText-Dsb1xS-E.js} +2 -2
  44. package/dist/lib/{IconText-BqwXA82-.js.map → IconText-Dsb1xS-E.js.map} +1 -1
  45. package/dist/lib/LanguageRegistry-CcVnbKuh.js +2 -0
  46. package/dist/lib/LanguageRegistry-CcVnbKuh.js.map +1 -0
  47. package/dist/lib/LayoutConstraints-LIHYYd2F.js +2 -0
  48. package/dist/lib/LayoutConstraints-LIHYYd2F.js.map +1 -0
  49. package/dist/lib/LayoutSerialization-ySzY1h2l.js +2 -0
  50. package/dist/lib/{LayoutSerialization-D82UtnDD.js.map → LayoutSerialization-ySzY1h2l.js.map} +1 -1
  51. package/dist/lib/LayoutSizes-DKDK1Cle.js +2 -0
  52. package/dist/lib/LayoutSizes-DKDK1Cle.js.map +1 -0
  53. package/dist/lib/List-BPd-IXZR.js +2 -0
  54. package/dist/lib/{List-CUntS8ux.js.map → List-BPd-IXZR.js.map} +1 -1
  55. package/dist/lib/MemoryStore-BgP7-Uzn.js +2 -0
  56. package/dist/lib/{MemoryStore-DT6iWWco.js.map → MemoryStore-BgP7-Uzn.js.map} +1 -1
  57. package/dist/lib/Menu-C0roOCY7.js +2 -0
  58. package/dist/lib/Menu-C0roOCY7.js.map +1 -0
  59. package/dist/lib/MenuButton-BR4KOFld.js +2 -0
  60. package/dist/lib/MenuButton-BR4KOFld.js.map +1 -0
  61. package/dist/lib/Panel-CpNQTLNF.js +2 -0
  62. package/dist/lib/{Panel-D2X33qR6.js.map → Panel-CpNQTLNF.js.map} +1 -1
  63. package/dist/lib/{Position-Ck_KD4cR.js → Position-PBVBW1JS.js} +2 -2
  64. package/dist/lib/{Position-Ck_KD4cR.js.map → Position-PBVBW1JS.js.map} +1 -1
  65. package/dist/lib/{ProgressSpinner-DCyq02pd.js → ProgressSpinner-lAsK26C-.js} +2 -2
  66. package/dist/lib/{ProgressSpinner-DCyq02pd.js.map → ProgressSpinner-lAsK26C-.js.map} +1 -1
  67. package/dist/lib/RadioButton-CCcIaL54.js +2 -0
  68. package/dist/lib/RadioButton-CCcIaL54.js.map +1 -0
  69. package/dist/lib/{RovingTabIndex-DFJyoveq.js → RovingTabIndex-C2Vzq0IX.js} +2 -2
  70. package/dist/lib/{RovingTabIndex-DFJyoveq.js.map → RovingTabIndex-C2Vzq0IX.js.map} +1 -1
  71. package/dist/lib/Scrollbar-C3ZZyZ1e.js +2 -0
  72. package/dist/lib/Scrollbar-C3ZZyZ1e.js.map +1 -0
  73. package/dist/lib/Slider-DZ9drUxn.js +2 -0
  74. package/dist/lib/Slider-DZ9drUxn.js.map +1 -0
  75. package/dist/lib/Spacer-SDhOMp2g.js +2 -0
  76. package/dist/lib/{Spacer-D159iJy9.js.map → Spacer-SDhOMp2g.js.map} +1 -1
  77. package/dist/lib/TabButton-DNo4ZgV8.js +2 -0
  78. package/dist/lib/TabButton-DNo4ZgV8.js.map +1 -0
  79. package/dist/lib/Text-CdHf3B-1.js +2 -0
  80. package/dist/lib/Text-CdHf3B-1.js.map +1 -0
  81. package/dist/lib/{Tooltip-DzK6LxUt.js → Tooltip-B_UF5bXD.js} +2 -2
  82. package/dist/lib/{Tooltip-DzK6LxUt.js.map → Tooltip-B_UF5bXD.js.map} +1 -1
  83. package/dist/lib/Tree-C7qLbIYH.js +2 -0
  84. package/dist/lib/Tree-C7qLbIYH.js.map +1 -0
  85. package/dist/lib/VBox-32fxpkDl.js +2 -0
  86. package/dist/lib/VBox-32fxpkDl.js.map +1 -0
  87. package/dist/lib/{Validator-Du8PqS5i.js → Validator-Cjs1EU5Q.js} +2 -2
  88. package/dist/lib/{Validator-Du8PqS5i.js.map → Validator-Cjs1EU5Q.js.map} +1 -1
  89. package/dist/lib/{VirtualScroller-zQr-vKrO.js → VirtualScroller-cvFNMS7U.js} +2 -2
  90. package/dist/lib/{VirtualScroller-zQr-vKrO.js.map → VirtualScroller-cvFNMS7U.js.map} +1 -1
  91. package/dist/lib/component/button.es.js +1 -1
  92. package/dist/lib/component/button.es.js.map +1 -1
  93. package/dist/lib/component/chart.es.js +1 -1
  94. package/dist/lib/component/chart.es.js.map +1 -1
  95. package/dist/lib/component/container.es.js +1 -1
  96. package/dist/lib/component/container.es.js.map +1 -1
  97. package/dist/lib/component/diagram.es.js +1 -1
  98. package/dist/lib/component/diagram.es.js.map +1 -1
  99. package/dist/lib/component/display.es.js +1 -1
  100. package/dist/lib/component/display.es.js.map +1 -1
  101. package/dist/lib/component/editor.es.js +3 -3
  102. package/dist/lib/component/editor.es.js.map +1 -1
  103. package/dist/lib/component/input.es.js +1 -1
  104. package/dist/lib/component/input.es.js.map +1 -1
  105. package/dist/lib/component/list.es.js +1 -1
  106. package/dist/lib/component/list.es.js.map +1 -1
  107. package/dist/lib/component/menubar.es.js +1 -1
  108. package/dist/lib/component/menubar.es.js.map +1 -1
  109. package/dist/lib/component/table.es.js +2 -2
  110. package/dist/lib/component/table.es.js.map +1 -1
  111. package/dist/lib/component/tree.es.js +1 -1
  112. package/dist/lib/component/tree.es.js.map +1 -1
  113. package/dist/lib/core.es.js +1 -1
  114. package/dist/lib/core.es.js.map +1 -1
  115. package/dist/lib/data.es.js +1 -1
  116. package/dist/lib/glyphs/solid/index.es.js +1 -1
  117. package/dist/lib/languages-Dl8qdL8a.js +2 -0
  118. package/dist/lib/languages-Dl8qdL8a.js.map +1 -0
  119. package/dist/lib/layout.es.js +1 -1
  120. package/dist/lib/layout.es.js.map +1 -1
  121. package/dist/lib/overlay.es.js +1 -1
  122. package/dist/lib/overlay.es.js.map +1 -1
  123. package/dist/lib/primitive.es.js +1 -1
  124. package/dist/lib/router.es.js +1 -1
  125. package/dist/lib/router.es.js.map +1 -1
  126. package/dist/lib/selectionsEqual-BrTxPMmK.js +2 -0
  127. package/dist/lib/{selectionsEqual-4r5R7pTK.js.map → selectionsEqual-BrTxPMmK.js.map} +1 -1
  128. package/dist/lib/types/component/button/MenuButton.d.ts +1 -0
  129. package/dist/lib/types/component/button/SplitButton.d.ts +1 -0
  130. package/dist/lib/types/component/button/TabButton.d.ts +2 -1
  131. package/dist/lib/types/component/button/ToggleButton.d.ts +1 -1
  132. package/dist/lib/types/component/chart/ChartLegend.d.ts +1 -2
  133. package/dist/lib/types/component/container/CollapseButton.d.ts +0 -1
  134. package/dist/lib/types/component/container/FloatingPanel.d.ts +23 -0
  135. package/dist/lib/types/component/container/ScrollStrip.d.ts +1 -1
  136. package/dist/lib/types/component/container/Scrollbar.d.ts +1 -3
  137. package/dist/lib/types/component/container/TabBar.d.ts +1 -1
  138. package/dist/lib/types/component/container/TabPanel.d.ts +3 -0
  139. package/dist/lib/types/component/container/index.d.ts +2 -0
  140. package/dist/lib/types/component/diagram/DiagramGroupNode.d.ts +1 -1
  141. package/dist/lib/types/component/display/Markdown.d.ts +42 -1
  142. package/dist/lib/types/component/display/MarkdownMinimap.d.ts +38 -0
  143. package/dist/lib/types/component/display/MarkdownViewer.d.ts +60 -0
  144. package/dist/lib/types/component/display/index.d.ts +6 -0
  145. package/dist/lib/types/component/editor/CodeEditor.d.ts +13 -0
  146. package/dist/lib/types/component/editor/index.d.ts +1 -1
  147. package/dist/lib/types/component/input/Checkbox.d.ts +1 -1
  148. package/dist/lib/types/component/input/Link.d.ts +0 -1
  149. package/dist/lib/types/component/input/RadioButton.d.ts +1 -1
  150. package/dist/lib/types/component/input/Slider.d.ts +1 -1
  151. package/dist/lib/types/component/input/Text.d.ts +0 -2
  152. package/dist/lib/types/component/input/Toggle.d.ts +1 -1
  153. package/dist/lib/types/component/menubar/MenuBar.d.ts +2 -1
  154. package/dist/lib/types/component/menubar/MenuBarButton.d.ts +0 -1
  155. package/dist/lib/types/component/menubar/ToolBar.d.ts +2 -0
  156. package/dist/lib/types/component/table/Body.d.ts +1 -0
  157. package/dist/lib/types/component/table/Table.d.ts +1 -0
  158. package/dist/lib/types/component/table/cell/SortPriorityBadge.d.ts +1 -1
  159. package/dist/lib/types/component/table/cell/editor/CellEditorPool.d.ts +1 -0
  160. package/dist/lib/types/component/table/cell/editor/Date.d.ts +1 -0
  161. package/dist/lib/types/component/table/cell/editor/DateTime.d.ts +1 -0
  162. package/dist/lib/types/component/table/cell/editor/Time.d.ts +1 -0
  163. package/dist/lib/types/component/tree/Tree.d.ts +9 -1
  164. package/dist/lib/types/component/tree/index.d.ts +1 -1
  165. package/dist/lib/types/component/tree/renderer/Label.d.ts +1 -1
  166. package/dist/lib/types/core/BorderWidths.d.ts +12 -0
  167. package/dist/lib/types/core/Component.d.ts +6 -0
  168. package/dist/lib/types/core/Event.d.ts +2 -0
  169. package/dist/lib/types/core/Theme.d.ts +4 -2
  170. package/dist/lib/types/layout/LayoutConstraints.d.ts +1 -0
  171. package/dist/lib/types/layout/LayoutManager.d.ts +8 -0
  172. package/dist/lib/types/layout/LayoutSerialization.d.ts +3 -0
  173. package/dist/lib/types/overlay/Dock.d.ts +1 -0
  174. package/dist/lib/validation.es.js +1 -1
  175. package/llms.txt +3 -0
  176. package/package.json +15 -15
  177. package/dist/lib/AnchorConstraints-CVrMP9rz.js +0 -2
  178. package/dist/lib/AnchorConstraints-CVrMP9rz.js.map +0 -1
  179. package/dist/lib/Border-Bz29z-_7.js.map +0 -1
  180. package/dist/lib/Button-bjpWruNc.js +0 -2
  181. package/dist/lib/Button-bjpWruNc.js.map +0 -1
  182. package/dist/lib/ComboBox-CBw2VLLN.js +0 -2
  183. package/dist/lib/ComboBox-CBw2VLLN.js.map +0 -1
  184. package/dist/lib/Component-DHqrPwAw.js +0 -2
  185. package/dist/lib/Component-DHqrPwAw.js.map +0 -1
  186. package/dist/lib/Container-CAQpj4yb.js +0 -2
  187. package/dist/lib/DOM-67StIm5G.js +0 -2
  188. package/dist/lib/DragManager-CHWCe3-8.js +0 -2
  189. package/dist/lib/LayoutConstraints-DkctJZXB.js +0 -2
  190. package/dist/lib/LayoutConstraints-DkctJZXB.js.map +0 -1
  191. package/dist/lib/LayoutSerialization-D82UtnDD.js +0 -2
  192. package/dist/lib/LayoutSizes-DG9aW9k6.js +0 -2
  193. package/dist/lib/LayoutSizes-DG9aW9k6.js.map +0 -1
  194. package/dist/lib/List-CUntS8ux.js +0 -2
  195. package/dist/lib/MemoryStore-DT6iWWco.js +0 -2
  196. package/dist/lib/Menu-B_-SQj72.js +0 -2
  197. package/dist/lib/Menu-B_-SQj72.js.map +0 -1
  198. package/dist/lib/MenuButton-C79l8Ysf.js +0 -2
  199. package/dist/lib/MenuButton-C79l8Ysf.js.map +0 -1
  200. package/dist/lib/Panel-D2X33qR6.js +0 -2
  201. package/dist/lib/RadioButton-BJIAQkII.js +0 -2
  202. package/dist/lib/RadioButton-BJIAQkII.js.map +0 -1
  203. package/dist/lib/Scrollbar-CSFK-Y57.js +0 -2
  204. package/dist/lib/Scrollbar-CSFK-Y57.js.map +0 -1
  205. package/dist/lib/Slider-C-kQQYCj.js +0 -2
  206. package/dist/lib/Slider-C-kQQYCj.js.map +0 -1
  207. package/dist/lib/Spacer-D159iJy9.js +0 -2
  208. package/dist/lib/TabButton-CHkXBgCj.js +0 -2
  209. package/dist/lib/TabButton-CHkXBgCj.js.map +0 -1
  210. package/dist/lib/Text-D5pg7taZ.js +0 -2
  211. package/dist/lib/Text-D5pg7taZ.js.map +0 -1
  212. package/dist/lib/VBox-BNegDPs_.js +0 -2
  213. package/dist/lib/VBox-BNegDPs_.js.map +0 -1
  214. package/dist/lib/selectionsEqual-4r5R7pTK.js +0 -2
@@ -0,0 +1,2 @@
1
+ import{t as e}from"./rolldown-runtime-O8uOSEUP.js";import{r as t}from"./LanguageRegistry-CcVnbKuh.js";function formatWithPrettier(e,t){return async(n,r)=>{let[{formatWithCursor:i},a]=await Promise.all([import(`prettier/standalone`),t()]);return i(n,{parser:e,plugins:a,cursorOffset:r})}}var formatWithSql=async(e,t)=>{let{format:n}=await import(`sql-formatter`),r=n(e);return{formatted:r,cursorOffset:Math.min(t,r.length)}},n=e({});async function loadBabelPlugins(){let[e,t]=await Promise.all([import(`prettier/plugins/babel`),import(`prettier/plugins/estree`)]);return[e,t]}t({id:`javascript`,label:`JavaScript / TypeScript`,loadExtension:async()=>{let{javascript:e}=await import(`@codemirror/lang-javascript`);return e({typescript:!0})},loadFormatter:async()=>formatWithPrettier(`babel-ts`,loadBabelPlugins)}),t({id:`json`,label:`JSON`,loadExtension:async()=>{let{json:e}=await import(`@codemirror/lang-json`);return e()},loadFormatter:async()=>formatWithPrettier(`json`,loadBabelPlugins)}),t({id:`html`,label:`HTML`,loadExtension:async()=>{let{html:e}=await import(`@codemirror/lang-html`);return e()},loadFormatter:async()=>formatWithPrettier(`html`,async()=>[await import(`prettier/plugins/html`)])}),t({id:`sql`,label:`SQL`,loadExtension:async()=>{let{sql:e}=await import(`@codemirror/lang-sql`);return e()},loadFormatter:async()=>formatWithSql}),t({id:`markdown`,label:`Markdown`,loadExtension:async()=>{let{markdown:e}=await import(`@codemirror/lang-markdown`);return e()},loadFormatter:async()=>formatWithPrettier(`markdown`,async()=>[await import(`prettier/plugins/markdown`)])});export{n as t};
2
+ //# sourceMappingURL=languages-Dl8qdL8a.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"languages-Dl8qdL8a.js","names":[],"sources":["../../src/typescript/lib/component/editor/formatters/prettier.ts","../../src/typescript/lib/component/editor/formatters/sql.ts","../../src/typescript/lib/component/editor/languages.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport type { Plugin } from \"prettier\";\nimport type { Formatter } from \"~/component/editor/LanguageRegistry.js\";\n\n/**\n * Builds a Prettier-backed {@link Formatter} for a given parser id.\n *\n * The returned closure dynamically imports `prettier/standalone` and the\n * caller-supplied plugin set on first invocation, so the (large) Prettier\n * standalone bundle only ever loads behind a `format()` call, never as part\n * of the base editor chunk. This adapter is shared by every Prettier-backed\n * language entry in `languages.ts` — each supplies its own parser id and\n * plugin loader (`babel-ts` + the babel/estree plugins for JS/TS, `json` for\n * JSON, `html` for HTML, `markdown` for Markdown).\n *\n * @param parser - The Prettier parser id (e.g. `\"babel-ts\"`, `\"json\"`).\n * @param loadPlugins - Dynamically imports the Prettier plugin modules the\n * parser needs.\n * @returns A {@link Formatter} that formats through Prettier's\n * `formatWithCursor`, which maps the cursor offset through the reformat.\n */\nexport function formatWithPrettier(\n parser: string,\n loadPlugins: () => Promise<Plugin[]>,\n): Formatter {\n return async (source: string, cursorOffset: number) => {\n const [{ formatWithCursor }, plugins] = await Promise.all([\n import(\"prettier/standalone\"),\n loadPlugins(),\n ]);\n\n return formatWithCursor(source, { parser, plugins, cursorOffset });\n };\n}\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport type { Formatter } from \"~/component/editor/LanguageRegistry.js\";\n\n/**\n * SQL formatter adapter backed by `sql-formatter`, dynamically imported on\n * first call so it never lands in the base editor chunk.\n *\n * Unlike Prettier's `formatWithCursor`, `sql-formatter` has no cursor-mapping\n * API, so the old cursor offset is clamped to the formatted document's length\n * rather than mapped to its logically-equivalent position.\n */\nexport const formatWithSql: Formatter = async (source: string, cursorOffset: number) => {\n const { format } = await import(\"sql-formatter\");\n const formatted = format(source);\n\n return { formatted, cursorOffset: Math.min(cursorOffset, formatted.length) };\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\n// Registers the five built-in language definitions as a side effect of\n// importing this module (from the barrel `index.ts`). Every grammar and\n// formatter loader is a dynamic `import()`, so — because the CodeMirror\n// language packages and Prettier/sql-formatter are `external` in the lib\n// build — none of them reach the base editor chunk; each loads only when a\n// consumer actually selects that language or calls `format()`.\n\nimport { registerLanguage } from \"~/component/editor/LanguageRegistry.js\";\nimport { formatWithPrettier } from \"~/component/editor/formatters/prettier.js\";\nimport { formatWithSql } from \"~/component/editor/formatters/sql.js\";\n\n/** Loads the babel + estree plugins Prettier's `babel-ts` and `json` parsers need. */\nasync function loadBabelPlugins() {\n const [babel, estree] = await Promise.all([\n import(\"prettier/plugins/babel\"),\n import(\"prettier/plugins/estree\"),\n ]);\n\n return [babel, estree];\n}\n\nregisterLanguage({\n id: \"javascript\",\n label: \"JavaScript / TypeScript\",\n loadExtension: async () => {\n const { javascript } = await import(\"@codemirror/lang-javascript\");\n\n return javascript({ typescript: true });\n },\n loadFormatter: async () => formatWithPrettier(\"babel-ts\", loadBabelPlugins),\n});\n\nregisterLanguage({\n id: \"json\",\n label: \"JSON\",\n loadExtension: async () => {\n const { json } = await import(\"@codemirror/lang-json\");\n\n return json();\n },\n loadFormatter: async () => formatWithPrettier(\"json\", loadBabelPlugins),\n});\n\nregisterLanguage({\n id: \"html\",\n label: \"HTML\",\n loadExtension: async () => {\n const { html } = await import(\"@codemirror/lang-html\");\n\n return html();\n },\n loadFormatter: async () => formatWithPrettier(\"html\", async () => [await import(\"prettier/plugins/html\")]),\n});\n\nregisterLanguage({\n id: \"sql\",\n label: \"SQL\",\n loadExtension: async () => {\n const { sql } = await import(\"@codemirror/lang-sql\");\n\n return sql();\n },\n loadFormatter: async () => formatWithSql,\n});\n\nregisterLanguage({\n id: \"markdown\",\n label: \"Markdown\",\n loadExtension: async () => {\n const { markdown } = await import(\"@codemirror/lang-markdown\");\n\n return markdown();\n },\n loadFormatter: async () => formatWithPrettier(\"markdown\", async () => [await import(\"prettier/plugins/markdown\")]),\n});\n"],"mappings":"sGAsBA,SAAgB,mBACZ,EACA,EACS,CACT,OAAO,MAAO,EAAgB,IAAyB,CACnD,GAAM,CAAC,CAAE,oBAAoB,GAAW,MAAM,QAAQ,IAAI,CACtD,OAAO,uBACP,EAAY,CAChB,CAAC,EAED,OAAO,EAAiB,EAAQ,CAAE,SAAQ,UAAS,cAAa,CAAC,CACrE,CACJ,CCtBA,IAAa,cAA2B,MAAO,EAAgB,IAAyB,CACpF,GAAM,CAAE,UAAW,MAAM,OAAO,iBAC1B,EAAY,EAAO,CAAM,EAE/B,MAAO,CAAE,YAAW,aAAc,KAAK,IAAI,EAAc,EAAU,MAAM,CAAE,CAC/E,UCHA,eAAe,kBAAmB,CAC9B,GAAM,CAAC,EAAO,GAAU,MAAM,QAAQ,IAAI,CACtC,OAAO,0BACP,OAAO,0BACX,CAAC,EAED,MAAO,CAAC,EAAO,CAAM,CACzB,CAEA,EAAiB,CACb,GAAI,aACJ,MAAO,0BACP,cAAe,SAAY,CACvB,GAAM,CAAE,cAAe,MAAM,OAAO,+BAEpC,OAAO,EAAW,CAAE,WAAY,EAAK,CAAC,CAC1C,EACA,cAAe,SAAY,mBAAmB,WAAY,gBAAgB,CAC9E,CAAC,EAED,EAAiB,CACb,GAAI,OACJ,MAAO,OACP,cAAe,SAAY,CACvB,GAAM,CAAE,QAAS,MAAM,OAAO,yBAE9B,OAAO,EAAK,CAChB,EACA,cAAe,SAAY,mBAAmB,OAAQ,gBAAgB,CAC1E,CAAC,EAED,EAAiB,CACb,GAAI,OACJ,MAAO,OACP,cAAe,SAAY,CACvB,GAAM,CAAE,QAAS,MAAM,OAAO,yBAE9B,OAAO,EAAK,CAChB,EACA,cAAe,SAAY,mBAAmB,OAAQ,SAAY,CAAC,MAAM,OAAO,wBAAwB,CAAC,CAC7G,CAAC,EAED,EAAiB,CACb,GAAI,MACJ,MAAO,MACP,cAAe,SAAY,CACvB,GAAM,CAAE,OAAQ,MAAM,OAAO,wBAE7B,OAAO,EAAI,CACf,EACA,cAAe,SAAY,aAC/B,CAAC,EAED,EAAiB,CACb,GAAI,WACJ,MAAO,WACP,cAAe,SAAY,CACvB,GAAM,CAAE,YAAa,MAAM,OAAO,6BAElC,OAAO,EAAS,CACpB,EACA,cAAe,SAAY,mBAAmB,WAAY,SAAY,CAAC,MAAM,OAAO,4BAA4B,CAAC,CACrH,CAAC"}
@@ -1,2 +1,2 @@
1
- import{a as e,o as t}from"./Position-Ck_KD4cR.js";import{d as n,f as r,h as i,m as a,p as o}from"./Component-DHqrPwAw.js";import{t as s}from"./Fit-DIYt2aQB.js";import{i as c,n as l,r as u}from"./VBox-BNegDPs_.js";import{o as d}from"./LayoutSizes-DG9aW9k6.js";import{t as f}from"./Border-Bz29z-_7.js";import{t as p}from"./LayoutConstraints-DkctJZXB.js";import{a as m,n as h,r as g,t as _}from"./LayoutSerialization-D82UtnDD.js";import{n as v,t as y}from"./AnchorConstraints-CVrMP9rz.js";import{n as b,r as x,t as S}from"./GridConstraints-B1rxCw9B.js";import{t as C}from"./Grid-ViA0joow.js";import{t as w}from"./Card-BdfbvOD_.js";var FlowLayout=class extends r{_spacing=5;_lineSpacing=5;_uniform=`none`;_align=`start`;_itemAlign=`start`;_justify=`start`;_wrappedLineExtent=null;constructor(e){super(),e&&this.applyOptions(e)}applyOptions(e){super.applyOptions(e),e.spacing!==void 0&&this.setComponentSpacing(e.spacing),e.lineSpacing!==void 0&&this.setLineSpacing(e.lineSpacing),e.uniform!==void 0&&this.setUniform(e.uniform),e.align!==void 0&&this.setAlign(e.align),e.itemAlign!==void 0&&this.setItemAlign(e.itemAlign),e.justify!==void 0&&this.setJustify(e.justify)}getComponentSpacing(){return this._spacing||0}setComponentSpacing(e){return this._spacing=e||0,this}getLineSpacing(){return this._lineSpacing||0}setLineSpacing(e){return this._lineSpacing=e||0,this}getWrappedLineExtent(){return this._wrappedLineExtent}publishWrappedLineExtent(e){!Number.isFinite(e)||this._wrappedLineExtent===e||(this._wrappedLineExtent=e,this.getContainer()?.notifyIntrinsicSizeChanged())}attach(e){return super.attach(e),this._wrappedLineExtent=null,this}getUniform(){return this._uniform}setUniform(e){return this._uniform=e,this}getAlign(){return this._align}setAlign(e){return this._align=e,this}getItemAlign(){return this._itemAlign}setItemAlign(e){return this._itemAlign=e,this}getJustify(){return this._justify}setJustify(e){return this._justify=e,this}isUniformWidth(){return this._uniform===`width`||this._uniform===`both`}isUniformHeight(){return this._uniform===`height`||this._uniform===`both`}computeUniformExtents(e){let t=0,n=0;for(let r of e){let e=this.clampedPreferredSize(r);t=Math.max(t,e.width),n=Math.max(n,e.height)}return{width:t,height:n}}clampedPreferredSize(e){let t=e.getPreferredSize(),n=e.getMinSize(),r=e.getMaxSize(),i=t?t.width:0,a=t?t.height:0;return r&&(i=Math.min(i,r.width),a=Math.min(a,r.height)),n&&(i=Math.max(i,n.width),a=Math.max(a,n.height)),{width:i,height:a}}alignLead(e,t){let n=Math.max(0,t-e);return this._align===`center`?n/2:this._align===`end`?n:0}crossOffset(e,t,n,r,i){switch(this._itemAlign){case`center`:return Math.max(0,(t-e)/2);case`end`:return Math.max(0,t-e);case`baseline`:return r===null?0:n===null?this.nullChildY(e,r,i):r-n;default:return 0}}justifyGaps(e,t,n,r){let i=t+r*Math.max(0,e-1);if(this._justify===`start`||e<2||i>=n)return{lead:0,gap:r};let a=n-t;if(this._justify===`between`)return{lead:0,gap:a/(e-1)};let o=a/e;return{lead:o/2,gap:o}}},HFlow=class extends FlowLayout{getPreferredSize(){let e=this.getContainer();if(!e)return null;let t=e.getPerimeterSize(),n=e.getLaidOutComponents(),r=this.isUniformWidth(),i=this.isUniformHeight(),a=r||i?this.computeUniformExtents(n):{width:0,height:0},o=this.getWrappedLineExtent(),s=o===null&&!i,c=t.left+t.right,l=[],u=[];for(let e of n){let t=e.getPreferredSize();t&&(r||(c+=t.width),s&&(l.push(t.height),u.push(e.getBaseline())))}r&&(c+=n.length*a.width),c+=this._spacing*Math.max(0,n.length-1);let d=o===null?i?a.height:this.lineExtent(l,u):o;return d+=t.top+t.bottom,{width:c,height:d}}getMinSize(){let e=this.getContainer();if(!e)return null;let t=e.getPerimeterSize(),n=e.getLaidOutComponents(),r=0,i=[],a=[];for(let e of n){let t=e.getMinSize();t&&(r=Math.max(r,t.width),i.push(t.height),a.push(e.getBaseline()))}let o=t.left+t.right+r,s=this.lineExtent(i,a);return s+=t.top+t.bottom,{width:o,height:s}}getMaxSize(){let n=this.getContainer();if(!n)return null;let r=n.getPerimeterSize(),i=n.getLaidOutComponents(),a=this.isUniformWidth(),o=a?this.computeUniformExtents(i):{width:0,height:0},s=r.left+r.right,c=0,l=!1,u=!1;for(let e of i){let n=e.getMaxSize();if(!n){a||(l=!0),u=!0;continue}a||(t(n.width)?l=!0:s+=n.width),t(n.height)?u=!0:c=Math.max(c,n.height)}a&&(s+=i.length*o.width),s+=this._spacing*Math.max(0,i.length-1);let d=this.getWrappedLineExtent();return d!==null&&!u&&(c=Math.max(c,d)),c+=r.top+r.bottom,{width:l?e:s,height:u?e:c}}doLayout(){let e=this.getContainer();if(!e)return;let t=e.getInnerSize();if(!t)return;let n=e.getLaidOutComponents(),r=e.getContentInsets(),i=this.getComponentSpacing(),a=this.getLineSpacing(),o=this.isUniformWidth(),s=this.isUniformHeight(),c=o||s?this.computeUniformExtents(n):{width:0,height:0},l=this.groupIntoRows(n,t.width,r.getTop(),i,a,o,s,c);this.placeRows(l,r.getLeft(),t.width,i),Number.isFinite(t.width)&&this.publishWrappedLineExtent(this.rowsCrossExtent(l,a)),this.reserveContentFrame()}groupIntoRows(e,t,n,r,i,a,o,s){let c=[],l=n,u=null;for(let n of e){let e=this.clampedPreferredSize(n),d=a?s.width:e.width,f=o?s.height:e.height;u&&u.contentWidth+r+d>t&&(l+=u.rowHeight+i,u=null),u||(u={cells:[],contentWidth:0,rowHeight:0,y:l},c.push(u));let p=u.cells.length===0?Math.min(d,t):d;u.contentWidth+=u.cells.length===0?p:r+p,u.cells.push({component:n,width:p,height:f,baseline:n.getBaseline()}),u.rowHeight=this.rowExtent(u,f)}return c}placeRows(e,t,n,r){for(let i of e){let e=i.cells.map(e=>e.height),o=i.cells.map(e=>e.baseline),{rowAscent:s,rowDescent:c}=this.computeRowMetrics(e,o),{lead:l,gap:u}=this.justifyGaps(i.cells.length,this.cellsMainExtent(i),n,r),d=t+(this._justify===`start`?this.alignLead(i.contentWidth,n):0)+l;for(let e of i.cells){let t=i.y+this.crossOffset(e.height,i.rowHeight,e.baseline,s,c);this.placeComponent(e.component,d,t,e.width,e.height,a.NONE),d+=e.width+u}}}cellsMainExtent(e){return e.cells.reduce((e,t)=>e+t.width,0)}rowsCrossExtent(e,t){if(e.length===0)return 0;let n=t*(e.length-1);for(let t of e)n+=t.rowHeight;return n}rowExtent(e,t){return this._itemAlign===`baseline`?this.lineExtent(e.cells.map(e=>e.height),e.cells.map(e=>e.baseline)):Math.max(e.rowHeight,t)}lineExtent(e,t){return this._itemAlign===`baseline`?this.computeRowHeight(e,t):e.reduce((e,t)=>Math.max(e,t),0)}},T=i(HFlow),VFlow=class extends FlowLayout{getPreferredSize(){let e=this.getContainer();if(!e)return null;let t=e.getPerimeterSize(),n=e.getLaidOutComponents(),r=this.isUniformWidth(),i=this.isUniformHeight(),a=r||i?this.computeUniformExtents(n):{width:0,height:0},o=t.top+t.bottom,s=0;for(let e of n){let t=e.getPreferredSize();t&&(i||(o+=t.height),s=Math.max(s,t.width))}i&&(o+=n.length*a.height),o+=this._spacing*Math.max(0,n.length-1);let c=this.getWrappedLineExtent(),l=c===null?r?a.width:s:c;return l+=t.left+t.right,{width:l,height:o}}getMinSize(){let e=this.getContainer();if(!e)return null;let t=e.getPerimeterSize(),n=e.getLaidOutComponents(),r=0,i=0;for(let e of n){let t=e.getMinSize();t&&(r=Math.max(r,t.height),i=Math.max(i,t.width))}return{width:t.left+t.right+i,height:t.top+t.bottom+r}}getMaxSize(){let n=this.getContainer();if(!n)return null;let r=n.getPerimeterSize(),i=n.getLaidOutComponents(),a=this.isUniformHeight(),o=a?this.computeUniformExtents(i):{width:0,height:0},s=r.top+r.bottom,c=0,l=!1,u=!1;for(let e of i){let n=e.getMaxSize();if(!n){a||(u=!0),l=!0;continue}a||(t(n.height)?u=!0:s+=n.height),t(n.width)?l=!0:c=Math.max(c,n.width)}a&&(s+=i.length*o.height),s+=this._spacing*Math.max(0,i.length-1);let d=this.getWrappedLineExtent();return d!==null&&!l&&(c=Math.max(c,d)),c+=r.left+r.right,{width:l?e:c,height:u?e:s}}doLayout(){let e=this.getContainer();if(!e)return;let t=e.getInnerSize();if(!t)return;let n=e.getLaidOutComponents(),r=e.getContentInsets(),i=this.getComponentSpacing(),a=this.getLineSpacing(),o=this.isUniformWidth(),s=this.isUniformHeight(),c=o||s?this.computeUniformExtents(n):{width:0,height:0},l=this.groupIntoColumns(n,t.height,r.getLeft(),i,a,o,s,c);this.placeColumns(l,r.getTop(),t.height,i),Number.isFinite(t.height)&&this.publishWrappedLineExtent(this.columnsCrossExtent(l,a)),this.reserveContentFrame()}groupIntoColumns(e,t,n,r,i,a,o,s){let c=[],l=n,u=null;for(let n of e){let e=this.clampedPreferredSize(n),d=a?s.width:e.width,f=o?s.height:e.height;u&&u.contentHeight+r+f>t&&(l+=u.columnWidth+i,u=null),u||(u={cells:[],contentHeight:0,columnWidth:0,x:l},c.push(u));let p=u.cells.length===0?Math.min(f,t):f;u.contentHeight+=u.cells.length===0?p:r+p,u.cells.push({component:n,width:d,height:p,baseline:null}),u.columnWidth=Math.max(u.columnWidth,d)}return c}placeColumns(e,t,n,r){for(let i of e){let{lead:e,gap:o}=this.justifyGaps(i.cells.length,this.cellsMainExtent(i),n,r),s=t+(this._justify===`start`?this.alignLead(i.contentHeight,n):0)+e;for(let e of i.cells){let t=i.x+this.crossOffset(e.width,i.columnWidth,null,null,0);this.placeComponent(e.component,t,s,e.width,e.height,a.NONE),s+=e.height+o}}}cellsMainExtent(e){return e.cells.reduce((e,t)=>e+t.height,0)}columnsCrossExtent(e,t){if(e.length===0)return 0;let n=t*(e.length-1);for(let t of e)n+=t.columnWidth;return n}},E=i(VFlow);export{n as Absolute,x as Accordion,b as AccordionConstraints,v as Anchor,y as AnchorConstraints,o as AnchorType,f as Border,c as BoxLayout,w as Card,g as DockRegion,a as FillType,s as Fit,FlowLayout,C as Grid,S as GridConstraints,u as HBox,T as HFlow,p as LayoutConstraints,r as LayoutManager,m as Split,d as Tab,l as VBox,E as VFlow,_ as restoreLayout,h as serializeLayout};
1
+ import{a as e,o as t}from"./Position-PBVBW1JS.js";import{d as n,f as r,h as i,m as a,p as o}from"./Component-w65rPK75.js";import{t as s}from"./Fit-Cg3dPyZg.js";import{i as c,n as l,r as u}from"./VBox-32fxpkDl.js";import{o as d}from"./LayoutSizes-DKDK1Cle.js";import{t as f}from"./Border-CNS6aEXB.js";import{t as p}from"./LayoutConstraints-LIHYYd2F.js";import{a as m,n as h,r as g,t as _}from"./LayoutSerialization-ySzY1h2l.js";import{t as v}from"./Anchor-BsblS5it.js";import{t as y}from"./AnchorConstraints-Bfkt8019.js";import{n as b,r as x,t as S}from"./GridConstraints-Bts284FI.js";import{t as C}from"./Grid-BYBohJIA.js";import{t as w}from"./Card-CD3jxshU.js";var FlowLayout=class extends r{_spacing=5;_lineSpacing=5;_uniform=`none`;_align=`start`;_itemAlign=`start`;_justify=`start`;_wrappedLineExtent=null;constructor(e){super(),e&&this.applyOptions(e)}applyOptions(e){super.applyOptions(e),e.spacing!==void 0&&this.setComponentSpacing(e.spacing),e.lineSpacing!==void 0&&this.setLineSpacing(e.lineSpacing),e.uniform!==void 0&&this.setUniform(e.uniform),e.align!==void 0&&this.setAlign(e.align),e.itemAlign!==void 0&&this.setItemAlign(e.itemAlign),e.justify!==void 0&&this.setJustify(e.justify)}getComponentSpacing(){return this._spacing||0}setComponentSpacing(e){return this._spacing=e||0,this}getLineSpacing(){return this._lineSpacing||0}setLineSpacing(e){return this._lineSpacing=e||0,this}getWrappedLineExtent(){return this._wrappedLineExtent}publishWrappedLineExtent(e){!Number.isFinite(e)||this._wrappedLineExtent===e||(this._wrappedLineExtent=e,this.getContainer()?.notifyIntrinsicSizeChanged())}attach(e){return super.attach(e),this._wrappedLineExtent=null,this}getUniform(){return this._uniform}setUniform(e){return this._uniform=e,this}getAlign(){return this._align}setAlign(e){return this._align=e,this}getItemAlign(){return this._itemAlign}setItemAlign(e){return this._itemAlign=e,this}getJustify(){return this._justify}setJustify(e){return this._justify=e,this}isUniformWidth(){return this._uniform===`width`||this._uniform===`both`}isUniformHeight(){return this._uniform===`height`||this._uniform===`both`}computeUniformExtents(e){let t=0,n=0;for(let r of e){let e=this.clampedPreferredSize(r);t=Math.max(t,e.width),n=Math.max(n,e.height)}return{width:t,height:n}}clampedPreferredSize(e){let t=e.getPreferredSize(),n=e.getMinSize(),r=e.getMaxSize(),i=t?t.width:0,a=t?t.height:0;return r&&(i=Math.min(i,r.width),a=Math.min(a,r.height)),n&&(i=Math.max(i,n.width),a=Math.max(a,n.height)),{width:i,height:a}}alignLead(e,t){let n=Math.max(0,t-e);return this._align===`center`?n/2:this._align===`end`?n:0}crossOffset(e,t,n,r,i){switch(this._itemAlign){case`center`:return Math.max(0,(t-e)/2);case`end`:return Math.max(0,t-e);case`baseline`:return r===null?0:n===null?this.nullChildY(e,r,i):r-n;default:return 0}}justifyGaps(e,t,n,r){let i=t+r*Math.max(0,e-1);if(this._justify===`start`||e<2||i>=n)return{lead:0,gap:r};let a=n-t;if(this._justify===`between`)return{lead:0,gap:a/(e-1)};let o=a/e;return{lead:o/2,gap:o}}},HFlow=class extends FlowLayout{getPreferredSize(){let e=this.getContainer();if(!e)return null;let t=e.getPerimeterSize(),n=e.getLaidOutComponents(),r=this.isUniformWidth(),i=this.isUniformHeight(),a=r||i?this.computeUniformExtents(n):{width:0,height:0},o=this.getWrappedLineExtent(),s=o===null&&!i,c=t.left+t.right,l=[],u=[];for(let e of n){let t=e.getPreferredSize();t&&(r||(c+=t.width),s&&(l.push(t.height),u.push(e.getBaseline())))}r&&(c+=n.length*a.width),c+=this._spacing*Math.max(0,n.length-1);let d=o===null?i?a.height:this.lineExtent(l,u):o;return d+=t.top+t.bottom,{width:c,height:d}}getMinSize(){let e=this.getContainer();if(!e)return null;let t=e.getPerimeterSize(),n=e.getLaidOutComponents(),r=0,i=[],a=[];for(let e of n){let t=e.getMinSize();t&&(r=Math.max(r,t.width),i.push(t.height),a.push(e.getBaseline()))}let o=t.left+t.right+r,s=this.lineExtent(i,a);return s+=t.top+t.bottom,{width:o,height:s}}getMaxSize(){let n=this.getContainer();if(!n)return null;let r=n.getPerimeterSize(),i=n.getLaidOutComponents(),a=this.isUniformWidth(),o=a?this.computeUniformExtents(i):{width:0,height:0},s=r.left+r.right,c=0,l=!1,u=!1;for(let e of i){let n=e.getMaxSize();if(!n){a||(l=!0),u=!0;continue}a||(t(n.width)?l=!0:s+=n.width),t(n.height)?u=!0:c=Math.max(c,n.height)}a&&(s+=i.length*o.width),s+=this._spacing*Math.max(0,i.length-1);let d=this.getWrappedLineExtent();return d!==null&&!u&&(c=Math.max(c,d)),c+=r.top+r.bottom,{width:l?e:s,height:u?e:c}}doLayout(){let e=this.getContainer();if(!e)return;let t=e.getInnerSize();if(!t)return;let n=e.getLaidOutComponents(),r=e.getContentInsets(),i=this.getComponentSpacing(),a=this.getLineSpacing(),o=this.isUniformWidth(),s=this.isUniformHeight(),c=o||s?this.computeUniformExtents(n):{width:0,height:0},l=this.groupIntoRows(n,t.width,r.getTop(),i,a,o,s,c);this.placeRows(l,r.getLeft(),t.width,i),Number.isFinite(t.width)&&this.publishWrappedLineExtent(this.rowsCrossExtent(l,a)),this.reserveContentFrame()}groupIntoRows(e,t,n,r,i,a,o,s){let c=[],l=n,u=null;for(let n of e){let e=this.clampedPreferredSize(n),d=a?s.width:e.width,f=o?s.height:e.height;u&&u.contentWidth+r+d>t&&(l+=u.rowHeight+i,u=null),u||(u={cells:[],contentWidth:0,rowHeight:0,y:l},c.push(u));let p=u.cells.length===0?Math.min(d,t):d;u.contentWidth+=u.cells.length===0?p:r+p,u.cells.push({component:n,width:p,height:f,baseline:n.getBaseline()}),u.rowHeight=this.rowExtent(u,f)}return c}placeRows(e,t,n,r){for(let i of e){let e=i.cells.map(e=>e.height),o=i.cells.map(e=>e.baseline),{rowAscent:s,rowDescent:c}=this.computeRowMetrics(e,o),{lead:l,gap:u}=this.justifyGaps(i.cells.length,this.cellsMainExtent(i),n,r),d=t+(this._justify===`start`?this.alignLead(i.contentWidth,n):0)+l;for(let e of i.cells){let t=i.y+this.crossOffset(e.height,i.rowHeight,e.baseline,s,c);this.placeComponent(e.component,d,t,e.width,e.height,a.NONE),d+=e.width+u}}}cellsMainExtent(e){return e.cells.reduce((e,t)=>e+t.width,0)}rowsCrossExtent(e,t){if(e.length===0)return 0;let n=t*(e.length-1);for(let t of e)n+=t.rowHeight;return n}rowExtent(e,t){return this._itemAlign===`baseline`?this.lineExtent(e.cells.map(e=>e.height),e.cells.map(e=>e.baseline)):Math.max(e.rowHeight,t)}lineExtent(e,t){return this._itemAlign===`baseline`?this.computeRowHeight(e,t):e.reduce((e,t)=>Math.max(e,t),0)}},T=i(HFlow),VFlow=class extends FlowLayout{getPreferredSize(){let e=this.getContainer();if(!e)return null;let t=e.getPerimeterSize(),n=e.getLaidOutComponents(),r=this.isUniformWidth(),i=this.isUniformHeight(),a=r||i?this.computeUniformExtents(n):{width:0,height:0},o=t.top+t.bottom,s=0;for(let e of n){let t=e.getPreferredSize();t&&(i||(o+=t.height),s=Math.max(s,t.width))}i&&(o+=n.length*a.height),o+=this._spacing*Math.max(0,n.length-1);let c=this.getWrappedLineExtent(),l=c===null?r?a.width:s:c;return l+=t.left+t.right,{width:l,height:o}}getMinSize(){let e=this.getContainer();if(!e)return null;let t=e.getPerimeterSize(),n=e.getLaidOutComponents(),r=0,i=0;for(let e of n){let t=e.getMinSize();t&&(r=Math.max(r,t.height),i=Math.max(i,t.width))}return{width:t.left+t.right+i,height:t.top+t.bottom+r}}getMaxSize(){let n=this.getContainer();if(!n)return null;let r=n.getPerimeterSize(),i=n.getLaidOutComponents(),a=this.isUniformHeight(),o=a?this.computeUniformExtents(i):{width:0,height:0},s=r.top+r.bottom,c=0,l=!1,u=!1;for(let e of i){let n=e.getMaxSize();if(!n){a||(u=!0),l=!0;continue}a||(t(n.height)?u=!0:s+=n.height),t(n.width)?l=!0:c=Math.max(c,n.width)}a&&(s+=i.length*o.height),s+=this._spacing*Math.max(0,i.length-1);let d=this.getWrappedLineExtent();return d!==null&&!l&&(c=Math.max(c,d)),c+=r.left+r.right,{width:l?e:c,height:u?e:s}}doLayout(){let e=this.getContainer();if(!e)return;let t=e.getInnerSize();if(!t)return;let n=e.getLaidOutComponents(),r=e.getContentInsets(),i=this.getComponentSpacing(),a=this.getLineSpacing(),o=this.isUniformWidth(),s=this.isUniformHeight(),c=o||s?this.computeUniformExtents(n):{width:0,height:0},l=this.groupIntoColumns(n,t.height,r.getLeft(),i,a,o,s,c);this.placeColumns(l,r.getTop(),t.height,i),Number.isFinite(t.height)&&this.publishWrappedLineExtent(this.columnsCrossExtent(l,a)),this.reserveContentFrame()}groupIntoColumns(e,t,n,r,i,a,o,s){let c=[],l=n,u=null;for(let n of e){let e=this.clampedPreferredSize(n),d=a?s.width:e.width,f=o?s.height:e.height;u&&u.contentHeight+r+f>t&&(l+=u.columnWidth+i,u=null),u||(u={cells:[],contentHeight:0,columnWidth:0,x:l},c.push(u));let p=u.cells.length===0?Math.min(f,t):f;u.contentHeight+=u.cells.length===0?p:r+p,u.cells.push({component:n,width:d,height:p,baseline:null}),u.columnWidth=Math.max(u.columnWidth,d)}return c}placeColumns(e,t,n,r){for(let i of e){let{lead:e,gap:o}=this.justifyGaps(i.cells.length,this.cellsMainExtent(i),n,r),s=t+(this._justify===`start`?this.alignLead(i.contentHeight,n):0)+e;for(let e of i.cells){let t=i.x+this.crossOffset(e.width,i.columnWidth,null,null,0);this.placeComponent(e.component,t,s,e.width,e.height,a.NONE),s+=e.height+o}}}cellsMainExtent(e){return e.cells.reduce((e,t)=>e+t.height,0)}columnsCrossExtent(e,t){if(e.length===0)return 0;let n=t*(e.length-1);for(let t of e)n+=t.columnWidth;return n}},E=i(VFlow);export{n as Absolute,x as Accordion,b as AccordionConstraints,v as Anchor,y as AnchorConstraints,o as AnchorType,f as Border,c as BoxLayout,w as Card,g as DockRegion,a as FillType,s as Fit,FlowLayout,C as Grid,S as GridConstraints,u as HBox,T as HFlow,p as LayoutConstraints,r as LayoutManager,m as Split,d as Tab,l as VBox,E as VFlow,_ as restoreLayout,h as serializeLayout};
2
2
  //# sourceMappingURL=layout.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"layout.es.js","names":[],"sources":["../../src/typescript/lib/layout/FlowLayout.ts","../../src/typescript/lib/layout/HFlow.ts","../../src/typescript/lib/layout/VFlow.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { LayoutManager, LayoutManagerOptions } from \"~/layout/LayoutManager.js\";\nimport { Size } from \"~/primitive/Size.js\";\nimport { Component } from \"~/core/Component.js\";\nimport type { AxisPosition, AxisSpread } from \"~/primitive/Axis.js\";\n\n/**\n * Which axes of a {@link FlowLayout}'s cells are made uniform so wrapped items\n * line up into a grid.\n *\n * - `\"none\"` (the default) — each item keeps its own preferred size and lines\n * pack independently, so columns do not align across lines.\n * - `\"width\"` — every cell takes the widest item's width, so columns align\n * horizontally; each line still uses its own (tallest-item) height.\n * - `\"height\"` — every cell takes the tallest item's height, so lines align\n * vertically; widths still vary per item.\n * - `\"both\"` — every cell is identical (widest × tallest), a full grid.\n *\n * @category Layouts\n */\nexport type FlowUniformity = \"none\" | \"width\" | \"height\" | \"both\";\n\n/**\n * Cross-axis alignment of an item within its wrapped line's cross extent — the\n * row height for {@link HFlow}, the column width for {@link VFlow}.\n *\n * - `\"start\"` (the default) — leading cross-edge (HFlow top, VFlow left). This\n * is the original placement.\n * - `\"center\"` — centred in the line's cross extent.\n * - `\"end\"` — trailing cross-edge (HFlow bottom, VFlow right).\n * - `\"baseline\"` — {@link HFlow} only: items are aligned on their shared text\n * baseline across the row; null-baseline (graphical) items centre in the text\n * line. {@link VFlow} has no shared text baseline, so it degrades to\n * `\"start\"`.\n *\n * @remarks This positions the *cell* within the line; a child's\n * {@link AnchorType} still positions the child within its (possibly uniform)\n * cell — both apply. Flow never resizes cells, so alignment only moves them.\n *\n * @category Layouts\n */\nexport type FlowItemAlign = \"start\" | \"center\" | \"end\" | \"baseline\";\n\n/**\n * Construction-time options shared by {@link HFlow} and {@link VFlow}.\n *\n * @category Layouts\n */\nexport interface FlowLayoutOptions extends LayoutManagerOptions {\n spacing?: number;\n lineSpacing?: number;\n uniform?: FlowUniformity;\n align?: AxisPosition;\n itemAlign?: FlowItemAlign;\n justify?: AxisSpread;\n}\n\n/**\n * Abstract base for the wrapping flow layouts {@link HFlow} and {@link VFlow}.\n * Holds the axis-agnostic configuration plumbing — item spacing, line spacing,\n * cell uniformity, and line alignment — and the shared cell-measurement\n * helpers, and dispatches a {@link FlowLayoutOptions} bag.\n *\n * @remarks This deliberately does not extend {@link BoxLayout}. That base models\n * a non-wrapping single-axis box — `mode`, `stretching`, `weight`, proportional\n * shrink, and a min-total overflow inflation — none of which a wrapping flow\n * uses. The geometric algorithms (`getPreferredSize`, `getMinSize`,\n * `getMaxSize`, `doLayout`) are mirror-image per axis and stay concrete on each\n * subclass.\n *\n * @category Layouts\n */\nexport abstract class FlowLayout extends LayoutManager {\n\n // `protected`, not `private`: the subclasses' geometric methods\n // (getPreferredSize/getMinSize/getMaxSize/doLayout) read these fields\n // directly, so they must be visible to HFlow/VFlow.\n protected _spacing: number = 5;\n protected _lineSpacing: number = 5;\n protected _uniform: FlowUniformity = \"none\";\n protected _align: AxisPosition = \"start\";\n protected _itemAlign: FlowItemAlign = \"start\";\n protected _justify: AxisSpread = \"start\";\n\n // The cross-axis extent the children last wrapped into, measured by doLayout\n // at the container's real inner extent. `null` until a layout has run at a\n // usable extent, which is what makes the single-line fallback in each\n // subclass's getPreferredSize reachable on the first pass.\n private _wrappedLineExtent: number | null = null;\n\n /**\n * Constructs the layout manager, applying any supplied options.\n *\n * @param options - Optional construction-time configuration.\n */\n constructor(options?: FlowLayoutOptions) {\n // LayoutManager's constructor takes no options; applied via applyOptions below.\n // eslint-disable-next-line local/forward-super-options\n super();\n\n if (options) {\n this.applyOptions(options);\n }\n }\n\n /**\n * Applies a {@link FlowLayoutOptions} bag after the inherited LayoutManager\n * defaults, dispatching the item and line spacings, the uniformity mode, and\n * the line alignment.\n *\n * @param options - The options bag carrying the values to apply.\n */\n protected applyOptions(options: FlowLayoutOptions): void {\n super.applyOptions(options);\n\n if (options.spacing !== undefined) {\n this.setComponentSpacing(options.spacing);\n }\n\n if (options.lineSpacing !== undefined) {\n this.setLineSpacing(options.lineSpacing);\n }\n\n if (options.uniform !== undefined) {\n this.setUniform(options.uniform);\n }\n\n if (options.align !== undefined) {\n this.setAlign(options.align);\n }\n\n if (options.itemAlign !== undefined) {\n this.setItemAlign(options.itemAlign);\n }\n\n if (options.justify !== undefined) {\n this.setJustify(options.justify);\n }\n }\n\n /**\n * Returns the pixel spacing between items along a line.\n *\n * @returns The current item spacing in pixels.\n */\n getComponentSpacing(): number {\n return this._spacing || 0;\n }\n\n /**\n * Sets the pixel spacing between items along a line.\n *\n * @param spacing - Spacing in pixels.\n *\n * @returns This layout manager, for method chaining.\n */\n setComponentSpacing(spacing: number): this {\n this._spacing = spacing || 0;\n\n return this;\n }\n\n /**\n * Returns the pixel spacing between wrapped lines.\n *\n * @returns The current line spacing in pixels.\n */\n getLineSpacing(): number {\n return this._lineSpacing || 0;\n }\n\n /**\n * Sets the pixel spacing between wrapped lines.\n *\n * @param lineSpacing - Spacing in pixels.\n *\n * @returns This layout manager, for method chaining.\n */\n setLineSpacing(lineSpacing: number): this {\n this._lineSpacing = lineSpacing || 0;\n\n return this;\n }\n\n /**\n * Returns the cross-axis extent the children wrapped into at the last\n * layout, or null if no layout has run at a usable extent yet.\n *\n * @returns The measured line extent in pixels, or null.\n *\n * @remarks The number covers the lines only — summed row heights (or column\n * widths) plus the gaps between them. It carries no insets, padding, or\n * border, so a caller adds the perimeter back itself.\n */\n protected getWrappedLineExtent(): number | null {\n return this._wrappedLineExtent;\n }\n\n /**\n * Records the cross-axis extent the children wrapped into, and tells the\n * container when that measurement has changed.\n *\n * @param extent - The measured line extent in pixels.\n *\n * @remarks The equality check is the loop guard. A settled layout publishes\n * the same extent on every pass and therefore notifies nothing; without the\n * check each pass would relay a size change that schedules the next one.\n *\n * A non-finite extent is dropped rather than stored, because it would defeat\n * that guard: `NaN !== NaN`, so every pass would look like a change and relay\n * one. One child with a `NaN` preferred height — a text whose font has not\n * resolved, say — is enough to poison the sum. Dropping it also keeps the\n * single-line fallback reachable, which is the right answer when nothing\n * usable was measured.\n */\n protected publishWrappedLineExtent(extent: number): void {\n if (!Number.isFinite(extent) || this._wrappedLineExtent === extent) {\n return;\n }\n\n this._wrappedLineExtent = extent;\n\n this.getContainer()?.notifyIntrinsicSizeChanged();\n }\n\n /**\n * Attaches to a container, dropping any measurement taken against a previous\n * one.\n *\n * @param container - The container component to attach to.\n *\n * @returns This layout manager, for method chaining.\n *\n * @remarks Clearing here rather than only in {@link FlowLayout.detach} is\n * what covers a manager moved between containers. `Component.setLayoutManager`\n * detaches the *container's* outgoing manager, never the *manager's* previous\n * container, so a reused manager arrives still holding the old measurement\n * and would report it for children it no longer has.\n */\n attach(container: Component): this {\n super.attach(container);\n\n this._wrappedLineExtent = null;\n\n return this;\n }\n\n /**\n * Returns which axes are made uniform so wrapped items align into a grid.\n *\n * @returns The current uniformity mode.\n */\n getUniform(): FlowUniformity {\n return this._uniform;\n }\n\n /**\n * Sets which axes are made uniform so wrapped items align into a grid.\n *\n * @param uniform - `\"width\"` aligns columns, `\"height\"` aligns rows,\n * `\"both\"` produces a full grid, `\"none\"` packs each item at its own\n * size. See {@link FlowUniformity}.\n *\n * @returns This layout manager, for method chaining.\n */\n setUniform(uniform: FlowUniformity): this {\n this._uniform = uniform;\n\n return this;\n }\n\n /**\n * Returns how each wrapped line's content block is packed along the main\n * axis within the container's inner main extent.\n *\n * @returns The current line alignment.\n */\n getAlign(): AxisPosition {\n return this._align;\n }\n\n /**\n * Sets how each wrapped line's content block is packed along the main axis.\n *\n * @param align - `\"start\"` packs at the leading edge (the default),\n * `\"center\"` centres the block, `\"end\"` packs at the trailing edge. The\n * leading/trailing edges are west/east for {@link HFlow} and north/south\n * for {@link VFlow}. See {@link AxisPosition}.\n *\n * @returns This layout manager, for method chaining.\n */\n setAlign(align: AxisPosition): this {\n this._align = align;\n\n return this;\n }\n\n /**\n * Returns how each item is aligned within its wrapped line's cross extent.\n *\n * @returns The current cross-axis item alignment.\n */\n getItemAlign(): FlowItemAlign {\n return this._itemAlign;\n }\n\n /**\n * Sets how each item is aligned within its wrapped line's cross extent — the\n * row height for {@link HFlow}, the column width for {@link VFlow}.\n *\n * @param itemAlign - `\"start\"` aligns to the leading cross-edge (the\n * default), `\"center\"` centres, `\"end\"` aligns to the trailing cross-edge,\n * `\"baseline\"` aligns text baselines across an {@link HFlow} row.\n * `\"baseline\"` degrades to `\"start\"` on {@link VFlow}, which has no shared\n * text baseline. See {@link FlowItemAlign}.\n *\n * @returns This layout manager, for method chaining.\n */\n setItemAlign(itemAlign: FlowItemAlign): this {\n this._itemAlign = itemAlign;\n\n return this;\n }\n\n /**\n * Returns how each wrapped line's items are distributed along the main axis.\n *\n * @returns The current main-axis distribution.\n */\n getJustify(): AxisSpread {\n return this._justify;\n }\n\n /**\n * Sets how each wrapped line's items are distributed along the main axis by\n * growing the inter-item gaps.\n *\n * @param justify - `\"start\"` packs items with the fixed `spacing` (the\n * default), `\"between\"` makes the first/last items flush to the edges with\n * equal interior gaps, `\"around\"` puts an equal gap around every item. See\n * {@link AxisSpread}.\n *\n * @returns This layout manager, for method chaining.\n *\n * @remarks When `justify` is `\"between\"` or `\"around\"` the line fills the\n * inner main extent, so it owns the residual and {@link AxisPosition} (the\n * `align` option) is ignored. A single-item or over-long line degrades to\n * `\"start\"`.\n */\n setJustify(justify: AxisSpread): this {\n this._justify = justify;\n\n return this;\n }\n\n /**\n * Whether cells are made uniform on the horizontal axis (columns align).\n *\n * @returns `true` for the `\"width\"` and `\"both\"` uniformity modes.\n */\n protected isUniformWidth(): boolean {\n return this._uniform === \"width\" || this._uniform === \"both\";\n }\n\n /**\n * Whether cells are made uniform on the vertical axis (rows align).\n *\n * @returns `true` for the `\"height\"` and `\"both\"` uniformity modes.\n */\n protected isUniformHeight(): boolean {\n return this._uniform === \"height\" || this._uniform === \"both\";\n }\n\n /**\n * Computes the uniform cell extent: the widest and tallest clamped preferred\n * size across the children, used to size cells in a `uniform` mode.\n *\n * @param components - The children sharing the flow.\n * @returns The `{width, height}` every uniform cell uses on its axis.\n */\n protected computeUniformExtents(components: Component[]): Size {\n let width = 0;\n let height = 0;\n\n for (const component of components) {\n const cell = this.clampedPreferredSize(component);\n\n width = Math.max(width, cell.width);\n height = Math.max(height, cell.height);\n }\n\n return {\n width: width,\n height: height\n };\n }\n\n /**\n * Resolves a child's placed size: its preferred size clamped to its own\n * min and max sizes — the minimum wins when the two conflict.\n *\n * @param component - The child to measure.\n * @returns The clamped `{width, height}`.\n */\n protected clampedPreferredSize(component: Component): Size {\n const pref = component.getPreferredSize();\n const min = component.getMinSize();\n const max = component.getMaxSize();\n\n let width = pref ? pref.width : 0;\n let height = pref ? pref.height : 0;\n\n if (max) {\n width = Math.min(width, max.width);\n height = Math.min(height, max.height);\n }\n\n if (min) {\n width = Math.max(width, min.width);\n height = Math.max(height, min.height);\n }\n\n return {\n width: width,\n height: height\n };\n }\n\n /**\n * Computes the per-line leading offset that packs a content block of the\n * given main extent within the inner main extent per the alignment mode.\n *\n * @param contentMain - The line's content main-extent (sum of placed cell\n * main-extents plus inter-item spacing).\n * @param innerMain - The container's inner extent along the main axis.\n * @returns The leading offset in pixels — `0` for `\"start\"`, half the\n * residual for `\"center\"`, the full residual for `\"end\"`. An over-long\n * line (content exceeding the inner extent) clamps to `0`.\n */\n protected alignLead(contentMain: number, innerMain: number): number {\n const residual = Math.max(0, innerMain - contentMain);\n\n if (this._align === \"center\") {\n return residual / 2;\n }\n\n if (this._align === \"end\") {\n return residual;\n }\n\n return 0;\n }\n\n /**\n * Computes the leading cross-axis offset that positions a cell within its\n * line's cross extent per the {@link FlowItemAlign} mode. The caller adds\n * this to the line's leading cross-edge (the row top for {@link HFlow}, the\n * column left for {@link VFlow}).\n *\n * @param cellExtent - The cell's own cross extent (its height for HFlow, its\n * width for VFlow).\n * @param lineExtent - The line's cross extent (the row height for HFlow, the\n * column width for VFlow); always at least `cellExtent`.\n * @param baseline - The cell's own baseline, or `null` for a graphical cell.\n * Only consulted for `\"baseline\"`.\n * @param rowAscent - The line's text baseline from `computeRowMetrics`, or\n * `null` when no cell reports one (always `null` for VFlow). Only consulted\n * for `\"baseline\"`.\n * @param rowDescent - The line's text descent from `computeRowMetrics`. Only\n * consulted for `\"baseline\"`.\n * @returns The leading offset in pixels — `0` for `\"start\"`, and never\n * negative.\n *\n * @remarks The `\"baseline\"` arm mirrors HBox's per-child baseline placement:\n * a text-bearing cell aligns on `rowAscent - baseline`, a null-baseline cell\n * centres in the text line, and a baseline-less line (`rowAscent === null`,\n * the VFlow case) falls back to `\"start\"`.\n */\n protected crossOffset(cellExtent: number, lineExtent: number, baseline: number | null, rowAscent: number | null, rowDescent: number): number {\n switch (this._itemAlign) {\n case \"center\":\n return Math.max(0, (lineExtent - cellExtent) / 2);\n\n case \"end\":\n return Math.max(0, lineExtent - cellExtent);\n\n case \"baseline\":\n if (rowAscent === null) {\n return 0;\n }\n\n return baseline !== null\n ? rowAscent - baseline\n : this.nullChildY(cellExtent, rowAscent, rowDescent);\n\n case \"start\":\n default:\n return 0;\n }\n }\n\n /**\n * Computes the per-line main-axis spacing under the active\n * {@link AxisSpread} mode.\n *\n * @param itemCount - The number of cells in the line.\n * @param contentMain - The sum of the cells' main extents (no spacing).\n * @param innerMain - The container's inner extent along the main axis.\n * @param spacing - The fixed inter-item spacing in pixels.\n * @returns `{ lead, gap }` — `lead` is the offset before the first item and\n * `gap` the spacing between successive items.\n *\n * @remarks Degrades to the fixed `spacing` (and `lead` `0`) for `\"start\"`,\n * single-item lines, and over-long lines, so the gaps are never negative. For\n * the distribution modes the line fills the inner extent, so the caller must\n * skip the `align` block move.\n */\n protected justifyGaps(itemCount: number, contentMain: number, innerMain: number, spacing: number): { lead: number; gap: number } {\n // Degrade to fixed spacing: start mode, fewer than two items, or content\n // already filling (or exceeding) the inner extent — no positive residual\n // to distribute.\n const fixedTotal = contentMain + spacing * Math.max(0, itemCount - 1);\n\n if (this._justify === \"start\" || itemCount < 2 || fixedTotal >= innerMain) {\n return { lead: 0, gap: spacing };\n }\n\n // The total gap budget to distribute, always positive here.\n const free = innerMain - contentMain;\n\n if (this._justify === \"between\") {\n return { lead: 0, gap: free / (itemCount - 1) };\n }\n\n // \"around\": one whole gap per item, split as half-gaps at the two ends.\n const unit = free / itemCount;\n\n return { lead: unit / 2, gap: unit };\n }\n}\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { FlowLayout, FlowLayoutOptions } from \"~/layout/FlowLayout.js\";\nimport { FillType } from \"~/layout/FillType.js\";\nimport { Size, UNBOUNDED, isUnbounded } from \"~/primitive/Size.js\";\nimport { Component } from \"~/core/Component.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link HFlow}.\n *\n * @remarks Inherits every flow field (`spacing`, `lineSpacing`, `uniform`,\n * `align`, `itemAlign`, `justify`) from {@link FlowLayoutOptions}; `HFlow` adds\n * none of its own.\n *\n * @category Layouts\n */\nexport interface HFlowOptions extends FlowLayoutOptions {}\n\n/**\n * One wrapped row of an {@link HFlow}: its ordered cells (each with the width it\n * was placed at, its own cell height, and its baseline for `\"baseline\"`\n * item-alignment), the row's total content width, the row height, and the row's\n * top in the container's coordinate space. The row height is its tallest cell,\n * except under `\"baseline\"` item-alignment where it is `rowAscent + rowDescent`,\n * which can exceed the tallest cell.\n */\ninterface HFlowRow {\n cells: Array<{ component: Component; width: number; height: number; baseline: number | null }>;\n contentWidth: number;\n rowHeight: number;\n y: number;\n}\n\n/**\n * A layout manager that packs children in horizontal rows, wrapping to a new\n * line when the next child would exceed the container's inner width. Unlike\n * {@link HBox} it never shrinks or stretches children: each keeps its preferred\n * size and lines stack downward. A scroll-enabled host (`Panel.setAutoScroll`)\n * gains a vertical scrollbar once the stacked lines exceed its inner height.\n *\n * @remarks Shares its flow configuration (item/line spacing, cell uniformity,\n * line alignment) with {@link VFlow} through the {@link FlowLayout} base. The\n * `uniform` option grows every cell to the widest and/or tallest item so wrapped\n * items line up into a grid; each item is positioned within its cell by its own\n * {@link AnchorType} constraint (default centre). The `align` option packs each\n * row's content block at the west edge (`\"start\"`, the default), centred, or the\n * east edge; `justify` instead spreads the row's items across the inner width\n * (`\"between\"`/`\"around\"`), and `itemAlign` positions each item within the row\n * height (including `\"baseline\"`, which aligns text baselines across the row) —\n * the scroll extent comes entirely from the children's committed positions read\n * by `reserveContentFrame`.\n *\n * @category Layouts\n */\nclass HFlow extends FlowLayout {\n\n /**\n * Returns the preferred size. The width is the single-line shape of the\n * children — the sum of their preferred widths plus item spacing, or\n * `count * columnWidth` in a `uniform` width mode. The height is the cross\n * extent the children wrapped into at the last layout: the summed row\n * heights plus the gaps between them.\n *\n * @returns The preferred `{width, height}`, or `null` if no container is attached.\n *\n * @remarks The two axes answer different questions. The width is an\n * aspiration — \"give me this much and I will not wrap at all\" — so it stays\n * the unwrapped sum however the children are actually laid out. The height\n * is a consequence of the width the flow was really given, so it reports the\n * measurement rather than an estimate. Before the first layout at a usable\n * width there is nothing measured yet, and the height falls back to the\n * height of one row; a parent that honours preferred sizes corrects that on\n * the pass after the first.\n */\n getPreferredSize(): Size | null {\n const container = this.getContainer();\n if (!container) {\n return null;\n }\n\n const perimeterSize = container.getPerimeterSize();\n const components = container.getLaidOutComponents();\n const uniformWidth = this.isUniformWidth();\n const uniformHeight = this.isUniformHeight();\n const extents = (uniformWidth || uniformHeight) ? this.computeUniformExtents(components) : { width: 0, height: 0 };\n\n // The measured extent covers every wrapped row; the single-line estimate\n // is only reachable before the first layout at a real width. Gathering\n // its inputs costs a getBaseline() per child, so skip them once either a\n // measurement or the uniform cell height has already answered the height.\n const measured = this.getWrappedLineExtent();\n const needsEstimate = measured === null && !uniformHeight;\n\n let width = perimeterSize.left + perimeterSize.right;\n const heights: number[] = [];\n const baselines: Array<number | null> = [];\n\n for (const component of components) {\n const size = component.getPreferredSize();\n\n if (size) {\n if (!uniformWidth) {\n width += size.width;\n }\n\n if (needsEstimate) {\n heights.push(size.height);\n baselines.push(component.getBaseline());\n }\n }\n }\n\n if (uniformWidth) {\n width += components.length * extents.width;\n }\n\n width += this._spacing * Math.max(0, components.length - 1);\n\n let height = measured !== null\n ? measured\n : (uniformHeight ? extents.height : this.lineExtent(heights, baselines));\n\n height += perimeterSize.top + perimeterSize.bottom;\n\n return {\n width: width,\n height: height\n };\n }\n\n /**\n * Returns the minimum size: the widest child's min width (the floor below\n * which not even one child per line fits) and one row's height taken over\n * the children's min heights.\n *\n * @returns The minimum `{width, height}`, or `null` if no container is attached.\n *\n * @remarks The row height follows the current `itemAlign` — the tallest min\n * under every alignment that places a cell inside its row, and\n * `rowAscent + rowDescent` under `\"baseline\"`. It has to use the same rule\n * the preferred size does, or a `start`-aligned row of baseline-bearing\n * children reports a minimum above its own preferred height.\n */\n getMinSize(): Size | null {\n const container = this.getContainer();\n if (!container) {\n return null;\n }\n\n const perimeterSize = container.getPerimeterSize();\n const components = container.getLaidOutComponents();\n\n let maxChildMinWidth = 0;\n const heights: number[] = [];\n const baselines: Array<number | null> = [];\n\n for (const component of components) {\n const size = component.getMinSize();\n\n if (size) {\n maxChildMinWidth = Math.max(maxChildMinWidth, size.width);\n heights.push(size.height);\n baselines.push(component.getBaseline());\n }\n }\n\n const width = perimeterSize.left + perimeterSize.right + maxChildMinWidth;\n\n let height = this.lineExtent(heights, baselines);\n\n height += perimeterSize.top + perimeterSize.bottom;\n\n return {\n width: width,\n height: height\n };\n }\n\n /**\n * Returns the maximum size the flow can usefully occupy: with every child on\n * one line the width is the sum of the children's *maximum* widths (or\n * `count * columnWidth` in a `uniform` width mode) plus item spacing, and the\n * height is the *largest* child maximum — the tallest a single row can grow\n * to. A child whose maximum is `null` or at the unbounded sentinel makes that\n * axis unbounded.\n *\n * @returns The maximum `{width, height}`, or `null` if no container is attached.\n *\n * @remarks Once a layout has measured a wrapped height, that measurement\n * floors the height reported here. A single row's maximum can otherwise sit\n * below the wrapped height the preferred size reports, and a host that sizes\n * itself to its content would clamp the flow back to one row and clip the\n * rest.\n */\n getMaxSize(): Size | null {\n const container = this.getContainer();\n if (!container) {\n return null;\n }\n\n const perimeterSize = container.getPerimeterSize();\n const components = container.getLaidOutComponents();\n const uniformWidth = this.isUniformWidth();\n const extents = uniformWidth ? this.computeUniformExtents(components) : { width: 0, height: 0 };\n\n let width = perimeterSize.left + perimeterSize.right;\n let height = 0;\n let widthUnbounded = false;\n let heightUnbounded = false;\n\n for (const component of components) {\n const max = component.getMaxSize();\n\n if (!max) {\n if (!uniformWidth) {\n widthUnbounded = true;\n }\n heightUnbounded = true;\n continue;\n }\n\n if (!uniformWidth) {\n if (isUnbounded(max.width)) {\n widthUnbounded = true;\n } else {\n width += max.width;\n }\n }\n\n if (isUnbounded(max.height)) {\n heightUnbounded = true;\n } else {\n height = Math.max(height, max.height);\n }\n }\n\n if (uniformWidth) {\n width += components.length * extents.width;\n }\n\n width += this._spacing * Math.max(0, components.length - 1);\n\n // The single-row maximum above can sit below the wrapped extent\n // getPreferredSize now reports. ARCHITECTURE binds min <= preferred <=\n // max, and a host that clamps to its content would otherwise clamp the\n // flow back to one row's height — re-clipping the very overflow the\n // measurement exists to expose. Floor the maximum at the measurement.\n const measured = this.getWrappedLineExtent();\n\n if (measured !== null && !heightUnbounded) {\n height = Math.max(height, measured);\n }\n\n height += perimeterSize.top + perimeterSize.bottom;\n\n return {\n width: widthUnbounded ? UNBOUNDED : width,\n height: heightUnbounded ? UNBOUNDED : height\n };\n }\n\n /**\n * Packs the children left-to-right at their cell size, wrapping to a new\n * line when the next cell's right edge would exceed the inner width, then\n * places each row's content block per the `align` mode. In a `uniform` mode\n * every cell grows to the widest and/or tallest item so the wrapped items\n * line up into a grid. A scroll-enabled host then scrolls the overflow via\n * `reserveContentFrame`, which sizes the content frame to the children's\n * committed extent.\n */\n doLayout(): void {\n const container = this.getContainer();\n if (!container) {\n return;\n }\n\n const innerSize = container.getInnerSize();\n if (!innerSize) {\n return;\n }\n\n const components = container.getLaidOutComponents();\n const insets = container.getContentInsets();\n const spacing = this.getComponentSpacing();\n const lineSpacing = this.getLineSpacing();\n\n const uniformWidth = this.isUniformWidth();\n const uniformHeight = this.isUniformHeight();\n const extents = (uniformWidth || uniformHeight) ? this.computeUniformExtents(components) : { width: 0, height: 0 };\n\n const rows = this.groupIntoRows(components, innerSize.width, insets.getTop(), spacing, lineSpacing, uniformWidth, uniformHeight, extents);\n\n this.placeRows(rows, insets.getLeft(), innerSize.width, spacing);\n\n // Only a wrap run against a real width says anything. Before the first\n // sizing pass getInnerSize() is NaN-wide, every `> NaN` comparison is\n // false, and the children collapse into one bogus row — the same reason\n // Table.doLayout guards its width arithmetic.\n if (Number.isFinite(innerSize.width)) {\n this.publishWrappedLineExtent(this.rowsCrossExtent(rows, lineSpacing));\n }\n\n this.reserveContentFrame();\n }\n\n /**\n * Phase 1 of {@link HFlow.doLayout}: walks the children left-to-right,\n * wrapping into rows, and records each row's cells, content width, height,\n * and top — without committing any bounds. A first cell wider than the inner\n * width is clamped to that width so its right edge stays inside a scrolling\n * host.\n *\n * @param components - The children to place, in order.\n * @param innerWidth - The container's inner width (the wrap threshold).\n * @param topInset - The container's top content inset (the first row's top).\n * @param spacing - Inter-item horizontal spacing in pixels.\n * @param lineSpacing - Inter-row vertical spacing in pixels.\n * @param uniformWidth - Whether cells take the uniform width.\n * @param uniformHeight - Whether cells take the uniform height.\n * @param extents - The uniform cell extents, when a uniform mode is active.\n * @returns The ordered rows ready for {@link HFlow.placeRows}.\n */\n private groupIntoRows(components: Component[], innerWidth: number, topInset: number, spacing: number, lineSpacing: number, uniformWidth: boolean, uniformHeight: boolean, extents: Size): HFlowRow[] {\n const rows: HFlowRow[] = [];\n let y = topInset;\n let current: HFlowRow | null = null;\n\n for (const component of components) {\n const cell = this.clampedPreferredSize(component);\n const cellWidth = uniformWidth ? extents.width : cell.width;\n const cellHeight = uniformHeight ? extents.height : cell.height;\n\n // Wrap before placing when the current row is non-empty and this\n // cell's right edge (including the joining spacing) would spill past\n // the inner width.\n if (current && current.contentWidth + spacing + cellWidth > innerWidth) {\n y += current.rowHeight + lineSpacing;\n current = null;\n }\n\n if (!current) {\n current = { cells: [], contentWidth: 0, rowHeight: 0, y: y };\n\n rows.push(current);\n }\n\n // A cell wider than the inner width occupies its own line clamped to\n // that width, so its right edge stays inside a scrolling host.\n const placedWidth = (current.cells.length === 0) ? Math.min(cellWidth, innerWidth) : cellWidth;\n\n current.contentWidth += (current.cells.length === 0) ? placedWidth : spacing + placedWidth;\n current.cells.push({ component: component, width: placedWidth, height: cellHeight, baseline: component.getBaseline() });\n current.rowHeight = this.rowExtent(current, cellHeight);\n }\n\n return rows;\n }\n\n /**\n * Phase 2 of {@link HFlow.doLayout}: distributes each row's cells along the\n * main axis per the `justify` mode (or packs them at the `align` offset when\n * `justify` is `\"start\"`), and positions each cell within the row height per\n * the `itemAlign` mode. Each child keeps its preferred size (`FillType.NONE`);\n * its own {@link AnchorType} positions it within its cell.\n *\n * @param rows - The rows produced by {@link HFlow.groupIntoRows}.\n * @param leftInset - The container's left content inset (the row's leading edge).\n * @param innerWidth - The container's inner width (for the alignment residual).\n * @param spacing - Inter-item horizontal spacing in pixels.\n */\n private placeRows(rows: HFlowRow[], leftInset: number, innerWidth: number, spacing: number): void {\n for (const row of rows) {\n // Row text metrics for \"baseline\" itemAlign (cheap; only used then).\n const heights = row.cells.map(cell => cell.height);\n const baselines = row.cells.map(cell => cell.baseline);\n\n const { rowAscent, rowDescent } = this.computeRowMetrics(heights, baselines);\n\n const { lead, gap } = this.justifyGaps(row.cells.length, this.cellsMainExtent(row), innerWidth, spacing);\n\n // A justify mode fills the inner extent and owns the residual, so the\n // align block move only applies when justify === \"start\".\n const blockLead = this._justify === \"start\"\n ? this.alignLead(row.contentWidth, innerWidth)\n : 0;\n\n let x = leftInset + blockLead + lead;\n\n for (const cell of row.cells) {\n const y = row.y + this.crossOffset(cell.height, row.rowHeight, cell.baseline, rowAscent, rowDescent);\n\n this.placeComponent(cell.component, x, y, cell.width, cell.height, FillType.NONE);\n\n x += cell.width + gap;\n }\n }\n }\n\n /**\n * Sums a row's cell widths without the inter-item spacing — the content\n * main-extent {@link FlowLayout.justifyGaps} distributes the residual around.\n *\n * @param row - The row to measure.\n * @returns The total cell width in pixels.\n */\n private cellsMainExtent(row: HFlowRow): number {\n return row.cells.reduce((sum, cell) => sum + cell.width, 0);\n }\n\n /**\n * Sums the rows' heights plus the gaps between them — the cross extent the\n * children actually occupy once wrapped.\n *\n * @param rows - The rows produced by {@link HFlow.groupIntoRows}.\n * @param lineSpacing - The gap between wrapped rows in pixels.\n *\n * @returns The total row extent in pixels, excluding the container perimeter.\n */\n private rowsCrossExtent(rows: HFlowRow[], lineSpacing: number): number {\n if (rows.length === 0) {\n return 0;\n }\n\n let extent = lineSpacing * (rows.length - 1);\n\n for (const row of rows) {\n extent += row.rowHeight;\n }\n\n return extent;\n }\n\n /**\n * Returns how tall a row has to be to hold the cells placed in it so far,\n * having just taken one more.\n *\n * @param row - The row being filled, including the cell just pushed.\n * @param addedHeight - The height of the cell just pushed.\n *\n * @returns The row's cross extent in pixels.\n *\n * @remarks Under every alignment but `\"baseline\"` a cell is placed inside\n * the row, so the row is exactly its tallest cell — folded in one cell at a\n * time. That agrees with {@link HFlow.lineExtent} over the whole row because\n * a maximum is associative and both start from `0`. Baseline alignment\n * cannot be folded: it offsets each cell by `rowAscent - baseline`, which can\n * push a low-baseline child's descender below the bottom of a taller one, so\n * the row is `rowAscent + rowDescent` — a function of every cell at once,\n * recomputed over the row so far. Using one number for both the row's height\n * and its advance is what keeps wrapped baseline rows from overlapping.\n */\n private rowExtent(row: HFlowRow, addedHeight: number): number {\n if (this._itemAlign !== \"baseline\") {\n return Math.max(row.rowHeight, addedHeight);\n }\n\n return this.lineExtent(\n row.cells.map(cell => cell.height),\n row.cells.map(cell => cell.baseline),\n );\n }\n\n /**\n * Returns how tall one line of children has to be under the current\n * `itemAlign`.\n *\n * @param heights - The children's heights, in line order.\n * @param baselines - Each child's baseline, or null where it reports none.\n *\n * @returns The line's cross extent in pixels.\n *\n * @remarks The shared formula behind the minimum, the pre-layout estimate,\n * and the measured row extent — {@link HFlow.rowExtent} calls it directly\n * for a baseline row and folds the same maximum cell-by-cell otherwise.\n * Before it, the minimum was baseline-aware unconditionally while the\n * measurement was not, which inverted `min <= preferred` for a\n * `start`-aligned row whose children happened to report baselines.\n *\n * One caller opts out: under a `uniform` height mode the preferred size\n * takes the uniform cell height instead of asking here. (The row extent does\n * not opt out — its cells carry the uniform height, but a baseline row is\n * still measured by `rowAscent + rowDescent` over them, which can exceed\n * that height.) A pre-layout `min > preferred` inversion survives for a\n * baseline-aligned uniform row of children with pinned minimums, because the\n * minimum has no uniform cell to take. That inversion predates this method\n * and is not introduced by it; the first layout resolves it.\n */\n private lineExtent(heights: number[], baselines: Array<number | null>): number {\n if (this._itemAlign !== \"baseline\") {\n return heights.reduce((tallest, height) => Math.max(tallest, height), 0);\n }\n\n return this.computeRowHeight(heights, baselines);\n }\n}\n\nconst HFlowCallable = callable(HFlow);\ntype HFlowCallable = HFlow;\nexport {\n HFlow as _HFlow,\n HFlowCallable as HFlow\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { FlowLayout, FlowLayoutOptions } from \"~/layout/FlowLayout.js\";\nimport { FillType } from \"~/layout/FillType.js\";\nimport { Size, UNBOUNDED, isUnbounded } from \"~/primitive/Size.js\";\nimport { Component } from \"~/core/Component.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link VFlow}.\n *\n * @remarks Inherits every flow field (`spacing`, `lineSpacing`, `uniform`,\n * `align`, `itemAlign`, `justify`) from {@link FlowLayoutOptions}; `VFlow` adds\n * none of its own. `spacing` is the vertical gap between items in a column;\n * `lineSpacing` is the horizontal gap between wrapped columns.\n *\n * @category Layouts\n */\nexport interface VFlowOptions extends FlowLayoutOptions {}\n\n/**\n * One wrapped column of a {@link VFlow}: its ordered cells (each with its own\n * cell width and the height it was placed at; `baseline` is always `null` since\n * a column exposes no shared text baseline), the column's total content height,\n * the column width (widest cell), and the column's left in the container's\n * coordinate space.\n */\ninterface VFlowColumn {\n cells: Array<{ component: Component; width: number; height: number; baseline: number | null }>;\n contentHeight: number;\n columnWidth: number;\n x: number;\n}\n\n/**\n * A layout manager that packs children in vertical columns, wrapping to a new\n * column when the next child would exceed the container's inner height. The\n * vertical transpose of {@link HFlow}: where `HFlow` packs rows left-to-right\n * and wraps downward, `VFlow` packs columns top-to-bottom and wraps rightward.\n * Like `HFlow` it never shrinks or stretches children — each keeps its preferred\n * size. A scroll-enabled host (`Panel.setAutoScroll`) gains a horizontal\n * scrollbar once the columns exceed its inner width.\n *\n * @remarks Shares its flow configuration (item/line spacing, cell uniformity,\n * line alignment) with `HFlow` through the {@link FlowLayout} base. Here\n * `spacing` is the vertical gap between items in a column and `lineSpacing` the\n * horizontal gap between columns. The `align` option packs each column's content\n * block at the north edge (`\"start\"`, the default), centred, or the south edge;\n * `justify` instead spreads the column's items across the inner height\n * (`\"between\"`/`\"around\"`), and `itemAlign` positions each item within the\n * column width. A wrapped column exposes no shared text baseline, so the cross\n * axis (width) uses a plain widest-cell measure and `itemAlign: \"baseline\"`\n * degrades to `\"start\"`.\n *\n * @category Layouts\n */\nclass VFlow extends FlowLayout {\n\n /**\n * Returns the preferred size. The height is the single-column shape of the\n * children — the sum of their preferred heights plus item spacing, or\n * `count * rowHeight` in a `uniform` height mode. The width is the cross\n * extent the children wrapped into at the last layout: the summed column\n * widths plus the gaps between them.\n *\n * @returns The preferred `{width, height}`, or `null` if no container is attached.\n *\n * @remarks The two axes answer different questions. The height is an\n * aspiration — \"give me this much and I will not wrap at all\" — so it stays\n * the unwrapped sum however the children are actually laid out. The width is\n * a consequence of the height the flow was really given, so it reports the\n * measurement rather than an estimate. Before the first layout at a usable\n * height there is nothing measured yet, and the width falls back to the\n * widest child; a parent that honours preferred sizes corrects that on the\n * pass after the first.\n */\n getPreferredSize(): Size | null {\n const container = this.getContainer();\n if (!container) {\n return null;\n }\n\n const perimeterSize = container.getPerimeterSize();\n const components = container.getLaidOutComponents();\n const uniformWidth = this.isUniformWidth();\n const uniformHeight = this.isUniformHeight();\n const extents = (uniformWidth || uniformHeight) ? this.computeUniformExtents(components) : { width: 0, height: 0 };\n\n let height = perimeterSize.top + perimeterSize.bottom;\n let maxWidth = 0;\n\n for (const component of components) {\n const size = component.getPreferredSize();\n\n if (size) {\n if (!uniformHeight) {\n height += size.height;\n }\n\n maxWidth = Math.max(maxWidth, size.width);\n }\n }\n\n if (uniformHeight) {\n height += components.length * extents.height;\n }\n\n height += this._spacing * Math.max(0, components.length - 1);\n\n // The measured extent covers every wrapped column; the single-column\n // estimate below it is only reachable before the first layout at a real\n // height.\n const measured = this.getWrappedLineExtent();\n\n let width = measured !== null\n ? measured\n : (uniformWidth ? extents.width : maxWidth);\n\n width += perimeterSize.left + perimeterSize.right;\n\n return {\n width: width,\n height: height\n };\n }\n\n /**\n * Returns the minimum size: the tallest child's min height (the floor below\n * which not even one child per column fits) and the widest child's min\n * width.\n *\n * @returns The minimum `{width, height}`, or `null` if no container is attached.\n */\n getMinSize(): Size | null {\n const container = this.getContainer();\n if (!container) {\n return null;\n }\n\n const perimeterSize = container.getPerimeterSize();\n const components = container.getLaidOutComponents();\n\n let maxChildMinHeight = 0;\n let maxWidth = 0;\n\n for (const component of components) {\n const size = component.getMinSize();\n\n if (size) {\n maxChildMinHeight = Math.max(maxChildMinHeight, size.height);\n maxWidth = Math.max(maxWidth, size.width);\n }\n }\n\n const width = perimeterSize.left + perimeterSize.right + maxWidth;\n const height = perimeterSize.top + perimeterSize.bottom + maxChildMinHeight;\n\n return {\n width: width,\n height: height\n };\n }\n\n /**\n * Returns the maximum size the flow can usefully occupy: with every child in\n * one column the height is the sum of the children's *maximum* heights (or\n * `count * rowHeight` in a `uniform` height mode) plus item spacing, and the\n * width is the *largest* child maximum — the widest a single column can grow\n * to. A child whose maximum is `null` or at the unbounded sentinel makes that\n * axis unbounded.\n *\n * @returns The maximum `{width, height}`, or `null` if no container is attached.\n *\n * @remarks Once a layout has measured a wrapped width, that measurement\n * floors the width reported here. A single column's maximum can otherwise\n * sit below the wrapped width the preferred size reports, and a host that\n * sizes itself to its content would clamp the flow back to one column and\n * clip the rest.\n */\n getMaxSize(): Size | null {\n const container = this.getContainer();\n if (!container) {\n return null;\n }\n\n const perimeterSize = container.getPerimeterSize();\n const components = container.getLaidOutComponents();\n const uniformHeight = this.isUniformHeight();\n const extents = uniformHeight ? this.computeUniformExtents(components) : { width: 0, height: 0 };\n\n let height = perimeterSize.top + perimeterSize.bottom;\n let width = 0;\n let widthUnbounded = false;\n let heightUnbounded = false;\n\n for (const component of components) {\n const max = component.getMaxSize();\n\n if (!max) {\n if (!uniformHeight) {\n heightUnbounded = true;\n }\n widthUnbounded = true;\n continue;\n }\n\n if (!uniformHeight) {\n if (isUnbounded(max.height)) {\n heightUnbounded = true;\n } else {\n height += max.height;\n }\n }\n\n if (isUnbounded(max.width)) {\n widthUnbounded = true;\n } else {\n width = Math.max(width, max.width);\n }\n }\n\n if (uniformHeight) {\n height += components.length * extents.height;\n }\n\n height += this._spacing * Math.max(0, components.length - 1);\n\n // The single-column maximum above can sit below the wrapped extent\n // getPreferredSize now reports. ARCHITECTURE binds min <= preferred <=\n // max, and a host that clamps to its content would otherwise clamp the\n // flow back to one column's width — re-clipping the very overflow the\n // measurement exists to expose. Floor the maximum at the measurement.\n const measured = this.getWrappedLineExtent();\n\n if (measured !== null && !widthUnbounded) {\n width = Math.max(width, measured);\n }\n\n width += perimeterSize.left + perimeterSize.right;\n\n return {\n width: widthUnbounded ? UNBOUNDED : width,\n height: heightUnbounded ? UNBOUNDED : height\n };\n }\n\n /**\n * Packs the children top-to-bottom at their cell size, wrapping to a new\n * column when the next cell's bottom edge would exceed the inner height, then\n * places each column's content block per the `align` mode. In a `uniform`\n * mode every cell grows to the widest and/or tallest item so the wrapped\n * items line up into a grid. A scroll-enabled host then scrolls the overflow\n * via `reserveContentFrame`, which sizes the content frame to the children's\n * committed extent.\n */\n doLayout(): void {\n const container = this.getContainer();\n if (!container) {\n return;\n }\n\n const innerSize = container.getInnerSize();\n if (!innerSize) {\n return;\n }\n\n const components = container.getLaidOutComponents();\n const insets = container.getContentInsets();\n const spacing = this.getComponentSpacing();\n const lineSpacing = this.getLineSpacing();\n\n const uniformWidth = this.isUniformWidth();\n const uniformHeight = this.isUniformHeight();\n const extents = (uniformWidth || uniformHeight) ? this.computeUniformExtents(components) : { width: 0, height: 0 };\n\n const columns = this.groupIntoColumns(components, innerSize.height, insets.getLeft(), spacing, lineSpacing, uniformWidth, uniformHeight, extents);\n\n this.placeColumns(columns, insets.getTop(), innerSize.height, spacing);\n\n // Only a wrap run against a real height says anything. Before the first\n // sizing pass getInnerSize() is NaN-tall, every `> NaN` comparison is\n // false, and the children collapse into one bogus column — the same\n // reason Table.doLayout guards its own arithmetic.\n if (Number.isFinite(innerSize.height)) {\n this.publishWrappedLineExtent(this.columnsCrossExtent(columns, lineSpacing));\n }\n\n this.reserveContentFrame();\n }\n\n /**\n * Phase 1 of {@link VFlow.doLayout}: walks the children top-to-bottom,\n * wrapping into columns, and records each column's cells, content height,\n * width, and left — without committing any bounds. A first cell taller than\n * the inner height is clamped to that height so its bottom edge stays inside\n * a scrolling host.\n *\n * @param components - The children to place, in order.\n * @param innerHeight - The container's inner height (the wrap threshold).\n * @param leftInset - The container's left content inset (the first column's left).\n * @param spacing - Inter-item vertical spacing in pixels.\n * @param lineSpacing - Inter-column horizontal spacing in pixels.\n * @param uniformWidth - Whether cells take the uniform width.\n * @param uniformHeight - Whether cells take the uniform height.\n * @param extents - The uniform cell extents, when a uniform mode is active.\n * @returns The ordered columns ready for {@link VFlow.placeColumns}.\n */\n private groupIntoColumns(components: Component[], innerHeight: number, leftInset: number, spacing: number, lineSpacing: number, uniformWidth: boolean, uniformHeight: boolean, extents: Size): VFlowColumn[] {\n const columns: VFlowColumn[] = [];\n let x = leftInset;\n let current: VFlowColumn | null = null;\n\n for (const component of components) {\n const cell = this.clampedPreferredSize(component);\n const cellWidth = uniformWidth ? extents.width : cell.width;\n const cellHeight = uniformHeight ? extents.height : cell.height;\n\n // Wrap before placing when the current column is non-empty and this\n // cell's bottom edge (including the joining spacing) would spill past\n // the inner height.\n if (current && current.contentHeight + spacing + cellHeight > innerHeight) {\n x += current.columnWidth + lineSpacing;\n current = null;\n }\n\n if (!current) {\n current = { cells: [], contentHeight: 0, columnWidth: 0, x: x };\n\n columns.push(current);\n }\n\n // A cell taller than the inner height occupies its own column clamped\n // to that height, so its bottom edge stays inside a scrolling host.\n const placedHeight = (current.cells.length === 0) ? Math.min(cellHeight, innerHeight) : cellHeight;\n\n current.contentHeight += (current.cells.length === 0) ? placedHeight : spacing + placedHeight;\n current.cells.push({ component: component, width: cellWidth, height: placedHeight, baseline: null });\n current.columnWidth = Math.max(current.columnWidth, cellWidth);\n }\n\n return columns;\n }\n\n /**\n * Phase 2 of {@link VFlow.doLayout}: distributes each column's cells along\n * the main axis per the `justify` mode (or packs them at the `align` offset\n * when `justify` is `\"start\"`), and positions each cell within the column\n * width per the `itemAlign` mode. The cross axis is width, which has no text\n * baseline, so `\"baseline\"` degrades to `\"start\"`. Each child keeps its\n * preferred size (`FillType.NONE`); its own {@link AnchorType} positions it\n * within its cell.\n *\n * @param columns - The columns produced by {@link VFlow.groupIntoColumns}.\n * @param topInset - The container's top content inset (the column's leading edge).\n * @param innerHeight - The container's inner height (for the alignment residual).\n * @param spacing - Inter-item vertical spacing in pixels.\n */\n private placeColumns(columns: VFlowColumn[], topInset: number, innerHeight: number, spacing: number): void {\n for (const column of columns) {\n const { lead, gap } = this.justifyGaps(column.cells.length, this.cellsMainExtent(column), innerHeight, spacing);\n\n // A justify mode fills the inner extent and owns the residual, so the\n // align block move only applies when justify === \"start\".\n const blockLead = this._justify === \"start\"\n ? this.alignLead(column.contentHeight, innerHeight)\n : 0;\n\n let y = topInset + blockLead + lead;\n\n for (const cell of column.cells) {\n // rowAscent null → \"baseline\" degrades to \"start\"; cross axis is width.\n const x = column.x + this.crossOffset(cell.width, column.columnWidth, null, null, 0);\n\n this.placeComponent(cell.component, x, y, cell.width, cell.height, FillType.NONE);\n\n y += cell.height + gap;\n }\n }\n }\n\n /**\n * Sums a column's cell heights without the inter-item spacing — the content\n * main-extent {@link FlowLayout.justifyGaps} distributes the residual around.\n *\n * @param column - The column to measure.\n * @returns The total cell height in pixels.\n */\n private cellsMainExtent(column: VFlowColumn): number {\n return column.cells.reduce((sum, cell) => sum + cell.height, 0);\n }\n\n /**\n * Sums the columns' widths plus the gaps between them — the cross extent the\n * children actually occupy once wrapped.\n *\n * @param columns - The columns produced by {@link VFlow.groupIntoColumns}.\n * @param lineSpacing - The gap between wrapped columns in pixels.\n *\n * @returns The total column extent in pixels, excluding the container perimeter.\n */\n private columnsCrossExtent(columns: VFlowColumn[], lineSpacing: number): number {\n if (columns.length === 0) {\n return 0;\n }\n\n let extent = lineSpacing * (columns.length - 1);\n\n for (const column of columns) {\n extent += column.columnWidth;\n }\n\n return extent;\n }\n}\n\nconst VFlowCallable = callable(VFlow);\ntype VFlowCallable = VFlow;\nexport {\n VFlow as _VFlow,\n VFlowCallable as VFlow\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"layout.es.js","names":[],"sources":["../../src/typescript/lib/layout/FlowLayout.ts","../../src/typescript/lib/layout/HFlow.ts","../../src/typescript/lib/layout/VFlow.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { LayoutManager, LayoutManagerOptions } from \"~/layout/LayoutManager.js\";\nimport { Size } from \"~/primitive/Size.js\";\nimport { Component } from \"~/core/Component.js\";\nimport type { AxisPosition, AxisSpread } from \"~/primitive/Axis.js\";\n\n/**\n * Which axes of a {@link FlowLayout}'s cells are made uniform so wrapped items\n * line up into a grid.\n *\n * - `\"none\"` (the default) — each item keeps its own preferred size and lines\n * pack independently, so columns do not align across lines.\n * - `\"width\"` — every cell takes the widest item's width, so columns align\n * horizontally; each line still uses its own (tallest-item) height.\n * - `\"height\"` — every cell takes the tallest item's height, so lines align\n * vertically; widths still vary per item.\n * - `\"both\"` — every cell is identical (widest × tallest), a full grid.\n *\n * @category Layouts\n */\nexport type FlowUniformity = \"none\" | \"width\" | \"height\" | \"both\";\n\n/**\n * Cross-axis alignment of an item within its wrapped line's cross extent — the\n * row height for {@link HFlow}, the column width for {@link VFlow}.\n *\n * - `\"start\"` (the default) — leading cross-edge (HFlow top, VFlow left). This\n * is the original placement.\n * - `\"center\"` — centred in the line's cross extent.\n * - `\"end\"` — trailing cross-edge (HFlow bottom, VFlow right).\n * - `\"baseline\"` — {@link HFlow} only: items are aligned on their shared text\n * baseline across the row; null-baseline (graphical) items centre in the text\n * line. {@link VFlow} has no shared text baseline, so it degrades to\n * `\"start\"`.\n *\n * @remarks This positions the *cell* within the line; a child's\n * {@link AnchorType} still positions the child within its (possibly uniform)\n * cell — both apply. Flow never resizes cells, so alignment only moves them.\n *\n * @category Layouts\n */\nexport type FlowItemAlign = \"start\" | \"center\" | \"end\" | \"baseline\";\n\n/**\n * Construction-time options shared by {@link HFlow} and {@link VFlow}.\n *\n * @category Layouts\n */\nexport interface FlowLayoutOptions extends LayoutManagerOptions {\n spacing?: number;\n lineSpacing?: number;\n uniform?: FlowUniformity;\n align?: AxisPosition;\n itemAlign?: FlowItemAlign;\n justify?: AxisSpread;\n}\n\n/**\n * Abstract base for the wrapping flow layouts {@link HFlow} and {@link VFlow}.\n * Holds the axis-agnostic configuration plumbing — item spacing, line spacing,\n * cell uniformity, and line alignment — and the shared cell-measurement\n * helpers, and dispatches a {@link FlowLayoutOptions} bag.\n *\n * @remarks This deliberately does not extend {@link BoxLayout}. That base models\n * a non-wrapping single-axis box — `mode`, `stretching`, `weight`, proportional\n * shrink, and a min-total overflow inflation — none of which a wrapping flow\n * uses. The geometric algorithms (`getPreferredSize`, `getMinSize`,\n * `getMaxSize`, `doLayout`) are mirror-image per axis and stay concrete on each\n * subclass.\n *\n * @category Layouts\n */\nexport abstract class FlowLayout extends LayoutManager {\n\n // `protected`, not `private`: the subclasses' geometric methods\n // (getPreferredSize/getMinSize/getMaxSize/doLayout) read these fields\n // directly, so they must be visible to HFlow/VFlow.\n protected _spacing: number = 5;\n protected _lineSpacing: number = 5;\n protected _uniform: FlowUniformity = \"none\";\n protected _align: AxisPosition = \"start\";\n protected _itemAlign: FlowItemAlign = \"start\";\n protected _justify: AxisSpread = \"start\";\n\n // The cross-axis extent the children last wrapped into, measured by doLayout\n // at the container's real inner extent. `null` until a layout has run at a\n // usable extent, which is what makes the single-line fallback in each\n // subclass's getPreferredSize reachable on the first pass.\n private _wrappedLineExtent: number | null = null;\n\n /**\n * Constructs the layout manager, applying any supplied options.\n *\n * @param options - Optional construction-time configuration.\n */\n constructor(options?: FlowLayoutOptions) {\n // LayoutManager's constructor takes no options; applied via applyOptions below.\n // eslint-disable-next-line local/forward-super-options\n super();\n\n if (options) {\n this.applyOptions(options);\n }\n }\n\n /**\n * Applies a {@link FlowLayoutOptions} bag after the inherited LayoutManager\n * defaults, dispatching the item and line spacings, the uniformity mode, and\n * the line alignment.\n *\n * @param options - The options bag carrying the values to apply.\n */\n protected applyOptions(options: FlowLayoutOptions): void {\n super.applyOptions(options);\n\n if (options.spacing !== undefined) {\n this.setComponentSpacing(options.spacing);\n }\n\n if (options.lineSpacing !== undefined) {\n this.setLineSpacing(options.lineSpacing);\n }\n\n if (options.uniform !== undefined) {\n this.setUniform(options.uniform);\n }\n\n if (options.align !== undefined) {\n this.setAlign(options.align);\n }\n\n if (options.itemAlign !== undefined) {\n this.setItemAlign(options.itemAlign);\n }\n\n if (options.justify !== undefined) {\n this.setJustify(options.justify);\n }\n }\n\n /**\n * Returns the pixel spacing between items along a line.\n *\n * @returns The current item spacing in pixels.\n */\n getComponentSpacing(): number {\n return this._spacing || 0;\n }\n\n /**\n * Sets the pixel spacing between items along a line.\n *\n * @param spacing - Spacing in pixels.\n *\n * @returns This layout manager, for method chaining.\n */\n setComponentSpacing(spacing: number): this {\n this._spacing = spacing || 0;\n\n return this;\n }\n\n /**\n * Returns the pixel spacing between wrapped lines.\n *\n * @returns The current line spacing in pixels.\n */\n getLineSpacing(): number {\n return this._lineSpacing || 0;\n }\n\n /**\n * Sets the pixel spacing between wrapped lines.\n *\n * @param lineSpacing - Spacing in pixels.\n *\n * @returns This layout manager, for method chaining.\n */\n setLineSpacing(lineSpacing: number): this {\n this._lineSpacing = lineSpacing || 0;\n\n return this;\n }\n\n /**\n * Returns the cross-axis extent the children wrapped into at the last\n * layout, or null if no layout has run at a usable extent yet.\n *\n * @returns The measured line extent in pixels, or null.\n *\n * @remarks The number covers the lines only — summed row heights (or column\n * widths) plus the gaps between them. It carries no insets, padding, or\n * border, so a caller adds the perimeter back itself.\n */\n protected getWrappedLineExtent(): number | null {\n return this._wrappedLineExtent;\n }\n\n /**\n * Records the cross-axis extent the children wrapped into, and tells the\n * container when that measurement has changed.\n *\n * @param extent - The measured line extent in pixels.\n *\n * @remarks The equality check is the loop guard. A settled layout publishes\n * the same extent on every pass and therefore notifies nothing; without the\n * check each pass would relay a size change that schedules the next one.\n *\n * A non-finite extent is dropped rather than stored, because it would defeat\n * that guard: `NaN !== NaN`, so every pass would look like a change and relay\n * one. One child with a `NaN` preferred height — a text whose font has not\n * resolved, say — is enough to poison the sum. Dropping it also keeps the\n * single-line fallback reachable, which is the right answer when nothing\n * usable was measured.\n */\n protected publishWrappedLineExtent(extent: number): void {\n if (!Number.isFinite(extent) || this._wrappedLineExtent === extent) {\n return;\n }\n\n this._wrappedLineExtent = extent;\n\n this.getContainer()?.notifyIntrinsicSizeChanged();\n }\n\n /**\n * Attaches to a container, dropping any measurement taken against a previous\n * one.\n *\n * @param container - The container component to attach to.\n *\n * @returns This layout manager, for method chaining.\n *\n * @remarks Clearing here rather than only in {@link FlowLayout.detach} is\n * what covers a manager moved between containers. `Component.setLayoutManager`\n * detaches the *container's* outgoing manager, never the *manager's* previous\n * container, so a reused manager arrives still holding the old measurement\n * and would report it for children it no longer has.\n */\n attach(container: Component): this {\n super.attach(container);\n\n this._wrappedLineExtent = null;\n\n return this;\n }\n\n /**\n * Returns which axes are made uniform so wrapped items align into a grid.\n *\n * @returns The current uniformity mode.\n */\n getUniform(): FlowUniformity {\n return this._uniform;\n }\n\n /**\n * Sets which axes are made uniform so wrapped items align into a grid.\n *\n * @param uniform - `\"width\"` aligns columns, `\"height\"` aligns rows,\n * `\"both\"` produces a full grid, `\"none\"` packs each item at its own\n * size. See {@link FlowUniformity}.\n *\n * @returns This layout manager, for method chaining.\n */\n setUniform(uniform: FlowUniformity): this {\n this._uniform = uniform;\n\n return this;\n }\n\n /**\n * Returns how each wrapped line's content block is packed along the main\n * axis within the container's inner main extent.\n *\n * @returns The current line alignment.\n */\n getAlign(): AxisPosition {\n return this._align;\n }\n\n /**\n * Sets how each wrapped line's content block is packed along the main axis.\n *\n * @param align - `\"start\"` packs at the leading edge (the default),\n * `\"center\"` centres the block, `\"end\"` packs at the trailing edge. The\n * leading/trailing edges are west/east for {@link HFlow} and north/south\n * for {@link VFlow}. See {@link AxisPosition}.\n *\n * @returns This layout manager, for method chaining.\n */\n setAlign(align: AxisPosition): this {\n this._align = align;\n\n return this;\n }\n\n /**\n * Returns how each item is aligned within its wrapped line's cross extent.\n *\n * @returns The current cross-axis item alignment.\n */\n getItemAlign(): FlowItemAlign {\n return this._itemAlign;\n }\n\n /**\n * Sets how each item is aligned within its wrapped line's cross extent — the\n * row height for {@link HFlow}, the column width for {@link VFlow}.\n *\n * @param itemAlign - `\"start\"` aligns to the leading cross-edge (the\n * default), `\"center\"` centres, `\"end\"` aligns to the trailing cross-edge,\n * `\"baseline\"` aligns text baselines across an {@link HFlow} row.\n * `\"baseline\"` degrades to `\"start\"` on {@link VFlow}, which has no shared\n * text baseline. See {@link FlowItemAlign}.\n *\n * @returns This layout manager, for method chaining.\n */\n setItemAlign(itemAlign: FlowItemAlign): this {\n this._itemAlign = itemAlign;\n\n return this;\n }\n\n /**\n * Returns how each wrapped line's items are distributed along the main axis.\n *\n * @returns The current main-axis distribution.\n */\n getJustify(): AxisSpread {\n return this._justify;\n }\n\n /**\n * Sets how each wrapped line's items are distributed along the main axis by\n * growing the inter-item gaps.\n *\n * @param justify - `\"start\"` packs items with the fixed `spacing` (the\n * default), `\"between\"` makes the first/last items flush to the edges with\n * equal interior gaps, `\"around\"` puts an equal gap around every item. See\n * {@link AxisSpread}.\n *\n * @returns This layout manager, for method chaining.\n *\n * @remarks When `justify` is `\"between\"` or `\"around\"` the line fills the\n * inner main extent, so it owns the residual and {@link AxisPosition} (the\n * `align` option) is ignored. A single-item or over-long line degrades to\n * `\"start\"`.\n */\n setJustify(justify: AxisSpread): this {\n this._justify = justify;\n\n return this;\n }\n\n /**\n * Whether cells are made uniform on the horizontal axis (columns align).\n *\n * @returns `true` for the `\"width\"` and `\"both\"` uniformity modes.\n */\n protected isUniformWidth(): boolean {\n return this._uniform === \"width\" || this._uniform === \"both\";\n }\n\n /**\n * Whether cells are made uniform on the vertical axis (rows align).\n *\n * @returns `true` for the `\"height\"` and `\"both\"` uniformity modes.\n */\n protected isUniformHeight(): boolean {\n return this._uniform === \"height\" || this._uniform === \"both\";\n }\n\n /**\n * Computes the uniform cell extent: the widest and tallest clamped preferred\n * size across the children, used to size cells in a `uniform` mode.\n *\n * @param components - The children sharing the flow.\n * @returns The `{width, height}` every uniform cell uses on its axis.\n */\n protected computeUniformExtents(components: Component[]): Size {\n let width = 0;\n let height = 0;\n\n for (const component of components) {\n const cell = this.clampedPreferredSize(component);\n\n width = Math.max(width, cell.width);\n height = Math.max(height, cell.height);\n }\n\n return {\n width: width,\n height: height\n };\n }\n\n /**\n * Resolves a child's placed size: its preferred size clamped to its own\n * min and max sizes — the minimum wins when the two conflict.\n *\n * @param component - The child to measure.\n * @returns The clamped `{width, height}`.\n */\n protected clampedPreferredSize(component: Component): Size {\n const pref = component.getPreferredSize();\n const min = component.getMinSize();\n const max = component.getMaxSize();\n\n let width = pref ? pref.width : 0;\n let height = pref ? pref.height : 0;\n\n if (max) {\n width = Math.min(width, max.width);\n height = Math.min(height, max.height);\n }\n\n if (min) {\n width = Math.max(width, min.width);\n height = Math.max(height, min.height);\n }\n\n return {\n width: width,\n height: height\n };\n }\n\n /**\n * Computes the per-line leading offset that packs a content block of the\n * given main extent within the inner main extent per the alignment mode.\n *\n * @param contentMain - The line's content main-extent (sum of placed cell\n * main-extents plus inter-item spacing).\n * @param innerMain - The container's inner extent along the main axis.\n * @returns The leading offset in pixels — `0` for `\"start\"`, half the\n * residual for `\"center\"`, the full residual for `\"end\"`. An over-long\n * line (content exceeding the inner extent) clamps to `0`.\n */\n protected alignLead(contentMain: number, innerMain: number): number {\n const residual = Math.max(0, innerMain - contentMain);\n\n if (this._align === \"center\") {\n return residual / 2;\n }\n\n if (this._align === \"end\") {\n return residual;\n }\n\n return 0;\n }\n\n /**\n * Computes the leading cross-axis offset that positions a cell within its\n * line's cross extent per the {@link FlowItemAlign} mode. The caller adds\n * this to the line's leading cross-edge (the row top for {@link HFlow}, the\n * column left for {@link VFlow}).\n *\n * @param cellExtent - The cell's own cross extent (its height for HFlow, its\n * width for VFlow).\n * @param lineExtent - The line's cross extent (the row height for HFlow, the\n * column width for VFlow); always at least `cellExtent`.\n * @param baseline - The cell's own baseline, or `null` for a graphical cell.\n * Only consulted for `\"baseline\"`.\n * @param rowAscent - The line's text baseline from `computeRowMetrics`, or\n * `null` when no cell reports one (always `null` for VFlow). Only consulted\n * for `\"baseline\"`.\n * @param rowDescent - The line's text descent from `computeRowMetrics`. Only\n * consulted for `\"baseline\"`.\n * @returns The leading offset in pixels — `0` for `\"start\"`, and never\n * negative.\n *\n * @remarks The `\"baseline\"` arm mirrors HBox's per-child baseline placement:\n * a text-bearing cell aligns on `rowAscent - baseline`, a null-baseline cell\n * centres in the text line, and a baseline-less line (`rowAscent === null`,\n * the VFlow case) falls back to `\"start\"`.\n */\n protected crossOffset(cellExtent: number, lineExtent: number, baseline: number | null, rowAscent: number | null, rowDescent: number): number {\n switch (this._itemAlign) {\n case \"center\":\n return Math.max(0, (lineExtent - cellExtent) / 2);\n\n case \"end\":\n return Math.max(0, lineExtent - cellExtent);\n\n case \"baseline\":\n if (rowAscent === null) {\n return 0;\n }\n\n return baseline !== null\n ? rowAscent - baseline\n : this.nullChildY(cellExtent, rowAscent, rowDescent);\n\n case \"start\":\n default:\n return 0;\n }\n }\n\n /**\n * Computes the per-line main-axis spacing under the active\n * {@link AxisSpread} mode.\n *\n * @param itemCount - The number of cells in the line.\n * @param contentMain - The sum of the cells' main extents (no spacing).\n * @param innerMain - The container's inner extent along the main axis.\n * @param spacing - The fixed inter-item spacing in pixels.\n * @returns `{ lead, gap }` — `lead` is the offset before the first item and\n * `gap` the spacing between successive items.\n *\n * @remarks Degrades to the fixed `spacing` (and `lead` `0`) for `\"start\"`,\n * single-item lines, and over-long lines, so the gaps are never negative. For\n * the distribution modes the line fills the inner extent, so the caller must\n * skip the `align` block move.\n */\n protected justifyGaps(itemCount: number, contentMain: number, innerMain: number, spacing: number): { lead: number; gap: number } {\n // Degrade to fixed spacing: start mode, fewer than two items, or content\n // already filling (or exceeding) the inner extent — no positive residual\n // to distribute.\n const fixedTotal = contentMain + spacing * Math.max(0, itemCount - 1);\n\n if (this._justify === \"start\" || itemCount < 2 || fixedTotal >= innerMain) {\n return { lead: 0, gap: spacing };\n }\n\n // The total gap budget to distribute, always positive here.\n const free = innerMain - contentMain;\n\n if (this._justify === \"between\") {\n return { lead: 0, gap: free / (itemCount - 1) };\n }\n\n // \"around\": one whole gap per item, split as half-gaps at the two ends.\n const unit = free / itemCount;\n\n return { lead: unit / 2, gap: unit };\n }\n}\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { FlowLayout, FlowLayoutOptions } from \"~/layout/FlowLayout.js\";\nimport { FillType } from \"~/layout/FillType.js\";\nimport { Size, UNBOUNDED, isUnbounded } from \"~/primitive/Size.js\";\nimport { Component } from \"~/core/Component.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link HFlow}.\n *\n * @remarks Inherits every flow field (`spacing`, `lineSpacing`, `uniform`,\n * `align`, `itemAlign`, `justify`) from {@link FlowLayoutOptions}; `HFlow` adds\n * none of its own.\n *\n * @category Layouts\n */\nexport interface HFlowOptions extends FlowLayoutOptions {}\n\n/**\n * One wrapped row of an {@link HFlow}: its ordered cells (each with the width it\n * was placed at, its own cell height, and its baseline for `\"baseline\"`\n * item-alignment), the row's total content width, the row height, and the row's\n * top in the container's coordinate space. The row height is its tallest cell,\n * except under `\"baseline\"` item-alignment where it is `rowAscent + rowDescent`,\n * which can exceed the tallest cell.\n */\ninterface HFlowRow {\n cells: Array<{ component: Component; width: number; height: number; baseline: number | null }>;\n contentWidth: number;\n rowHeight: number;\n y: number;\n}\n\n/**\n * A layout manager that packs children in horizontal rows, wrapping to a new\n * line when the next child would exceed the container's inner width. Unlike\n * {@link HBox} it never shrinks or stretches children: each keeps its preferred\n * size and lines stack downward. A scroll-enabled host (`Panel.setAutoScroll`)\n * gains a vertical scrollbar once the stacked lines exceed its inner height.\n *\n * @remarks Shares its flow configuration (item/line spacing, cell uniformity,\n * line alignment) with {@link VFlow} through the {@link FlowLayout} base. The\n * `uniform` option grows every cell to the widest and/or tallest item so wrapped\n * items line up into a grid; each item is positioned within its cell by its own\n * {@link AnchorType} constraint (default centre). The `align` option packs each\n * row's content block at the west edge (`\"start\"`, the default), centred, or the\n * east edge; `justify` instead spreads the row's items across the inner width\n * (`\"between\"`/`\"around\"`), and `itemAlign` positions each item within the row\n * height (including `\"baseline\"`, which aligns text baselines across the row) —\n * the scroll extent comes entirely from the children's committed positions read\n * by `reserveContentFrame`.\n *\n * @category Layouts\n */\nclass HFlow extends FlowLayout {\n\n /**\n * Returns the preferred size. The width is the single-line shape of the\n * children — the sum of their preferred widths plus item spacing, or\n * `count * columnWidth` in a `uniform` width mode. The height is the cross\n * extent the children wrapped into at the last layout: the summed row\n * heights plus the gaps between them.\n *\n * @returns The preferred `{width, height}`, or `null` if no container is attached.\n *\n * @remarks The two axes answer different questions. The width is an\n * aspiration — \"give me this much and I will not wrap at all\" — so it stays\n * the unwrapped sum however the children are actually laid out. The height\n * is a consequence of the width the flow was really given, so it reports the\n * measurement rather than an estimate. Before the first layout at a usable\n * width there is nothing measured yet, and the height falls back to the\n * height of one row; a parent that honours preferred sizes corrects that on\n * the pass after the first.\n */\n getPreferredSize(): Size | null {\n const container = this.getContainer();\n if (!container) {\n return null;\n }\n\n const perimeterSize = container.getPerimeterSize();\n const components = container.getLaidOutComponents();\n const uniformWidth = this.isUniformWidth();\n const uniformHeight = this.isUniformHeight();\n const extents = (uniformWidth || uniformHeight) ? this.computeUniformExtents(components) : { width: 0, height: 0 };\n\n // The measured extent covers every wrapped row; the single-line estimate\n // is only reachable before the first layout at a real width. Gathering\n // its inputs costs a getBaseline() per child, so skip them once either a\n // measurement or the uniform cell height has already answered the height.\n const measured = this.getWrappedLineExtent();\n const needsEstimate = measured === null && !uniformHeight;\n\n let width = perimeterSize.left + perimeterSize.right;\n const heights: number[] = [];\n const baselines: Array<number | null> = [];\n\n for (const component of components) {\n const size = component.getPreferredSize();\n\n if (size) {\n if (!uniformWidth) {\n width += size.width;\n }\n\n if (needsEstimate) {\n heights.push(size.height);\n baselines.push(component.getBaseline());\n }\n }\n }\n\n if (uniformWidth) {\n width += components.length * extents.width;\n }\n\n width += this._spacing * Math.max(0, components.length - 1);\n\n let height = measured !== null\n ? measured\n : (uniformHeight ? extents.height : this.lineExtent(heights, baselines));\n\n height += perimeterSize.top + perimeterSize.bottom;\n\n return {\n width: width,\n height: height\n };\n }\n\n /**\n * Returns the minimum size: the widest child's min width (the floor below\n * which not even one child per line fits) and one row's height taken over\n * the children's min heights.\n *\n * @returns The minimum `{width, height}`, or `null` if no container is attached.\n *\n * @remarks The row height follows the current `itemAlign` — the tallest min\n * under every alignment that places a cell inside its row, and\n * `rowAscent + rowDescent` under `\"baseline\"`. It has to use the same rule\n * the preferred size does, or a `start`-aligned row of baseline-bearing\n * children reports a minimum above its own preferred height.\n */\n getMinSize(): Size | null {\n const container = this.getContainer();\n if (!container) {\n return null;\n }\n\n const perimeterSize = container.getPerimeterSize();\n const components = container.getLaidOutComponents();\n\n let maxChildMinWidth = 0;\n const heights: number[] = [];\n const baselines: Array<number | null> = [];\n\n for (const component of components) {\n const size = component.getMinSize();\n\n if (size) {\n maxChildMinWidth = Math.max(maxChildMinWidth, size.width);\n heights.push(size.height);\n baselines.push(component.getBaseline());\n }\n }\n\n const width = perimeterSize.left + perimeterSize.right + maxChildMinWidth;\n\n let height = this.lineExtent(heights, baselines);\n\n height += perimeterSize.top + perimeterSize.bottom;\n\n return {\n width: width,\n height: height\n };\n }\n\n /**\n * Returns the maximum size the flow can usefully occupy: with every child on\n * one line the width is the sum of the children's *maximum* widths (or\n * `count * columnWidth` in a `uniform` width mode) plus item spacing, and the\n * height is the *largest* child maximum — the tallest a single row can grow\n * to. A child whose maximum is `null` or at the unbounded sentinel makes that\n * axis unbounded.\n *\n * @returns The maximum `{width, height}`, or `null` if no container is attached.\n *\n * @remarks Once a layout has measured a wrapped height, that measurement\n * floors the height reported here. A single row's maximum can otherwise sit\n * below the wrapped height the preferred size reports, and a host that sizes\n * itself to its content would clamp the flow back to one row and clip the\n * rest.\n */\n getMaxSize(): Size | null {\n const container = this.getContainer();\n if (!container) {\n return null;\n }\n\n const perimeterSize = container.getPerimeterSize();\n const components = container.getLaidOutComponents();\n const uniformWidth = this.isUniformWidth();\n const extents = uniformWidth ? this.computeUniformExtents(components) : { width: 0, height: 0 };\n\n let width = perimeterSize.left + perimeterSize.right;\n let height = 0;\n let widthUnbounded = false;\n let heightUnbounded = false;\n\n for (const component of components) {\n const max = component.getMaxSize();\n\n if (!max) {\n if (!uniformWidth) {\n widthUnbounded = true;\n }\n heightUnbounded = true;\n continue;\n }\n\n if (!uniformWidth) {\n if (isUnbounded(max.width)) {\n widthUnbounded = true;\n } else {\n width += max.width;\n }\n }\n\n if (isUnbounded(max.height)) {\n heightUnbounded = true;\n } else {\n height = Math.max(height, max.height);\n }\n }\n\n if (uniformWidth) {\n width += components.length * extents.width;\n }\n\n width += this._spacing * Math.max(0, components.length - 1);\n\n // The single-row maximum above can sit below the wrapped extent\n // getPreferredSize now reports. ARCHITECTURE binds min <= preferred <=\n // max, and a host that clamps to its content would otherwise clamp the\n // flow back to one row's height — re-clipping the very overflow the\n // measurement exists to expose. Floor the maximum at the measurement.\n const measured = this.getWrappedLineExtent();\n\n if (measured !== null && !heightUnbounded) {\n height = Math.max(height, measured);\n }\n\n height += perimeterSize.top + perimeterSize.bottom;\n\n return {\n width: widthUnbounded ? UNBOUNDED : width,\n height: heightUnbounded ? UNBOUNDED : height\n };\n }\n\n /**\n * Packs the children left-to-right at their cell size, wrapping to a new\n * line when the next cell's right edge would exceed the inner width, then\n * places each row's content block per the `align` mode. In a `uniform` mode\n * every cell grows to the widest and/or tallest item so the wrapped items\n * line up into a grid. A scroll-enabled host then scrolls the overflow via\n * `reserveContentFrame`, which sizes the content frame to the children's\n * committed extent.\n */\n doLayout(): void {\n const container = this.getContainer();\n if (!container) {\n return;\n }\n\n const innerSize = container.getInnerSize();\n if (!innerSize) {\n return;\n }\n\n const components = container.getLaidOutComponents();\n const insets = container.getContentInsets();\n const spacing = this.getComponentSpacing();\n const lineSpacing = this.getLineSpacing();\n\n const uniformWidth = this.isUniformWidth();\n const uniformHeight = this.isUniformHeight();\n const extents = (uniformWidth || uniformHeight) ? this.computeUniformExtents(components) : { width: 0, height: 0 };\n\n const rows = this.groupIntoRows(components, innerSize.width, insets.getTop(), spacing, lineSpacing, uniformWidth, uniformHeight, extents);\n\n this.placeRows(rows, insets.getLeft(), innerSize.width, spacing);\n\n // Only a wrap run against a real width says anything. Before the first\n // sizing pass getInnerSize() is NaN-wide, every `> NaN` comparison is\n // false, and the children collapse into one bogus row — the same reason\n // Table.doLayout guards its width arithmetic.\n if (Number.isFinite(innerSize.width)) {\n this.publishWrappedLineExtent(this.rowsCrossExtent(rows, lineSpacing));\n }\n\n this.reserveContentFrame();\n }\n\n /**\n * Phase 1 of {@link HFlow.doLayout}: walks the children left-to-right,\n * wrapping into rows, and records each row's cells, content width, height,\n * and top — without committing any bounds. A first cell wider than the inner\n * width is clamped to that width so its right edge stays inside a scrolling\n * host.\n *\n * @param components - The children to place, in order.\n * @param innerWidth - The container's inner width (the wrap threshold).\n * @param topInset - The container's top content inset (the first row's top).\n * @param spacing - Inter-item horizontal spacing in pixels.\n * @param lineSpacing - Inter-row vertical spacing in pixels.\n * @param uniformWidth - Whether cells take the uniform width.\n * @param uniformHeight - Whether cells take the uniform height.\n * @param extents - The uniform cell extents, when a uniform mode is active.\n * @returns The ordered rows ready for {@link HFlow.placeRows}.\n */\n private groupIntoRows(components: Component[], innerWidth: number, topInset: number, spacing: number, lineSpacing: number, uniformWidth: boolean, uniformHeight: boolean, extents: Size): HFlowRow[] {\n const rows: HFlowRow[] = [];\n let y = topInset;\n let current: HFlowRow | null = null;\n\n for (const component of components) {\n const cell = this.clampedPreferredSize(component);\n const cellWidth = uniformWidth ? extents.width : cell.width;\n const cellHeight = uniformHeight ? extents.height : cell.height;\n\n // Wrap before placing when the current row is non-empty and this\n // cell's right edge (including the joining spacing) would spill past\n // the inner width.\n if (current && current.contentWidth + spacing + cellWidth > innerWidth) {\n y += current.rowHeight + lineSpacing;\n current = null;\n }\n\n if (!current) {\n current = { cells: [], contentWidth: 0, rowHeight: 0, y: y };\n\n rows.push(current);\n }\n\n // A cell wider than the inner width occupies its own line clamped to\n // that width, so its right edge stays inside a scrolling host.\n const placedWidth = (current.cells.length === 0) ? Math.min(cellWidth, innerWidth) : cellWidth;\n\n current.contentWidth += (current.cells.length === 0) ? placedWidth : spacing + placedWidth;\n current.cells.push({ component: component, width: placedWidth, height: cellHeight, baseline: component.getBaseline() });\n current.rowHeight = this.rowExtent(current, cellHeight);\n }\n\n return rows;\n }\n\n /**\n * Phase 2 of {@link HFlow.doLayout}: distributes each row's cells along the\n * main axis per the `justify` mode (or packs them at the `align` offset when\n * `justify` is `\"start\"`), and positions each cell within the row height per\n * the `itemAlign` mode. Each child keeps its preferred size (`FillType.NONE`);\n * its own {@link AnchorType} positions it within its cell.\n *\n * @param rows - The rows produced by {@link HFlow.groupIntoRows}.\n * @param leftInset - The container's left content inset (the row's leading edge).\n * @param innerWidth - The container's inner width (for the alignment residual).\n * @param spacing - Inter-item horizontal spacing in pixels.\n */\n private placeRows(rows: HFlowRow[], leftInset: number, innerWidth: number, spacing: number): void {\n for (const row of rows) {\n // Row text metrics for \"baseline\" itemAlign (cheap; only used then).\n const heights = row.cells.map(cell => cell.height);\n const baselines = row.cells.map(cell => cell.baseline);\n\n const { rowAscent, rowDescent } = this.computeRowMetrics(heights, baselines);\n\n const { lead, gap } = this.justifyGaps(row.cells.length, this.cellsMainExtent(row), innerWidth, spacing);\n\n // A justify mode fills the inner extent and owns the residual, so the\n // align block move only applies when justify === \"start\".\n const blockLead = this._justify === \"start\"\n ? this.alignLead(row.contentWidth, innerWidth)\n : 0;\n\n let x = leftInset + blockLead + lead;\n\n for (const cell of row.cells) {\n const y = row.y + this.crossOffset(cell.height, row.rowHeight, cell.baseline, rowAscent, rowDescent);\n\n this.placeComponent(cell.component, x, y, cell.width, cell.height, FillType.NONE);\n\n x += cell.width + gap;\n }\n }\n }\n\n /**\n * Sums a row's cell widths without the inter-item spacing — the content\n * main-extent {@link FlowLayout.justifyGaps} distributes the residual around.\n *\n * @param row - The row to measure.\n * @returns The total cell width in pixels.\n */\n private cellsMainExtent(row: HFlowRow): number {\n return row.cells.reduce((sum, cell) => sum + cell.width, 0);\n }\n\n /**\n * Sums the rows' heights plus the gaps between them — the cross extent the\n * children actually occupy once wrapped.\n *\n * @param rows - The rows produced by {@link HFlow.groupIntoRows}.\n * @param lineSpacing - The gap between wrapped rows in pixels.\n *\n * @returns The total row extent in pixels, excluding the container perimeter.\n */\n private rowsCrossExtent(rows: HFlowRow[], lineSpacing: number): number {\n if (rows.length === 0) {\n return 0;\n }\n\n let extent = lineSpacing * (rows.length - 1);\n\n for (const row of rows) {\n extent += row.rowHeight;\n }\n\n return extent;\n }\n\n /**\n * Returns how tall a row has to be to hold the cells placed in it so far,\n * having just taken one more.\n *\n * @param row - The row being filled, including the cell just pushed.\n * @param addedHeight - The height of the cell just pushed.\n *\n * @returns The row's cross extent in pixels.\n *\n * @remarks Under every alignment but `\"baseline\"` a cell is placed inside\n * the row, so the row is exactly its tallest cell — folded in one cell at a\n * time. That agrees with {@link HFlow.lineExtent} over the whole row because\n * a maximum is associative and both start from `0`. Baseline alignment\n * cannot be folded: it offsets each cell by `rowAscent - baseline`, which can\n * push a low-baseline child's descender below the bottom of a taller one, so\n * the row is `rowAscent + rowDescent` — a function of every cell at once,\n * recomputed over the row so far. Using one number for both the row's height\n * and its advance is what keeps wrapped baseline rows from overlapping.\n */\n private rowExtent(row: HFlowRow, addedHeight: number): number {\n if (this._itemAlign !== \"baseline\") {\n return Math.max(row.rowHeight, addedHeight);\n }\n\n return this.lineExtent(\n row.cells.map(cell => cell.height),\n row.cells.map(cell => cell.baseline),\n );\n }\n\n /**\n * Returns how tall one line of children has to be under the current\n * `itemAlign`.\n *\n * @param heights - The children's heights, in line order.\n * @param baselines - Each child's baseline, or null where it reports none.\n *\n * @returns The line's cross extent in pixels.\n *\n * @remarks The shared formula behind the minimum, the pre-layout estimate,\n * and the measured row extent — {@link HFlow.rowExtent} calls it directly\n * for a baseline row and folds the same maximum cell-by-cell otherwise.\n * Before it, the minimum was baseline-aware unconditionally while the\n * measurement was not, which inverted `min <= preferred` for a\n * `start`-aligned row whose children happened to report baselines.\n *\n * One caller opts out: under a `uniform` height mode the preferred size\n * takes the uniform cell height instead of asking here. (The row extent does\n * not opt out — its cells carry the uniform height, but a baseline row is\n * still measured by `rowAscent + rowDescent` over them, which can exceed\n * that height.) A pre-layout `min > preferred` inversion survives for a\n * baseline-aligned uniform row of children with pinned minimums, because the\n * minimum has no uniform cell to take. That inversion predates this method\n * and is not introduced by it; the first layout resolves it.\n */\n private lineExtent(heights: number[], baselines: Array<number | null>): number {\n if (this._itemAlign !== \"baseline\") {\n return heights.reduce((tallest, height) => Math.max(tallest, height), 0);\n }\n\n return this.computeRowHeight(heights, baselines);\n }\n}\n\nconst HFlowCallable = callable(HFlow);\ntype HFlowCallable = HFlow;\nexport {\n HFlow as _HFlow,\n HFlowCallable as HFlow\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { FlowLayout, FlowLayoutOptions } from \"~/layout/FlowLayout.js\";\nimport { FillType } from \"~/layout/FillType.js\";\nimport { Size, UNBOUNDED, isUnbounded } from \"~/primitive/Size.js\";\nimport { Component } from \"~/core/Component.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link VFlow}.\n *\n * @remarks Inherits every flow field (`spacing`, `lineSpacing`, `uniform`,\n * `align`, `itemAlign`, `justify`) from {@link FlowLayoutOptions}; `VFlow` adds\n * none of its own. `spacing` is the vertical gap between items in a column;\n * `lineSpacing` is the horizontal gap between wrapped columns.\n *\n * @category Layouts\n */\nexport interface VFlowOptions extends FlowLayoutOptions {}\n\n/**\n * One wrapped column of a {@link VFlow}: its ordered cells (each with its own\n * cell width and the height it was placed at; `baseline` is always `null` since\n * a column exposes no shared text baseline), the column's total content height,\n * the column width (widest cell), and the column's left in the container's\n * coordinate space.\n */\ninterface VFlowColumn {\n cells: Array<{ component: Component; width: number; height: number; baseline: number | null }>;\n contentHeight: number;\n columnWidth: number;\n x: number;\n}\n\n/**\n * A layout manager that packs children in vertical columns, wrapping to a new\n * column when the next child would exceed the container's inner height. The\n * vertical transpose of {@link HFlow}: where `HFlow` packs rows left-to-right\n * and wraps downward, `VFlow` packs columns top-to-bottom and wraps rightward.\n * Like `HFlow` it never shrinks or stretches children — each keeps its preferred\n * size. A scroll-enabled host (`Panel.setAutoScroll`) gains a horizontal\n * scrollbar once the columns exceed its inner width.\n *\n * @remarks Shares its flow configuration (item/line spacing, cell uniformity,\n * line alignment) with `HFlow` through the {@link FlowLayout} base. Here\n * `spacing` is the vertical gap between items in a column and `lineSpacing` the\n * horizontal gap between columns. The `align` option packs each column's content\n * block at the north edge (`\"start\"`, the default), centred, or the south edge;\n * `justify` instead spreads the column's items across the inner height\n * (`\"between\"`/`\"around\"`), and `itemAlign` positions each item within the\n * column width. A wrapped column exposes no shared text baseline, so the cross\n * axis (width) uses a plain widest-cell measure and `itemAlign: \"baseline\"`\n * degrades to `\"start\"`.\n *\n * @category Layouts\n */\nclass VFlow extends FlowLayout {\n\n /**\n * Returns the preferred size. The height is the single-column shape of the\n * children — the sum of their preferred heights plus item spacing, or\n * `count * rowHeight` in a `uniform` height mode. The width is the cross\n * extent the children wrapped into at the last layout: the summed column\n * widths plus the gaps between them.\n *\n * @returns The preferred `{width, height}`, or `null` if no container is attached.\n *\n * @remarks The two axes answer different questions. The height is an\n * aspiration — \"give me this much and I will not wrap at all\" — so it stays\n * the unwrapped sum however the children are actually laid out. The width is\n * a consequence of the height the flow was really given, so it reports the\n * measurement rather than an estimate. Before the first layout at a usable\n * height there is nothing measured yet, and the width falls back to the\n * widest child; a parent that honours preferred sizes corrects that on the\n * pass after the first.\n */\n getPreferredSize(): Size | null {\n const container = this.getContainer();\n if (!container) {\n return null;\n }\n\n const perimeterSize = container.getPerimeterSize();\n const components = container.getLaidOutComponents();\n const uniformWidth = this.isUniformWidth();\n const uniformHeight = this.isUniformHeight();\n const extents = (uniformWidth || uniformHeight) ? this.computeUniformExtents(components) : { width: 0, height: 0 };\n\n let height = perimeterSize.top + perimeterSize.bottom;\n let maxWidth = 0;\n\n for (const component of components) {\n const size = component.getPreferredSize();\n\n if (size) {\n if (!uniformHeight) {\n height += size.height;\n }\n\n maxWidth = Math.max(maxWidth, size.width);\n }\n }\n\n if (uniformHeight) {\n height += components.length * extents.height;\n }\n\n height += this._spacing * Math.max(0, components.length - 1);\n\n // The measured extent covers every wrapped column; the single-column\n // estimate below it is only reachable before the first layout at a real\n // height.\n const measured = this.getWrappedLineExtent();\n\n let width = measured !== null\n ? measured\n : (uniformWidth ? extents.width : maxWidth);\n\n width += perimeterSize.left + perimeterSize.right;\n\n return {\n width: width,\n height: height\n };\n }\n\n /**\n * Returns the minimum size: the tallest child's min height (the floor below\n * which not even one child per column fits) and the widest child's min\n * width.\n *\n * @returns The minimum `{width, height}`, or `null` if no container is attached.\n */\n getMinSize(): Size | null {\n const container = this.getContainer();\n if (!container) {\n return null;\n }\n\n const perimeterSize = container.getPerimeterSize();\n const components = container.getLaidOutComponents();\n\n let maxChildMinHeight = 0;\n let maxWidth = 0;\n\n for (const component of components) {\n const size = component.getMinSize();\n\n if (size) {\n maxChildMinHeight = Math.max(maxChildMinHeight, size.height);\n maxWidth = Math.max(maxWidth, size.width);\n }\n }\n\n const width = perimeterSize.left + perimeterSize.right + maxWidth;\n const height = perimeterSize.top + perimeterSize.bottom + maxChildMinHeight;\n\n return {\n width: width,\n height: height\n };\n }\n\n /**\n * Returns the maximum size the flow can usefully occupy: with every child in\n * one column the height is the sum of the children's *maximum* heights (or\n * `count * rowHeight` in a `uniform` height mode) plus item spacing, and the\n * width is the *largest* child maximum — the widest a single column can grow\n * to. A child whose maximum is `null` or at the unbounded sentinel makes that\n * axis unbounded.\n *\n * @returns The maximum `{width, height}`, or `null` if no container is attached.\n *\n * @remarks Once a layout has measured a wrapped width, that measurement\n * floors the width reported here. A single column's maximum can otherwise\n * sit below the wrapped width the preferred size reports, and a host that\n * sizes itself to its content would clamp the flow back to one column and\n * clip the rest.\n */\n getMaxSize(): Size | null {\n const container = this.getContainer();\n if (!container) {\n return null;\n }\n\n const perimeterSize = container.getPerimeterSize();\n const components = container.getLaidOutComponents();\n const uniformHeight = this.isUniformHeight();\n const extents = uniformHeight ? this.computeUniformExtents(components) : { width: 0, height: 0 };\n\n let height = perimeterSize.top + perimeterSize.bottom;\n let width = 0;\n let widthUnbounded = false;\n let heightUnbounded = false;\n\n for (const component of components) {\n const max = component.getMaxSize();\n\n if (!max) {\n if (!uniformHeight) {\n heightUnbounded = true;\n }\n widthUnbounded = true;\n continue;\n }\n\n if (!uniformHeight) {\n if (isUnbounded(max.height)) {\n heightUnbounded = true;\n } else {\n height += max.height;\n }\n }\n\n if (isUnbounded(max.width)) {\n widthUnbounded = true;\n } else {\n width = Math.max(width, max.width);\n }\n }\n\n if (uniformHeight) {\n height += components.length * extents.height;\n }\n\n height += this._spacing * Math.max(0, components.length - 1);\n\n // The single-column maximum above can sit below the wrapped extent\n // getPreferredSize now reports. ARCHITECTURE binds min <= preferred <=\n // max, and a host that clamps to its content would otherwise clamp the\n // flow back to one column's width — re-clipping the very overflow the\n // measurement exists to expose. Floor the maximum at the measurement.\n const measured = this.getWrappedLineExtent();\n\n if (measured !== null && !widthUnbounded) {\n width = Math.max(width, measured);\n }\n\n width += perimeterSize.left + perimeterSize.right;\n\n return {\n width: widthUnbounded ? UNBOUNDED : width,\n height: heightUnbounded ? UNBOUNDED : height\n };\n }\n\n /**\n * Packs the children top-to-bottom at their cell size, wrapping to a new\n * column when the next cell's bottom edge would exceed the inner height, then\n * places each column's content block per the `align` mode. In a `uniform`\n * mode every cell grows to the widest and/or tallest item so the wrapped\n * items line up into a grid. A scroll-enabled host then scrolls the overflow\n * via `reserveContentFrame`, which sizes the content frame to the children's\n * committed extent.\n */\n doLayout(): void {\n const container = this.getContainer();\n if (!container) {\n return;\n }\n\n const innerSize = container.getInnerSize();\n if (!innerSize) {\n return;\n }\n\n const components = container.getLaidOutComponents();\n const insets = container.getContentInsets();\n const spacing = this.getComponentSpacing();\n const lineSpacing = this.getLineSpacing();\n\n const uniformWidth = this.isUniformWidth();\n const uniformHeight = this.isUniformHeight();\n const extents = (uniformWidth || uniformHeight) ? this.computeUniformExtents(components) : { width: 0, height: 0 };\n\n const columns = this.groupIntoColumns(components, innerSize.height, insets.getLeft(), spacing, lineSpacing, uniformWidth, uniformHeight, extents);\n\n this.placeColumns(columns, insets.getTop(), innerSize.height, spacing);\n\n // Only a wrap run against a real height says anything. Before the first\n // sizing pass getInnerSize() is NaN-tall, every `> NaN` comparison is\n // false, and the children collapse into one bogus column — the same\n // reason Table.doLayout guards its own arithmetic.\n if (Number.isFinite(innerSize.height)) {\n this.publishWrappedLineExtent(this.columnsCrossExtent(columns, lineSpacing));\n }\n\n this.reserveContentFrame();\n }\n\n /**\n * Phase 1 of {@link VFlow.doLayout}: walks the children top-to-bottom,\n * wrapping into columns, and records each column's cells, content height,\n * width, and left — without committing any bounds. A first cell taller than\n * the inner height is clamped to that height so its bottom edge stays inside\n * a scrolling host.\n *\n * @param components - The children to place, in order.\n * @param innerHeight - The container's inner height (the wrap threshold).\n * @param leftInset - The container's left content inset (the first column's left).\n * @param spacing - Inter-item vertical spacing in pixels.\n * @param lineSpacing - Inter-column horizontal spacing in pixels.\n * @param uniformWidth - Whether cells take the uniform width.\n * @param uniformHeight - Whether cells take the uniform height.\n * @param extents - The uniform cell extents, when a uniform mode is active.\n * @returns The ordered columns ready for {@link VFlow.placeColumns}.\n */\n private groupIntoColumns(components: Component[], innerHeight: number, leftInset: number, spacing: number, lineSpacing: number, uniformWidth: boolean, uniformHeight: boolean, extents: Size): VFlowColumn[] {\n const columns: VFlowColumn[] = [];\n let x = leftInset;\n let current: VFlowColumn | null = null;\n\n for (const component of components) {\n const cell = this.clampedPreferredSize(component);\n const cellWidth = uniformWidth ? extents.width : cell.width;\n const cellHeight = uniformHeight ? extents.height : cell.height;\n\n // Wrap before placing when the current column is non-empty and this\n // cell's bottom edge (including the joining spacing) would spill past\n // the inner height.\n if (current && current.contentHeight + spacing + cellHeight > innerHeight) {\n x += current.columnWidth + lineSpacing;\n current = null;\n }\n\n if (!current) {\n current = { cells: [], contentHeight: 0, columnWidth: 0, x: x };\n\n columns.push(current);\n }\n\n // A cell taller than the inner height occupies its own column clamped\n // to that height, so its bottom edge stays inside a scrolling host.\n const placedHeight = (current.cells.length === 0) ? Math.min(cellHeight, innerHeight) : cellHeight;\n\n current.contentHeight += (current.cells.length === 0) ? placedHeight : spacing + placedHeight;\n current.cells.push({ component: component, width: cellWidth, height: placedHeight, baseline: null });\n current.columnWidth = Math.max(current.columnWidth, cellWidth);\n }\n\n return columns;\n }\n\n /**\n * Phase 2 of {@link VFlow.doLayout}: distributes each column's cells along\n * the main axis per the `justify` mode (or packs them at the `align` offset\n * when `justify` is `\"start\"`), and positions each cell within the column\n * width per the `itemAlign` mode. The cross axis is width, which has no text\n * baseline, so `\"baseline\"` degrades to `\"start\"`. Each child keeps its\n * preferred size (`FillType.NONE`); its own {@link AnchorType} positions it\n * within its cell.\n *\n * @param columns - The columns produced by {@link VFlow.groupIntoColumns}.\n * @param topInset - The container's top content inset (the column's leading edge).\n * @param innerHeight - The container's inner height (for the alignment residual).\n * @param spacing - Inter-item vertical spacing in pixels.\n */\n private placeColumns(columns: VFlowColumn[], topInset: number, innerHeight: number, spacing: number): void {\n for (const column of columns) {\n const { lead, gap } = this.justifyGaps(column.cells.length, this.cellsMainExtent(column), innerHeight, spacing);\n\n // A justify mode fills the inner extent and owns the residual, so the\n // align block move only applies when justify === \"start\".\n const blockLead = this._justify === \"start\"\n ? this.alignLead(column.contentHeight, innerHeight)\n : 0;\n\n let y = topInset + blockLead + lead;\n\n for (const cell of column.cells) {\n // rowAscent null → \"baseline\" degrades to \"start\"; cross axis is width.\n const x = column.x + this.crossOffset(cell.width, column.columnWidth, null, null, 0);\n\n this.placeComponent(cell.component, x, y, cell.width, cell.height, FillType.NONE);\n\n y += cell.height + gap;\n }\n }\n }\n\n /**\n * Sums a column's cell heights without the inter-item spacing — the content\n * main-extent {@link FlowLayout.justifyGaps} distributes the residual around.\n *\n * @param column - The column to measure.\n * @returns The total cell height in pixels.\n */\n private cellsMainExtent(column: VFlowColumn): number {\n return column.cells.reduce((sum, cell) => sum + cell.height, 0);\n }\n\n /**\n * Sums the columns' widths plus the gaps between them — the cross extent the\n * children actually occupy once wrapped.\n *\n * @param columns - The columns produced by {@link VFlow.groupIntoColumns}.\n * @param lineSpacing - The gap between wrapped columns in pixels.\n *\n * @returns The total column extent in pixels, excluding the container perimeter.\n */\n private columnsCrossExtent(columns: VFlowColumn[], lineSpacing: number): number {\n if (columns.length === 0) {\n return 0;\n }\n\n let extent = lineSpacing * (columns.length - 1);\n\n for (const column of columns) {\n extent += column.columnWidth;\n }\n\n return extent;\n }\n}\n\nconst VFlowCallable = callable(VFlow);\ntype VFlowCallable = VFlow;\nexport {\n VFlow as _VFlow,\n VFlowCallable as VFlow\n};\n"],"mappings":"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"}