silvery 0.18.2 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{animation-DhINOJk8.mjs → animation-Cn64yepo.mjs} +1 -1
- package/dist/{animation-DhINOJk8.mjs.map → animation-Cn64yepo.mjs.map} +1 -1
- package/dist/{ansi-C6Qs1Wn2.mjs → ansi-CLOitHKx.mjs} +1 -1
- package/dist/ansi-CLOitHKx.mjs.map +1 -0
- package/dist/{ansi-CsjnZtAw.d.mts → ansi-Cc33mW54.d.mts} +1 -1
- package/dist/{ansi-CsjnZtAw.d.mts.map → ansi-Cc33mW54.d.mts.map} +1 -1
- package/dist/{chunk-BSw8zbkd.mjs → chunk-Vs_PY4HZ.mjs} +1 -1
- package/dist/cli-BKp0YtBD.mjs +4 -0
- package/dist/{context-BjWgrikx.mjs → context-BU5LkkIy.mjs} +8 -7
- package/dist/context-BU5LkkIy.mjs.map +1 -0
- package/dist/devtools-9QY4teqI.mjs +2 -0
- package/dist/{devtools-CeO9X_uv.mjs → devtools-DxkSLXDA.mjs} +4 -5
- package/dist/devtools-DxkSLXDA.mjs.map +1 -0
- package/dist/{eta-BnQSZcWf.mjs → eta-Bb3RH3wh.mjs} +1 -1
- package/dist/{eta-BnQSZcWf.mjs.map → eta-Bb3RH3wh.mjs.map} +1 -1
- package/dist/{flexily-zero-adapter-BOM0cl8R.mjs → flexily-zero-adapter-BlQa46nr.mjs} +21 -64
- package/dist/flexily-zero-adapter-BlQa46nr.mjs.map +1 -0
- package/dist/{flexily-zero-adapter-V8R3HQtK.mjs → flexily-zero-adapter-CMxXhdOL.mjs} +1 -1
- package/dist/{image-B0zMbVUr.mjs → image-CTII5QWI.mjs} +3 -3
- package/dist/image-CTII5QWI.mjs.map +1 -0
- package/dist/{index-Bh3U1K09.d.mts → index-BXslOebb.d.mts} +547 -137
- package/dist/index-BXslOebb.d.mts.map +1 -0
- package/dist/{index-C4vrhbud.d.mts → index-BnA7mNpo.d.mts} +1 -1
- package/dist/{index-C4vrhbud.d.mts.map → index-BnA7mNpo.d.mts.map} +1 -1
- package/dist/index-D3saHouR.d.mts +1392 -0
- package/dist/index-D3saHouR.d.mts.map +1 -0
- package/dist/index.d.mts +5 -33
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +13 -13
- package/dist/{layout-engine--drvrWjD.mjs → layout-engine-B6Cdz1yZ.mjs} +1 -1
- package/dist/{layout-engine-Dr3cY5U4.mjs → layout-engine-ClUgv6jB.mjs} +3 -3
- package/dist/{layout-engine-Dr3cY5U4.mjs.map → layout-engine-ClUgv6jB.mjs.map} +1 -1
- package/dist/{multi-progress-CcdqJFlf.mjs → multi-progress-Bq9Oi_WI.mjs} +3 -3
- package/dist/{multi-progress-CcdqJFlf.mjs.map → multi-progress-Bq9Oi_WI.mjs.map} +1 -1
- package/dist/{multi-progress-DQ-uUzLf.d.mts → multi-progress-DAQC7eap.d.mts} +2 -2
- package/dist/{multi-progress-DQ-uUzLf.d.mts.map → multi-progress-DAQC7eap.d.mts.map} +1 -1
- package/dist/{node-CP5WChgr.mjs → node-BeWlnCPY.mjs} +4 -4
- package/dist/node-BeWlnCPY.mjs.map +1 -0
- package/dist/{progress-bar-IrUjkLfU.mjs → progress-bar-CXE5Qfkd.mjs} +4 -4
- package/dist/progress-bar-CXE5Qfkd.mjs.map +1 -0
- package/dist/reconciler-Cwgm8hRR.mjs +8459 -0
- package/dist/reconciler-Cwgm8hRR.mjs.map +1 -0
- package/dist/{render-string-BwLG7rIX.mjs → render-string-0mN37DLf.mjs} +1 -1
- package/dist/{render-string-DVfgc8xr.mjs → render-string-X-CxpTdZ.mjs} +935 -136
- package/dist/render-string-X-CxpTdZ.mjs.map +1 -0
- package/dist/runtime.d.mts +2 -2
- package/dist/runtime.mjs +3 -3
- package/dist/{spinner-BRkaJI0N.d.mts → spinner-CGo34vyR.d.mts} +2 -2
- package/dist/{spinner-BRkaJI0N.d.mts.map → spinner-CGo34vyR.d.mts.map} +1 -1
- package/dist/{spinner-BmldKx0M.mjs → spinner-CeOmcuw_.mjs} +3 -3
- package/dist/spinner-CeOmcuw_.mjs.map +1 -0
- package/dist/src-B5GjfG7g.mjs +4305 -0
- package/dist/src-B5GjfG7g.mjs.map +1 -0
- package/dist/{src-CJPXf3fC.mjs → src-Bd7ezSgG.mjs} +7560 -6474
- package/dist/src-Bd7ezSgG.mjs.map +1 -0
- package/dist/{src-D8kLrQBT.mjs → src-CChwjk0Z.mjs} +8 -86
- package/dist/src-CChwjk0Z.mjs.map +1 -0
- package/dist/{src-D_BS-as7.mjs → src-NCKb8kE5.mjs} +777 -776
- package/dist/src-NCKb8kE5.mjs.map +1 -0
- package/dist/theme.d.mts +2 -130
- package/dist/theme.mjs +3 -8
- package/dist/{types-B4A8Ebba.d.mts → types-BH_v3iMT.d.mts} +1 -1
- package/dist/{types-B4A8Ebba.d.mts.map → types-BH_v3iMT.d.mts.map} +1 -1
- package/dist/{types-e4dpfbSa.mjs → types-Bk2yw9Qj.mjs} +3 -3
- package/dist/types-Bk2yw9Qj.mjs.map +1 -0
- package/dist/ui/animation.d.mts +1 -1
- package/dist/ui/animation.mjs +1 -1
- package/dist/ui/ansi.d.mts +1 -1
- package/dist/ui/ansi.mjs +1 -1
- package/dist/ui/cli.d.mts +3 -3
- package/dist/ui/cli.mjs +5 -5
- package/dist/ui/display.d.mts +1 -1
- package/dist/ui/display.mjs.map +1 -1
- package/dist/ui/image.d.mts +1 -1
- package/dist/ui/image.mjs +1 -1
- package/dist/ui/input.d.mts +1 -1
- package/dist/ui/input.d.mts.map +1 -1
- package/dist/ui/input.mjs +2 -4
- package/dist/ui/input.mjs.map +1 -1
- package/dist/ui/progress.d.mts +3 -3
- package/dist/ui/progress.d.mts.map +1 -1
- package/dist/ui/progress.mjs +3 -3
- package/dist/ui/progress.mjs.map +1 -1
- package/dist/ui/react.d.mts +1 -1
- package/dist/ui/react.d.mts.map +1 -1
- package/dist/ui/react.mjs +2 -2
- package/dist/ui/react.mjs.map +1 -1
- package/dist/ui/utils.mjs +1 -1
- package/dist/ui/wrappers.d.mts +2 -2
- package/dist/ui/wrappers.mjs +1 -1
- package/dist/ui.d.mts +5 -5
- package/dist/ui.mjs +6 -6
- package/dist/{useLatest-6xqnGIU6.d.mts → useLatest-Bg2x4bfP.d.mts} +1 -1
- package/dist/{useLatest-6xqnGIU6.d.mts.map → useLatest-Bg2x4bfP.d.mts.map} +1 -1
- package/dist/{with-text-input-lUh9gYAG.d.mts → with-text-input-CRfoiFFG.d.mts} +3 -3
- package/dist/with-text-input-CRfoiFFG.d.mts.map +1 -0
- package/dist/{wrappers-JrEYTuKA.mjs → wrappers-UTADQkSY.mjs} +4 -4
- package/dist/wrappers-UTADQkSY.mjs.map +1 -0
- package/dist/{yoga-adapter-Bc8XT9cN.mjs → yoga-adapter-8oRGRw8V.mjs} +2 -2
- package/dist/{yoga-adapter-Bc8XT9cN.mjs.map → yoga-adapter-8oRGRw8V.mjs.map} +1 -1
- package/dist/yoga-adapter-D_CcxSt5.mjs +2 -0
- package/package.json +3 -3
- package/dist/UPNG-DvKjM6wE.mjs +0 -5076
- package/dist/UPNG-DvKjM6wE.mjs.map +0 -1
- package/dist/__vite-browser-external-2447137e-DPKHHqQK.mjs +0 -6
- package/dist/__vite-browser-external-2447137e-DPKHHqQK.mjs.map +0 -1
- package/dist/ansi-C6Qs1Wn2.mjs.map +0 -1
- package/dist/apng-CvSlLBtc.mjs +0 -3
- package/dist/apng-DFFVOItr.mjs +0 -70
- package/dist/apng-DFFVOItr.mjs.map +0 -1
- package/dist/assets/resvgjs.darwin-arm64-BtufyGW1.node +0 -0
- package/dist/backend-DU0Y938U.mjs +0 -13396
- package/dist/backend-DU0Y938U.mjs.map +0 -1
- package/dist/backends-BihMKFY_.mjs +0 -1181
- package/dist/backends-BihMKFY_.mjs.map +0 -1
- package/dist/backends-Dk_5G_gC.mjs +0 -3
- package/dist/cli-GwJ0S2In.mjs +0 -4
- package/dist/context-BjWgrikx.mjs.map +0 -1
- package/dist/derive-O_Kb1Bk_.d.mts +0 -28
- package/dist/derive-O_Kb1Bk_.d.mts.map +0 -1
- package/dist/devtools-CeO9X_uv.mjs.map +0 -1
- package/dist/devtools-nX4tj6OH.mjs +0 -2
- package/dist/flexily-zero-adapter-BOM0cl8R.mjs.map +0 -1
- package/dist/gif-B9Uq4qZA.mjs +0 -73
- package/dist/gif-B9Uq4qZA.mjs.map +0 -1
- package/dist/gif-BdrLRBmM.mjs +0 -3
- package/dist/gifenc-DfhOb4xr.mjs +0 -730
- package/dist/gifenc-DfhOb4xr.mjs.map +0 -1
- package/dist/image-B0zMbVUr.mjs.map +0 -1
- package/dist/index-Bh3U1K09.d.mts.map +0 -1
- package/dist/index-dehZ18K-.d.mts +0 -679
- package/dist/index-dehZ18K-.d.mts.map +0 -1
- package/dist/key-mapping-7k2ufK2b.mjs +0 -3
- package/dist/key-mapping-WLUmxjx1.mjs +0 -132
- package/dist/key-mapping-WLUmxjx1.mjs.map +0 -1
- package/dist/node-CP5WChgr.mjs.map +0 -1
- package/dist/progress-bar-IrUjkLfU.mjs.map +0 -1
- package/dist/reconciler-B8uxQxaU.mjs +0 -16482
- package/dist/reconciler-B8uxQxaU.mjs.map +0 -1
- package/dist/render-string-DVfgc8xr.mjs.map +0 -1
- package/dist/resvg-js-Cwipz-_J.mjs +0 -203
- package/dist/resvg-js-Cwipz-_J.mjs.map +0 -1
- package/dist/spinner-BmldKx0M.mjs.map +0 -1
- package/dist/src-C0sOQW-t.mjs +0 -3866
- package/dist/src-C0sOQW-t.mjs.map +0 -1
- package/dist/src-CJPXf3fC.mjs.map +0 -1
- package/dist/src-D8kLrQBT.mjs.map +0 -1
- package/dist/src-D_BS-as7.mjs.map +0 -1
- package/dist/theme.d.mts.map +0 -1
- package/dist/theme.mjs.map +0 -1
- package/dist/types-e4dpfbSa.mjs.map +0 -1
- package/dist/with-text-input-lUh9gYAG.d.mts.map +0 -1
- package/dist/wrapper-CE6GQ27z.mjs +0 -3527
- package/dist/wrapper-CE6GQ27z.mjs.map +0 -1
- package/dist/wrappers-JrEYTuKA.mjs.map +0 -1
- package/dist/yoga-adapter-B8LZpQcE.mjs +0 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flexily-zero-adapter-BlQa46nr.mjs","names":["segmenter","FlexilyNode"],"sources":["../node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/utils.ts","../node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/logger.ts","../node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/trace.ts","../node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/layout-helpers.ts","../node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/layout-traversal.ts","../node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/layout-stats.ts","../node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/layout-measure.ts","../node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/layout-flex-lines.ts","../node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/layout-zero.ts","../node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/types.ts","../node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/node-zero.ts","../node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/monospace-measurer.ts","../node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/test-measurer.ts","../packages/ag-term/src/adapters/flexily-zero-adapter.ts"],"sourcesContent":["/**\n * Flexily Utility Functions\n *\n * Helper functions for edge value manipulation and value resolution.\n */\n\nimport * as C from \"./constants.js\"\nimport type { Value } from \"./types.js\"\n\n// ============================================================================\n// Shared Traversal Stack\n// ============================================================================\n// Pre-allocated stack array for iterative tree traversal. Shared across all\n// layout functions to avoid multiple allocations. Using a single stack is safe\n// because layout operations are synchronous (no concurrent traversals).\n\n/**\n * Shared traversal stack for iterative tree operations.\n * Avoids recursion (prevents stack overflow on deep trees) and avoids\n * allocation during layout passes.\n */\nexport const traversalStack: unknown[] = []\n\n/**\n * Set a value on an edge array (supports all edge types including logical START/END).\n */\nexport function setEdgeValue(\n arr: [Value, Value, Value, Value, Value, Value],\n edge: number,\n value: number,\n unit: number,\n): void {\n const v = { value, unit }\n switch (edge) {\n case C.EDGE_LEFT:\n arr[0] = v\n break\n case C.EDGE_TOP:\n arr[1] = v\n break\n case C.EDGE_RIGHT:\n arr[2] = v\n break\n case C.EDGE_BOTTOM:\n arr[3] = v\n break\n case C.EDGE_HORIZONTAL:\n arr[0] = v\n arr[2] = v\n break\n case C.EDGE_VERTICAL:\n arr[1] = v\n arr[3] = v\n break\n case C.EDGE_ALL:\n arr[0] = v\n arr[1] = v\n arr[2] = v\n arr[3] = v\n break\n case C.EDGE_START:\n // Store in logical START slot (resolved to physical at layout time)\n arr[4] = v\n break\n case C.EDGE_END:\n // Store in logical END slot (resolved to physical at layout time)\n arr[5] = v\n break\n }\n}\n\n/**\n * Set a border value on an edge array.\n */\nexport function setEdgeBorder(\n arr: [number, number, number, number, number, number],\n edge: number,\n value: number,\n): void {\n switch (edge) {\n case C.EDGE_LEFT:\n arr[0] = value\n break\n case C.EDGE_TOP:\n arr[1] = value\n break\n case C.EDGE_RIGHT:\n arr[2] = value\n break\n case C.EDGE_BOTTOM:\n arr[3] = value\n break\n case C.EDGE_HORIZONTAL:\n arr[0] = value\n arr[2] = value\n break\n case C.EDGE_VERTICAL:\n arr[1] = value\n arr[3] = value\n break\n case C.EDGE_ALL:\n arr[0] = value\n arr[1] = value\n arr[2] = value\n arr[3] = value\n break\n case C.EDGE_START:\n // Store in logical START slot (resolved to physical at layout time)\n arr[4] = value\n break\n case C.EDGE_END:\n // Store in logical END slot (resolved to physical at layout time)\n arr[5] = value\n break\n }\n}\n\n/**\n * Get a value from an edge array.\n */\nexport function getEdgeValue(arr: [Value, Value, Value, Value, Value, Value], edge: number): Value {\n switch (edge) {\n case C.EDGE_LEFT:\n return arr[0]\n case C.EDGE_TOP:\n return arr[1]\n case C.EDGE_RIGHT:\n return arr[2]\n case C.EDGE_BOTTOM:\n return arr[3]\n case C.EDGE_START:\n return arr[4]\n case C.EDGE_END:\n return arr[5]\n default:\n return arr[0] // Default to left\n }\n}\n\n/**\n * Get a border value from an edge array.\n */\nexport function getEdgeBorderValue(arr: [number, number, number, number, number, number], edge: number): number {\n switch (edge) {\n case C.EDGE_LEFT:\n return arr[0]\n case C.EDGE_TOP:\n return arr[1]\n case C.EDGE_RIGHT:\n return arr[2]\n case C.EDGE_BOTTOM:\n return arr[3]\n case C.EDGE_START:\n return arr[4]\n case C.EDGE_END:\n return arr[5]\n default:\n return arr[0] // Default to left\n }\n}\n\n/**\n * Resolve a value (point or percent) to an absolute number.\n */\nexport function resolveValue(value: Value, availableSize: number): number {\n switch (value.unit) {\n case C.UNIT_POINT:\n return value.value\n case C.UNIT_PERCENT:\n // Percentage against NaN (auto-sized parent) resolves to 0\n if (Number.isNaN(availableSize)) {\n return 0\n }\n return availableSize * (value.value / 100)\n default:\n return 0\n }\n}\n\n/**\n * Apply min/max constraints to a size.\n *\n * CSS behavior:\n * - min: Floor constraint. Does NOT affect children's layout — the container expands\n * after shrink-wrap. When size is NaN (auto-sized), min is NOT applied here;\n * the post-shrink-wrap applyMinMax call (Phase 9) handles it.\n * - max: Ceiling constraint. DOES affect children's layout — content wraps/clips\n * within the max. When size is NaN (auto-sized), max constrains the container\n * so children are laid out within the max bound.\n *\n * Percent constraints that can't resolve (available is NaN) are skipped entirely,\n * since resolveValue returns 0 for percent-against-NaN, which would incorrectly\n * clamp sizes to 0.\n */\nexport function applyMinMax(size: number, min: Value, max: Value, available: number): number {\n let result = size\n\n // Apply max first, then min. CSS spec: when min > max, min wins.\n // By applying max before min, Math.max(result, minValue) ensures min dominates.\n\n if (max.unit !== C.UNIT_UNDEFINED) {\n // Skip percent max when available is NaN — can't resolve meaningfully\n if (max.unit === C.UNIT_PERCENT && Number.isNaN(available)) {\n // Skip: percent against NaN resolves to 0, which would be wrong\n } else {\n const maxValue = resolveValue(max, available)\n if (!Number.isNaN(maxValue)) {\n // Apply max as ceiling even when size is NaN (auto-sized).\n // This constrains children's layout to the max bound.\n // Phase 9 shrink-wrap may reduce it further; the post-shrink-wrap\n // applyMinMax call ensures max is still respected.\n if (Number.isNaN(result)) {\n // For auto-sized nodes, only apply finite max constraints.\n // Infinity means \"no real constraint\" (e.g., silvery sets\n // maxWidth=Infinity as default) and should not replace NaN.\n if (maxValue !== Infinity) {\n result = maxValue\n }\n } else {\n result = Math.min(result, maxValue)\n }\n }\n }\n }\n\n if (min.unit !== C.UNIT_UNDEFINED) {\n // Skip percent min when available is NaN — can't resolve meaningfully\n if (min.unit === C.UNIT_PERCENT && Number.isNaN(available)) {\n // Skip: percent against NaN resolves to 0, which would be wrong\n } else {\n const minValue = resolveValue(min, available)\n if (!Number.isNaN(minValue)) {\n // Only apply min to definite sizes. When size is NaN (auto-sized),\n // skip — the post-shrink-wrap applyMinMax call will floor it.\n if (!Number.isNaN(result)) {\n result = Math.max(result, minValue)\n }\n }\n }\n }\n\n return result\n}\n","/**\n * Logger with auto-detection\n *\n * Uses @beorn/logger if available (when used in km), falls back to debug library.\n * Supports the conditional `?.` pattern for zero-cost when disabled.\n */\n\n// Debug library style: (msg, ...args) - printf-style formatting\ntype DebugFn = (msg: string, ...args: unknown[]) => void\n\ninterface ConditionalLogger {\n debug?: DebugFn\n}\n\nlet _logger: ConditionalLogger | null = null\n\nasync function createFallbackLogger(namespace: string): Promise<ConditionalLogger> {\n // Dynamic import to avoid bundling debug if not needed\n try {\n const { default: createDebug } = (await import(\"debug\")) as {\n default: (ns: string) => DebugFn & { enabled: boolean }\n }\n const debug = createDebug(namespace)\n return { debug: debug.enabled ? debug : undefined }\n } catch {\n // debug not installed either\n return { debug: undefined }\n }\n}\n\nasync function detectLogger(namespace: string): Promise<ConditionalLogger> {\n try {\n const { createLogger } = await import(\"loggily\")\n const logger = createLogger(namespace)\n // Wrap @beorn/logger to accept printf-style args\n if (logger.debug) {\n const originalDebug = logger.debug\n return {\n debug: (msg: string, ...args: unknown[]) => {\n // Format printf-style placeholders\n let i = 0\n const formatted = msg.replace(/%[sdOo]/g, () => {\n const arg = args[i++]\n if (arg === undefined) return \"\"\n if (arg === null) return \"null\"\n if (typeof arg === \"object\") return JSON.stringify(arg)\n return String(arg)\n })\n originalDebug(formatted)\n },\n }\n }\n return { debug: undefined }\n } catch {\n return createFallbackLogger(namespace)\n }\n}\n\n// Eagerly initialize (top-level await)\n// This runs once at module load time\n_logger = await detectLogger(\"flexily:layout\")\n\n/** Logger instance - use with optional chaining: `log.debug?.('message')` */\nexport const log: ConditionalLogger = {\n get debug() {\n return _logger?.debug\n },\n}\n","/**\n * Layout Trace — instrumented debug mode for fingerprint/cache tracing.\n *\n * Records every fingerprint check (hit/miss), cache lookup (hit/miss),\n * measureNode save/restore, and parent size override during a layout pass.\n * Two traces from consecutive passes can be diffed to find where they diverge.\n *\n * Zero-cost when disabled: the module-level `trace` getter returns undefined,\n * and all callsites use optional chaining (`trace?.event()`).\n *\n * @example\n * ```typescript\n * import { enableTrace, disableTrace, diffTraces } from 'flexily/trace';\n *\n * const t1 = enableTrace();\n * root.calculateLayout(80, 24, DIRECTION_LTR);\n * disableTrace();\n *\n * // Mutate tree...\n * const t2 = enableTrace();\n * root.calculateLayout(80, 24, DIRECTION_LTR);\n * disableTrace();\n *\n * const diffs = diffTraces(t1, t2);\n * ```\n */\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type TraceEventType =\n | \"fingerprint_hit\"\n | \"fingerprint_miss\"\n | \"cache_hit\"\n | \"cache_miss\"\n | \"measure_cache_hit\"\n | \"measure_cache_miss\"\n | \"measure_save_restore\"\n | \"parent_override\"\n | \"layout_enter\"\n | \"layout_exit\"\n\nexport interface TraceEvent {\n type: TraceEventType\n /** Node index in tree traversal order (stable across same tree) */\n nodeIndex: number\n /** Available width constraint */\n availW: number\n /** Available height constraint */\n availH: number\n /** Extra data depending on event type */\n detail?: Record<string, number | string | boolean>\n}\n\nexport interface TraceDiff {\n index: number\n event1: TraceEvent | undefined\n event2: TraceEvent | undefined\n reason: string\n}\n\n// =============================================================================\n// Trace Recorder\n// =============================================================================\n\nexport class LayoutTrace {\n readonly events: TraceEvent[] = []\n private _nodeCounter = 0\n\n /** Reset node counter at start of a new layout pass */\n resetCounter(): void {\n this._nodeCounter = 0\n }\n\n /** Get next node index (call once per layoutNode entry) */\n nextNode(): number {\n return this._nodeCounter++\n }\n\n fingerprintHit(nodeIndex: number, availW: number, availH: number): void {\n this.events.push({ type: \"fingerprint_hit\", nodeIndex, availW, availH })\n }\n\n fingerprintMiss(\n nodeIndex: number,\n availW: number,\n availH: number,\n detail?: Record<string, number | string | boolean>,\n ): void {\n this.events.push({ type: \"fingerprint_miss\", nodeIndex, availW, availH, detail })\n }\n\n cacheHit(nodeIndex: number, availW: number, availH: number, width: number, height: number): void {\n this.events.push({\n type: \"cache_hit\",\n nodeIndex,\n availW,\n availH,\n detail: { width, height },\n })\n }\n\n cacheMiss(nodeIndex: number, availW: number, availH: number): void {\n this.events.push({ type: \"cache_miss\", nodeIndex, availW, availH })\n }\n\n measureCacheHit(nodeIndex: number, availW: number, availH: number, width: number, height: number): void {\n this.events.push({\n type: \"measure_cache_hit\",\n nodeIndex,\n availW,\n availH,\n detail: { width, height },\n })\n }\n\n measureCacheMiss(nodeIndex: number, availW: number, availH: number): void {\n this.events.push({ type: \"measure_cache_miss\", nodeIndex, availW, availH })\n }\n\n measureSaveRestore(nodeIndex: number, savedW: number, savedH: number, measuredW: number, measuredH: number): void {\n this.events.push({\n type: \"measure_save_restore\",\n nodeIndex,\n availW: 0,\n availH: 0,\n detail: { savedW, savedH, measuredW, measuredH },\n })\n }\n\n parentOverride(nodeIndex: number, axis: \"main\" | \"cross\", original: number, overridden: number): void {\n this.events.push({\n type: \"parent_override\",\n nodeIndex,\n availW: 0,\n availH: 0,\n detail: { axis, original, overridden },\n })\n }\n\n layoutEnter(nodeIndex: number, availW: number, availH: number, isDirty: boolean, childCount: number): void {\n this.events.push({\n type: \"layout_enter\",\n nodeIndex,\n availW,\n availH,\n detail: { isDirty, childCount },\n })\n }\n\n layoutExit(nodeIndex: number, width: number, height: number): void {\n this.events.push({\n type: \"layout_exit\",\n nodeIndex,\n availW: 0,\n availH: 0,\n detail: { width, height },\n })\n }\n}\n\n// =============================================================================\n// Module-level state (zero-cost when null)\n// =============================================================================\n\nlet _trace: LayoutTrace | null = null\n\n/** Enable tracing. Returns the trace recorder for later inspection. */\nexport function enableTrace(): LayoutTrace {\n _trace = new LayoutTrace()\n return _trace\n}\n\n/** Disable tracing. Returns the trace that was recorded. */\nexport function disableTrace(): LayoutTrace | null {\n const t = _trace\n _trace = null\n return t\n}\n\n/** Get the current trace recorder (null when tracing is disabled). */\nexport function getTrace(): LayoutTrace | null {\n return _trace\n}\n\n// =============================================================================\n// Diff Utility\n// =============================================================================\n\n/**\n * Compare two traces event-by-event.\n * Returns divergence points — where the two passes made different decisions.\n */\nexport function diffTraces(t1: LayoutTrace, t2: LayoutTrace): TraceDiff[] {\n const diffs: TraceDiff[] = []\n const maxLen = Math.max(t1.events.length, t2.events.length)\n\n for (let i = 0; i < maxLen; i++) {\n const e1 = t1.events[i]\n const e2 = t2.events[i]\n\n if (!e1 || !e2) {\n diffs.push({\n index: i,\n event1: e1,\n event2: e2,\n reason: !e1 ? \"extra event in trace 2\" : \"extra event in trace 1\",\n })\n continue\n }\n\n if (e1.type !== e2.type) {\n diffs.push({\n index: i,\n event1: e1,\n event2: e2,\n reason: `type differs: ${e1.type} vs ${e2.type}`,\n })\n } else if (e1.nodeIndex !== e2.nodeIndex) {\n diffs.push({\n index: i,\n event1: e1,\n event2: e2,\n reason: `nodeIndex differs: ${e1.nodeIndex} vs ${e2.nodeIndex}`,\n })\n } else if (!Object.is(e1.availW, e2.availW) || !Object.is(e1.availH, e2.availH)) {\n diffs.push({\n index: i,\n event1: e1,\n event2: e2,\n reason: `constraints differ: (${e1.availW},${e1.availH}) vs (${e2.availW},${e2.availH})`,\n })\n } else if (e1.detail && e2.detail) {\n // Compare detail fields\n const keys = new Set([...Object.keys(e1.detail), ...Object.keys(e2.detail)])\n for (const key of keys) {\n if (!Object.is(e1.detail[key], e2.detail[key])) {\n diffs.push({\n index: i,\n event1: e1,\n event2: e2,\n reason: `detail.${key} differs: ${e1.detail[key]} vs ${e2.detail[key]}`,\n })\n break\n }\n }\n }\n }\n\n return diffs\n}\n","/**\n * Layout Helper Functions\n *\n * Edge resolution helpers for margins, padding, borders.\n * These are pure functions with no state — safe to extract.\n */\n\nimport * as C from \"./constants.js\"\nimport type { Value } from \"./types.js\"\nimport { resolveValue } from \"./utils.js\"\n\n// Re-export edge constants (canonical definitions in constants.ts)\nexport { EDGE_LEFT, EDGE_TOP, EDGE_RIGHT, EDGE_BOTTOM } from \"./constants.js\"\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Check if flex direction is row-oriented (horizontal main axis).\n */\nexport function isRowDirection(flexDirection: number): boolean {\n return flexDirection === C.FLEX_DIRECTION_ROW || flexDirection === C.FLEX_DIRECTION_ROW_REVERSE\n}\n\n/**\n * Check if flex direction is reversed.\n */\nexport function isReverseDirection(flexDirection: number): boolean {\n return flexDirection === C.FLEX_DIRECTION_ROW_REVERSE || flexDirection === C.FLEX_DIRECTION_COLUMN_REVERSE\n}\n\n/**\n * Get the logical edge value (START/END) for a given physical index.\n * Returns undefined if no logical value applies to this physical edge.\n *\n * EDGE_START/EDGE_END always resolve along the inline (horizontal) axis,\n * regardless of flex direction. Direction (LTR/RTL) determines the mapping:\n * - LTR: START->left, END->right\n * - RTL: START->right, END->left\n */\nfunction getLogicalEdgeValue(\n arr: [Value, Value, Value, Value, Value, Value],\n physicalIndex: number,\n _flexDirection: number,\n direction: number = C.DIRECTION_LTR,\n): Value | undefined {\n const isRTL = direction === C.DIRECTION_RTL\n\n // START/END always map to left/right (inline direction)\n if (physicalIndex === 0) {\n return isRTL ? arr[5] : arr[4] // Left: START (LTR) or END (RTL)\n } else if (physicalIndex === 2) {\n return isRTL ? arr[4] : arr[5] // Right: END (LTR) or START (RTL)\n }\n return undefined\n}\n\n/**\n * Resolve logical (START/END) margins/padding to physical values.\n * EDGE_START/EDGE_END always resolve along the inline (horizontal) axis:\n * - LTR: START->left, END->right\n * - RTL: START->right, END->left\n *\n * Physical edges (LEFT/RIGHT/TOP/BOTTOM) are used directly.\n * When both physical and logical are set, logical takes precedence.\n */\nexport function resolveEdgeValue(\n arr: [Value, Value, Value, Value, Value, Value],\n physicalIndex: number, // 0=left, 1=top, 2=right, 3=bottom\n flexDirection: number,\n availableSize: number,\n direction: number = C.DIRECTION_LTR,\n): number {\n const logicalValue = getLogicalEdgeValue(arr, physicalIndex, flexDirection, direction)\n\n // Logical takes precedence if defined\n if (logicalValue && logicalValue.unit !== C.UNIT_UNDEFINED) {\n return resolveValue(logicalValue, availableSize)\n }\n\n // Fall back to physical\n return resolveValue(arr[physicalIndex]!, availableSize)\n}\n\n/**\n * Check if a logical edge margin is set to auto.\n */\nexport function isEdgeAuto(\n arr: [Value, Value, Value, Value, Value, Value],\n physicalIndex: number,\n flexDirection: number,\n direction: number = C.DIRECTION_LTR,\n): boolean {\n const logicalValue = getLogicalEdgeValue(arr, physicalIndex, flexDirection, direction)\n\n // Check logical first\n if (logicalValue && logicalValue.unit !== C.UNIT_UNDEFINED) {\n return logicalValue.unit === C.UNIT_AUTO\n }\n\n // Fall back to physical\n return arr[physicalIndex]!.unit === C.UNIT_AUTO\n}\n\n/**\n * Resolve logical (START/END) border widths to physical values.\n * Border values are plain numbers (always points), so resolution is simpler\n * than for margin/padding. Uses NaN as the \"not set\" sentinel for logical slots.\n * When both physical and logical are set, logical takes precedence.\n *\n * EDGE_START/EDGE_END always resolve along the inline (horizontal) axis,\n * regardless of flex direction. Direction (LTR/RTL) determines the mapping:\n * - LTR: START->left, END->right\n * - RTL: START->right, END->left\n */\n/**\n * Resolve logical (START/END) position edges to physical values.\n * Returns the resolved Value for a physical position index, considering\n * logical EDGE_START/EDGE_END. Logical takes precedence over physical.\n *\n * EDGE_START/EDGE_END always resolve along the inline (horizontal) axis:\n * - LTR: START->left, END->right\n * - RTL: START->right, END->left\n */\nexport function resolvePositionEdge(\n arr: [Value, Value, Value, Value, Value, Value],\n physicalIndex: number, // 0=left, 1=top, 2=right, 3=bottom\n direction: number = C.DIRECTION_LTR,\n): Value {\n const logicalValue = getLogicalEdgeValue(arr, physicalIndex, 0 /* unused */, direction)\n\n // Logical takes precedence if defined\n if (logicalValue && logicalValue.unit !== C.UNIT_UNDEFINED) {\n return logicalValue\n }\n\n // Fall back to physical\n return arr[physicalIndex]!\n}\n\nexport function resolveEdgeBorderValue(\n arr: [number, number, number, number, number, number],\n physicalIndex: number, // 0=left, 1=top, 2=right, 3=bottom\n _flexDirection: number,\n direction: number = C.DIRECTION_LTR,\n): number {\n const isRTL = direction === C.DIRECTION_RTL\n\n // START/END always map to left/right (inline direction)\n let logicalSlot: number | undefined\n if (physicalIndex === 0) logicalSlot = isRTL ? 5 : 4\n else if (physicalIndex === 2) logicalSlot = isRTL ? 4 : 5\n\n // Logical takes precedence if set (NaN = not set)\n if (logicalSlot !== undefined && !Number.isNaN(arr[logicalSlot])) {\n return arr[logicalSlot]!\n }\n return arr[physicalIndex]!\n}\n","/**\n * Layout Tree Traversal Utilities\n *\n * Iterative tree traversal functions that avoid recursion\n * (prevents stack overflow on deep trees).\n * Uses shared traversalStack from utils.ts for zero-allocation.\n */\n\nimport type { Node } from \"./node-zero.js\"\nimport { traversalStack } from \"./utils.js\"\n\n/**\n * Mark subtree as having new layout and clear dirty flags (iterative to avoid stack overflow).\n * This is called after layout completes to reset dirty tracking for all nodes.\n */\nexport function markSubtreeLayoutSeen(node: Node): void {\n traversalStack.length = 0\n traversalStack.push(node)\n while (traversalStack.length > 0) {\n const current = traversalStack.pop() as Node\n // Clear dirty flag - layout is now complete\n ;(current as Node)[\"_isDirty\"] = false\n ;(current as Node)[\"_hasNewLayout\"] = true\n for (const child of current.children) {\n traversalStack.push(child)\n }\n }\n}\n\n/**\n * Count total nodes in tree (iterative to avoid stack overflow).\n */\nexport function countNodes(node: Node): number {\n let count = 0\n traversalStack.length = 0\n traversalStack.push(node)\n while (traversalStack.length > 0) {\n const current = traversalStack.pop() as Node\n count++\n for (const child of current.children) {\n traversalStack.push(child)\n }\n }\n return count\n}\n\n/**\n * Propagate position delta to all descendants (iterative to avoid stack overflow).\n * Used when parent position changes but layout is cached.\n *\n * Only updates the constraint fingerprint's lastOffset values, NOT layout.top/left.\n * layout.top/left store RELATIVE positions (relative to parent's border box),\n * so they don't change when an ancestor moves — only the absolute offset\n * (tracked via lastOffsetX/Y) changes.\n */\nexport function propagatePositionDelta(node: Node, deltaX: number, deltaY: number): void {\n traversalStack.length = 0\n // Start with all children of the node\n for (const child of node.children) {\n traversalStack.push(child)\n }\n while (traversalStack.length > 0) {\n const current = traversalStack.pop() as Node\n current.flex.lastOffsetX += deltaX\n current.flex.lastOffsetY += deltaY\n for (const child of current.children) {\n traversalStack.push(child)\n }\n }\n}\n","/**\n * Layout Statistics Counters\n *\n * Mutable counters for debugging and benchmarking.\n * Separated to avoid circular dependencies between layout modules.\n */\n\n// Layout statistics for debugging\nexport let layoutNodeCalls = 0\nexport let measureNodeCalls = 0\nexport let layoutSizingCalls = 0 // Calls for intrinsic sizing (offset=0,0)\nexport let layoutPositioningCalls = 0 // Calls for final positioning\nexport let layoutCacheHits = 0\n\nexport function resetLayoutStats(): void {\n layoutNodeCalls = 0\n measureNodeCalls = 0\n layoutSizingCalls = 0\n layoutPositioningCalls = 0\n layoutCacheHits = 0\n}\n\nexport function incLayoutNodeCalls(): void {\n layoutNodeCalls++\n}\n\nexport function incMeasureNodeCalls(): void {\n measureNodeCalls++\n}\n\nexport function incLayoutSizingCalls(): void {\n layoutSizingCalls++\n}\n\nexport function incLayoutPositioningCalls(): void {\n layoutPositioningCalls++\n}\n\nexport function incLayoutCacheHits(): void {\n layoutCacheHits++\n}\n","/**\n * Node Measurement (Intrinsic Sizing)\n *\n * measureNode() computes a node's width and height without calculating positions.\n * It's a lightweight alternative to layoutNode() used during Phase 5 for\n * intrinsic sizing of auto-sized container children.\n *\n * IMPORTANT: measureNode() overwrites layout.width/layout.height as a side effect.\n * Callers MUST save/restore these fields around calls to avoid corrupting\n * the fingerprint cache (see \"Bug 1: measureNode corruption\" in CLAUDE.md).\n */\n\nimport * as C from \"./constants.js\"\nimport type { Node } from \"./node-zero.js\"\nimport { resolveValue, applyMinMax } from \"./utils.js\"\nimport { resolveEdgeValue, resolveEdgeBorderValue, isRowDirection } from \"./layout-helpers.js\"\nimport { incMeasureNodeCalls, incLayoutCacheHits } from \"./layout-stats.js\"\n\n/**\n * Measure a node to get its intrinsic size without computing positions.\n * This is a lightweight alternative to layoutNode for sizing-only passes.\n *\n * Sets layout.width and layout.height but NOT layout.left/top.\n *\n * @param node - The node to measure\n * @param availableWidth - Available width (NaN for unconstrained)\n * @param availableHeight - Available height (NaN for unconstrained)\n * @param direction - Layout direction (LTR or RTL)\n */\nexport function measureNode(\n node: Node,\n availableWidth: number,\n availableHeight: number,\n direction: number = C.DIRECTION_LTR,\n): void {\n incMeasureNodeCalls()\n const style = node.style\n const layout = node.layout\n\n // Handle display: none\n if (style.display === C.DISPLAY_NONE) {\n layout.width = 0\n layout.height = 0\n return\n }\n\n // Calculate spacing\n const marginLeft = resolveEdgeValue(style.margin, 0, style.flexDirection, availableWidth, direction)\n const marginTop = resolveEdgeValue(style.margin, 1, style.flexDirection, availableWidth, direction)\n const marginRight = resolveEdgeValue(style.margin, 2, style.flexDirection, availableWidth, direction)\n const marginBottom = resolveEdgeValue(style.margin, 3, style.flexDirection, availableWidth, direction)\n\n const paddingLeft = resolveEdgeValue(style.padding, 0, style.flexDirection, availableWidth, direction)\n const paddingTop = resolveEdgeValue(style.padding, 1, style.flexDirection, availableWidth, direction)\n const paddingRight = resolveEdgeValue(style.padding, 2, style.flexDirection, availableWidth, direction)\n const paddingBottom = resolveEdgeValue(style.padding, 3, style.flexDirection, availableWidth, direction)\n\n const borderLeft = resolveEdgeBorderValue(style.border, 0, style.flexDirection, direction)\n const borderTop = resolveEdgeBorderValue(style.border, 1, style.flexDirection, direction)\n const borderRight = resolveEdgeBorderValue(style.border, 2, style.flexDirection, direction)\n const borderBottom = resolveEdgeBorderValue(style.border, 3, style.flexDirection, direction)\n\n // Calculate node dimensions\n let nodeWidth: number\n if (style.width.unit === C.UNIT_POINT) {\n nodeWidth = style.width.value\n } else if (style.width.unit === C.UNIT_PERCENT) {\n nodeWidth = resolveValue(style.width, availableWidth)\n } else if (Number.isNaN(availableWidth)) {\n nodeWidth = NaN\n } else {\n nodeWidth = availableWidth - marginLeft - marginRight\n }\n nodeWidth = applyMinMax(nodeWidth, style.minWidth, style.maxWidth, availableWidth)\n\n let nodeHeight: number\n if (style.height.unit === C.UNIT_POINT) {\n nodeHeight = style.height.value\n } else if (style.height.unit === C.UNIT_PERCENT) {\n nodeHeight = resolveValue(style.height, availableHeight)\n } else if (Number.isNaN(availableHeight)) {\n nodeHeight = NaN\n } else {\n nodeHeight = availableHeight - marginTop - marginBottom\n }\n\n // Apply aspect ratio (CSS aspect-ratio spec)\n // Re-apply min/max on the derived dimension to respect CSS box model.\n const aspectRatio = style.aspectRatio\n if (!Number.isNaN(aspectRatio) && aspectRatio > 0) {\n const widthIsAuto = Number.isNaN(nodeWidth) || style.width.unit === C.UNIT_AUTO\n const heightIsAuto = Number.isNaN(nodeHeight) || style.height.unit === C.UNIT_AUTO\n if (widthIsAuto && !heightIsAuto && !Number.isNaN(nodeHeight)) {\n nodeWidth = nodeHeight * aspectRatio\n nodeWidth = applyMinMax(nodeWidth, style.minWidth, style.maxWidth, availableWidth)\n } else if (heightIsAuto && !widthIsAuto && !Number.isNaN(nodeWidth)) {\n nodeHeight = nodeWidth / aspectRatio\n }\n }\n\n nodeHeight = applyMinMax(nodeHeight, style.minHeight, style.maxHeight, availableHeight)\n\n // Content area\n const innerLeft = borderLeft + paddingLeft\n const innerTop = borderTop + paddingTop\n const innerRight = borderRight + paddingRight\n const innerBottom = borderBottom + paddingBottom\n\n const minInnerWidth = innerLeft + innerRight\n const minInnerHeight = innerTop + innerBottom\n if (!Number.isNaN(nodeWidth) && nodeWidth < minInnerWidth) {\n nodeWidth = minInnerWidth\n }\n if (!Number.isNaN(nodeHeight) && nodeHeight < minInnerHeight) {\n nodeHeight = minInnerHeight\n }\n\n const contentWidth = Number.isNaN(nodeWidth) ? NaN : Math.max(0, nodeWidth - innerLeft - innerRight)\n const contentHeight = Number.isNaN(nodeHeight) ? NaN : Math.max(0, nodeHeight - innerTop - innerBottom)\n\n // Handle measure function (text nodes)\n if (node.hasMeasureFunc() && node.children.length === 0) {\n const widthIsAuto =\n style.width.unit === C.UNIT_AUTO || style.width.unit === C.UNIT_UNDEFINED || Number.isNaN(nodeWidth)\n const heightIsAuto =\n style.height.unit === C.UNIT_AUTO || style.height.unit === C.UNIT_UNDEFINED || Number.isNaN(nodeHeight)\n const widthMode = widthIsAuto ? C.MEASURE_MODE_AT_MOST : C.MEASURE_MODE_EXACTLY\n const heightMode = heightIsAuto ? C.MEASURE_MODE_UNDEFINED : C.MEASURE_MODE_EXACTLY\n const measureWidth = Number.isNaN(contentWidth) ? Infinity : contentWidth\n const measureHeight = Number.isNaN(contentHeight) ? Infinity : contentHeight\n\n const measured = node.cachedMeasure(measureWidth, widthMode, measureHeight, heightMode)!\n\n if (widthIsAuto) {\n nodeWidth = measured.width + innerLeft + innerRight\n }\n if (heightIsAuto) {\n nodeHeight = measured.height + innerTop + innerBottom\n }\n\n layout.width = Math.round(nodeWidth)\n layout.height = Math.round(nodeHeight)\n return\n }\n\n // Handle leaf nodes without measureFunc\n if (node.children.length === 0) {\n if (Number.isNaN(nodeWidth)) {\n nodeWidth = innerLeft + innerRight\n }\n if (Number.isNaN(nodeHeight)) {\n nodeHeight = innerTop + innerBottom\n }\n layout.width = Math.round(nodeWidth)\n layout.height = Math.round(nodeHeight)\n return\n }\n\n // For container nodes, we need to measure children to compute intrinsic size\n // Zero-alloc: iterate children directly without collecting into temporary array\n\n // First pass: count relative children (skip absolute/hidden)\n let relativeChildCount = 0\n for (const c of node.children) {\n if (c.style.display === C.DISPLAY_NONE) continue\n if (c.style.positionType !== C.POSITION_TYPE_ABSOLUTE) {\n relativeChildCount++\n }\n }\n\n if (relativeChildCount === 0) {\n // No relative children - size is just padding+border\n if (Number.isNaN(nodeWidth)) nodeWidth = minInnerWidth\n if (Number.isNaN(nodeHeight)) nodeHeight = minInnerHeight\n layout.width = Math.round(nodeWidth)\n layout.height = Math.round(nodeHeight)\n return\n }\n\n const isRow = isRowDirection(style.flexDirection)\n const mainAxisSize = isRow ? contentWidth : contentHeight\n const crossAxisSize = isRow ? contentHeight : contentWidth\n const mainGap = isRow ? style.gap[0] : style.gap[1]\n\n // Second pass: measure each child and sum for intrinsic size\n let totalMainSize = 0\n let maxCrossSize = 0\n let itemCount = 0\n\n for (const child of node.children) {\n // Skip absolute/hidden children (same filter as count pass)\n if (child.style.display === C.DISPLAY_NONE) continue\n if (child.style.positionType === C.POSITION_TYPE_ABSOLUTE) continue\n\n const childStyle = child.style\n\n // Get child margins\n const childMarginMain = isRow\n ? resolveEdgeValue(childStyle.margin, 0, style.flexDirection, contentWidth, direction) +\n resolveEdgeValue(childStyle.margin, 2, style.flexDirection, contentWidth, direction)\n : resolveEdgeValue(childStyle.margin, 1, style.flexDirection, contentWidth, direction) +\n resolveEdgeValue(childStyle.margin, 3, style.flexDirection, contentWidth, direction)\n const childMarginCross = isRow\n ? resolveEdgeValue(childStyle.margin, 1, style.flexDirection, contentWidth, direction) +\n resolveEdgeValue(childStyle.margin, 3, style.flexDirection, contentWidth, direction)\n : resolveEdgeValue(childStyle.margin, 0, style.flexDirection, contentWidth, direction) +\n resolveEdgeValue(childStyle.margin, 2, style.flexDirection, contentWidth, direction)\n\n // Measure child with appropriate constraints\n // For shrink-wrap: pass NaN for main axis, cross axis constraint for cross\n const childAvailW = isRow ? NaN : crossAxisSize\n const childAvailH = isRow ? crossAxisSize : NaN\n\n // Check cache first\n let measuredW = 0\n let measuredH = 0\n const cached = child.getCachedLayout(childAvailW, childAvailH)\n if (cached) {\n incLayoutCacheHits()\n } else {\n // Save/restore layout around measureNode — it overwrites node.layout\n const savedW = child.layout.width\n const savedH = child.layout.height\n measureNode(child, childAvailW, childAvailH, direction)\n measuredW = child.layout.width\n measuredH = child.layout.height\n child.layout.width = savedW\n child.layout.height = savedH\n child.setCachedLayout(childAvailW, childAvailH, measuredW, measuredH)\n }\n\n const childMainSize = cached ? (isRow ? cached.width : cached.height) : isRow ? measuredW : measuredH\n const childCrossSize = cached ? (isRow ? cached.height : cached.width) : isRow ? measuredH : measuredW\n\n totalMainSize += childMainSize + childMarginMain\n maxCrossSize = Math.max(maxCrossSize, childCrossSize + childMarginCross)\n itemCount++\n }\n\n // Add gaps\n if (itemCount > 1) {\n totalMainSize += mainGap * (itemCount - 1)\n }\n\n // Compute final node size\n if (Number.isNaN(nodeWidth)) {\n nodeWidth = (isRow ? totalMainSize : maxCrossSize) + innerLeft + innerRight\n }\n if (Number.isNaN(nodeHeight)) {\n nodeHeight = (isRow ? maxCrossSize : totalMainSize) + innerTop + innerBottom\n }\n\n // Apply min/max again after shrink-wrap\n nodeWidth = applyMinMax(nodeWidth, style.minWidth, style.maxWidth, availableWidth)\n nodeHeight = applyMinMax(nodeHeight, style.minHeight, style.maxHeight, availableHeight)\n\n layout.width = Math.round(nodeWidth)\n layout.height = Math.round(nodeHeight)\n}\n","/**\n * Flex Line Breaking and Space Distribution\n *\n * Pre-allocated arrays for zero-allocation flex-wrap layout,\n * plus the line-breaking and flex-distribution algorithms.\n *\n * Re-entrancy: A user measureFunc or baselineFunc may synchronously call\n * calculateLayout() on a separate tree. saveLineState/restoreLineState\n * bracket such nested calls to protect the outer pass's scratch arrays.\n */\n\nimport * as C from \"./constants.js\"\nimport type { Node } from \"./node-zero.js\"\n\n// ============================================================================\n// Pre-allocated Arrays for Zero-Allocation Layout\n// ============================================================================\n//\n// These module-level typed arrays enable zero-allocation flex-wrap layout.\n// They store per-line metrics that would otherwise require FlexLine[] allocation.\n//\n// Trade-offs:\n// - Pro: No heap allocation during layout passes (eliminates GC pressure)\n// - Pro: Cache-friendly contiguous memory access\n// - Con: Fixed maximum lines (grows dynamically if exceeded, rare allocation)\n// - Con: Not reentrant (single layout calculation at a time)\n//\n// Memory usage: ~768 bytes total (32 lines x 8 bytes x 2 + 32 x 2 bytes)\n\n/**\n * Maximum number of flex lines supported without dynamic allocation.\n * If a layout exceeds this, arrays grow automatically (rare edge case).\n * 32 lines covers virtually all real-world layouts while using minimal memory.\n */\nexport let MAX_FLEX_LINES = 32\n\n/**\n * Pre-allocated array for line cross sizes (reused across layout passes).\n * Stores the computed cross-axis size of each flex line.\n */\nexport let _lineCrossSizes = new Float64Array(MAX_FLEX_LINES)\n\n/**\n * Pre-allocated array for line cross offsets (reused across layout passes).\n * Stores the cross-axis position offset for each flex line.\n */\nexport let _lineCrossOffsets = new Float64Array(MAX_FLEX_LINES)\n\n/**\n * Pre-allocated array for line lengths (number of children per line).\n * Uint16 supports up to 65535 children per line (more than sufficient).\n */\nexport let _lineLengths = new Uint16Array(MAX_FLEX_LINES)\n\n/**\n * Pre-allocated 2D array for children per line.\n * Avoids O(n*m) iteration when processing multi-line flex layouts.\n * Each slot holds array of Node references for that line.\n */\nexport let _lineChildren: Node[][] = Array.from({ length: MAX_FLEX_LINES }, () => [])\n\n/**\n * Pre-allocated array for per-line justify-content start offsets.\n * Stores the main-axis starting position for each flex line.\n */\nexport let _lineJustifyStarts = new Float64Array(MAX_FLEX_LINES)\n\n/**\n * Pre-allocated array for per-line item spacing (justify-content gaps).\n * Stores the spacing between items for each flex line.\n */\nexport let _lineItemSpacings = new Float64Array(MAX_FLEX_LINES)\n\n/**\n * Grow pre-allocated line arrays if needed.\n * Called when a layout has more lines than current capacity.\n * This is rare (>32 lines) and acceptable as a one-time allocation.\n */\nexport function growLineArrays(needed: number): void {\n const newSize = Math.max(needed, MAX_FLEX_LINES * 2)\n MAX_FLEX_LINES = newSize\n _lineCrossSizes = new Float64Array(newSize)\n _lineCrossOffsets = new Float64Array(newSize)\n _lineLengths = new Uint16Array(newSize)\n _lineJustifyStarts = new Float64Array(newSize)\n _lineItemSpacings = new Float64Array(newSize)\n // Grow _lineChildren array\n while (_lineChildren.length < newSize) {\n _lineChildren.push([])\n }\n}\n\n// ============================================================================\n// Re-entrancy Support\n// ============================================================================\n// When a measureFunc/baselineFunc synchronously calls calculateLayout() on\n// another tree, we must save and restore the module-level scratch arrays so\n// the outer pass resumes with its own data intact.\n\n/**\n * Saved snapshot of all module-level line arrays.\n * Allocated only on re-entrant calls (depth > 0).\n */\nexport interface LineStateSave {\n crossSizes: Float64Array<ArrayBuffer>\n crossOffsets: Float64Array<ArrayBuffer>\n lengths: Uint16Array<ArrayBuffer>\n justifyStarts: Float64Array<ArrayBuffer>\n itemSpacings: Float64Array<ArrayBuffer>\n children: Node[][]\n maxLines: number\n}\n\n/** Current re-entrancy depth. 0 = outermost (no save needed). */\nlet _layoutDepth = 0\n\n/**\n * Enter a layout pass. If re-entrant (depth > 0), saves current line state.\n * @returns The saved state (to pass to restoreLineState), or null at depth 0.\n */\nexport function enterLayout(): LineStateSave | null {\n const depth = _layoutDepth++\n if (depth === 0) return null // Outermost — no save needed\n\n // Save current state (allocates only on re-entrant calls — rare)\n const saved: LineStateSave = {\n crossSizes: _lineCrossSizes.slice(),\n crossOffsets: _lineCrossOffsets.slice(),\n lengths: _lineLengths.slice(),\n justifyStarts: _lineJustifyStarts.slice(),\n itemSpacings: _lineItemSpacings.slice(),\n children: _lineChildren.map((arr) => arr.slice()),\n maxLines: MAX_FLEX_LINES,\n }\n return saved\n}\n\n/**\n * Exit a layout pass. If re-entrant, restores saved line state.\n * @param saved - The state returned by enterLayout (null at depth 0).\n */\nexport function exitLayout(saved: LineStateSave | null): void {\n _layoutDepth--\n if (!saved) return // Outermost — nothing to restore\n\n // Restore saved state\n MAX_FLEX_LINES = saved.maxLines\n _lineCrossSizes = saved.crossSizes\n _lineCrossOffsets = saved.crossOffsets\n _lineLengths = saved.lengths\n _lineJustifyStarts = saved.justifyStarts\n _lineItemSpacings = saved.itemSpacings\n _lineChildren = saved.children\n}\n\n/**\n * Epsilon value for floating point comparisons in flex distribution.\n * Used to determine when remaining space is negligible and iteration should stop.\n */\nconst EPSILON_FLOAT = 0.001\n\n/**\n * Break children into flex lines based on available main-axis space.\n * Zero-allocation: Sets child.flex.lineIndex directly, uses pre-allocated _lineStarts/_lineLengths.\n *\n * @param parent - Parent node whose children to wrap\n * @param relativeCount - Number of relative children (those with flex.relativeIndex >= 0)\n * @param mainAxisSize - Available main-axis space (NaN for unconstrained)\n * @param mainGap - Gap between items on main axis\n * @param wrap - Wrap mode (WRAP_NO_WRAP, WRAP_WRAP, WRAP_WRAP_REVERSE)\n * @returns Number of lines created\n */\nexport function breakIntoLines(\n parent: Node,\n relativeCount: number,\n mainAxisSize: number,\n mainGap: number,\n wrap: number,\n): number {\n // No wrapping or unconstrained - all children on one line\n if (wrap === C.WRAP_NO_WRAP || Number.isNaN(mainAxisSize) || relativeCount === 0) {\n // All relative children on line 0, populate _lineChildren for O(n) access\n // Use index-based assignment to avoid push() backing store growth\n const lineArr = _lineChildren[0]!\n let idx = 0\n for (const child of parent.children) {\n if (child.flex.relativeIndex >= 0) {\n child.flex.lineIndex = 0\n lineArr[idx++] = child\n }\n }\n lineArr.length = idx // Trim to actual size\n _lineLengths[0] = relativeCount\n _lineCrossSizes[0] = 0\n _lineCrossOffsets[0] = 0\n return 1\n }\n\n let lineIndex = 0\n let lineMainSize = 0\n let lineChildCount = 0\n let lineChildIdx = 0 // Index within current line array\n\n for (const child of parent.children) {\n if (child.flex.relativeIndex < 0) continue\n\n const flex = child.flex\n // CSS spec 9.3.4: line breaking uses the \"hypothetical main size\" which is\n // the flex base size clamped to min/max, not the unclamped base size.\n const hypotheticalMainSize = Math.max(flex.minMain, Math.min(flex.maxMain, flex.baseSize))\n const childMainSize = hypotheticalMainSize + flex.mainMargin\n const gapIfNotFirst = lineChildCount > 0 ? mainGap : 0\n\n // Check if child fits on current line\n if (lineChildCount > 0 && lineMainSize + gapIfNotFirst + childMainSize > mainAxisSize) {\n // Finalize current line: trim array to actual size\n _lineChildren[lineIndex]!.length = lineChildIdx\n _lineLengths[lineIndex] = lineChildCount\n lineIndex++\n if (lineIndex >= MAX_FLEX_LINES) {\n // Grow arrays dynamically (rare - only for >32 line layouts)\n growLineArrays(lineIndex + 16)\n }\n lineChildIdx = 0 // Reset index for new line\n lineMainSize = childMainSize\n lineChildCount = 1\n } else {\n lineMainSize += gapIfNotFirst + childMainSize\n lineChildCount++\n }\n flex.lineIndex = lineIndex\n // Use index-based assignment to avoid push() backing store growth\n _lineChildren[lineIndex]![lineChildIdx++] = child\n }\n\n // Finalize the last line\n if (lineChildCount > 0) {\n _lineChildren[lineIndex]!.length = lineChildIdx // Trim to actual size\n _lineLengths[lineIndex] = lineChildCount\n lineIndex++\n }\n\n const numLines = lineIndex\n\n // Initialize cross sizes/offsets\n for (let i = 0; i < numLines; i++) {\n _lineCrossSizes[i] = 0\n _lineCrossOffsets[i] = 0\n }\n\n // Handle wrap-reverse by reversing line CONTENTS (not references) to maintain pool stability\n // Swapping array references would corrupt the global _lineChildren pool across layout calls\n if (wrap === C.WRAP_WRAP_REVERSE && numLines > 1) {\n // Swap contents between symmetric line pairs (element-by-element, zero allocation)\n for (let i = 0; i < Math.floor(numLines / 2); i++) {\n const j = numLines - 1 - i\n const lineI = _lineChildren[i]!\n const lineJ = _lineChildren[j]!\n const lenI = lineI.length\n const lenJ = lineJ.length\n\n // Swap elements up to max length (JS arrays auto-extend on assignment)\n const maxLen = Math.max(lenI, lenJ)\n for (let k = 0; k < maxLen; k++) {\n const hasI = k < lenI\n const hasJ = k < lenJ\n const tmpI = hasI ? lineI[k] : null\n const tmpJ = hasJ ? lineJ[k] : null\n if (hasJ) lineI[k] = tmpJ!\n if (hasI) lineJ[k] = tmpI!\n }\n\n // Set correct lengths (truncates or maintains as needed)\n lineI.length = lenJ\n lineJ.length = lenI\n }\n // Update lineIndex on each child to match new positions\n for (let i = 0; i < numLines; i++) {\n const lc = _lineChildren[i]!\n for (let c = 0; c < lc.length; c++) {\n lc[c]!.flex.lineIndex = i\n }\n }\n }\n\n return numLines\n}\n\n/**\n * Distribute flex space for a single line of children.\n * Implements CSS Flexbox section 9.7: Resolving Flexible Lengths.\n *\n * Takes pre-collected children array to avoid O(n*m) iteration pattern.\n * Previously iterated through ALL parent.children 8 times per line.\n *\n * @param lineChildren - Pre-collected children for this line (from _lineChildren)\n * @param initialFreeSpace - Free space to distribute (positive=grow, negative=shrink)\n */\nexport function distributeFlexSpaceForLine(lineChildren: Node[], initialFreeSpace: number): void {\n const isGrowing = initialFreeSpace > 0\n if (initialFreeSpace === 0) return\n\n const childCount = lineChildren.length\n if (childCount === 0) return\n\n // Single-child fast path: skip iteration, direct assignment\n if (childCount === 1) {\n const flex = lineChildren[0]!.flex\n const canFlex = isGrowing ? flex.flexGrow > 0 : flex.flexShrink > 0\n if (canFlex) {\n // Target = base + all free space, clamped by min/max\n const target = flex.baseSize + initialFreeSpace\n flex.mainSize = Math.max(flex.minMain, Math.min(flex.maxMain, target))\n }\n // If can't flex, mainSize stays at baseSize (already set)\n return\n }\n\n // Calculate container inner size\n let totalBase = 0\n for (let i = 0; i < childCount; i++) {\n totalBase += lineChildren[i]!.flex.baseSize\n }\n\n const containerInner = initialFreeSpace + totalBase\n\n // Initialize: all items start unfrozen\n for (let i = 0; i < childCount; i++) {\n lineChildren[i]!.flex.frozen = false\n }\n\n let freeSpace = initialFreeSpace\n let iterations = 0\n const maxIterations = childCount + 1\n\n while (iterations++ < maxIterations) {\n let totalFlex = 0\n for (let i = 0; i < childCount; i++) {\n const flex = lineChildren[i]!.flex\n if (flex.frozen) continue\n if (isGrowing) {\n totalFlex += flex.flexGrow\n } else {\n totalFlex += flex.flexShrink * flex.baseSize\n }\n }\n\n if (totalFlex === 0) break\n\n let effectiveFreeSpace = freeSpace\n if (isGrowing && totalFlex < 1) {\n effectiveFreeSpace = freeSpace * totalFlex\n }\n\n let totalViolation = 0\n for (let i = 0; i < childCount; i++) {\n const flex = lineChildren[i]!.flex\n if (flex.frozen) continue\n\n const flexFactor = isGrowing ? flex.flexGrow : flex.flexShrink * flex.baseSize\n const ratio = totalFlex > 0 ? flexFactor / totalFlex : 0\n const target = flex.baseSize + effectiveFreeSpace * ratio\n const clamped = Math.max(flex.minMain, Math.min(flex.maxMain, target))\n totalViolation += clamped - target\n flex.mainSize = clamped\n }\n\n let anyFrozen = false\n if (Math.abs(totalViolation) < EPSILON_FLOAT) {\n for (let i = 0; i < childCount; i++) {\n lineChildren[i]!.flex.frozen = true\n }\n break\n } else if (totalViolation > 0) {\n for (let i = 0; i < childCount; i++) {\n const flex = lineChildren[i]!.flex\n if (flex.frozen) continue\n const target =\n flex.baseSize +\n ((isGrowing ? flex.flexGrow : flex.flexShrink * flex.baseSize) / totalFlex) * effectiveFreeSpace\n if (flex.mainSize > target + EPSILON_FLOAT) {\n flex.frozen = true\n anyFrozen = true\n }\n }\n } else {\n for (let i = 0; i < childCount; i++) {\n const flex = lineChildren[i]!.flex\n if (flex.frozen) continue\n const flexFactor = isGrowing ? flex.flexGrow : flex.flexShrink * flex.baseSize\n const target = flex.baseSize + (flexFactor / totalFlex) * effectiveFreeSpace\n if (flex.mainSize < target - EPSILON_FLOAT) {\n flex.frozen = true\n anyFrozen = true\n }\n }\n }\n\n if (!anyFrozen) break\n\n let frozenSpace = 0\n let unfrozenBase = 0\n for (let i = 0; i < childCount; i++) {\n const flex = lineChildren[i]!.flex\n if (flex.frozen) {\n frozenSpace += flex.mainSize\n } else {\n unfrozenBase += flex.baseSize\n }\n }\n freeSpace = containerInner - frozenSpace - unfrozenBase\n }\n}\n","/**\n * Flexily Layout Algorithm — Main Entry Point\n *\n * Core flexbox layout computation. This file contains:\n * - computeLayout(): top-level entry point\n * - layoutNode(): recursive layout algorithm (11 phases)\n *\n * Helper modules (split for maintainability, zero-allocation preserved):\n * - layout-helpers.ts: Edge resolution (margins, padding, borders)\n * - layout-traversal.ts: Tree traversal (markSubtreeLayoutSeen, countNodes)\n * - layout-flex-lines.ts: Pre-allocated arrays, line breaking, flex distribution\n * - layout-measure.ts: Intrinsic sizing (measureNode)\n * - layout-stats.ts: Debug/benchmark counters\n *\n * Based on Planning-nl/flexbox.js reference implementation.\n */\n\nimport * as C from \"./constants.js\"\nimport type { Node } from \"./node-zero.js\"\nimport { resolveValue, applyMinMax } from \"./utils.js\"\nimport { log } from \"./logger.js\"\nimport { getTrace } from \"./trace.js\"\n\n// Re-export helpers for backward compatibility\nexport {\n isRowDirection,\n isReverseDirection,\n resolveEdgeValue,\n isEdgeAuto,\n resolveEdgeBorderValue,\n} from \"./layout-helpers.js\"\n\n// Re-export traversal utilities for backward compatibility\nexport { markSubtreeLayoutSeen, countNodes } from \"./layout-traversal.js\"\n\n// Re-export stats for backward compatibility\nexport {\n layoutNodeCalls,\n measureNodeCalls,\n layoutSizingCalls,\n layoutPositioningCalls,\n layoutCacheHits,\n resetLayoutStats,\n} from \"./layout-stats.js\"\n\n// Re-export measureNode for backward compatibility\nexport { measureNode } from \"./layout-measure.js\"\n\n// Import what we need internally\nimport {\n isRowDirection,\n isReverseDirection,\n resolveEdgeValue,\n resolvePositionEdge,\n isEdgeAuto,\n resolveEdgeBorderValue,\n} from \"./layout-helpers.js\"\nimport { propagatePositionDelta } from \"./layout-traversal.js\"\nimport {\n resetLayoutStats,\n incLayoutNodeCalls,\n incLayoutSizingCalls,\n incLayoutPositioningCalls,\n incLayoutCacheHits,\n} from \"./layout-stats.js\"\nimport { measureNode } from \"./layout-measure.js\"\nimport {\n MAX_FLEX_LINES,\n _lineCrossSizes,\n _lineCrossOffsets,\n _lineChildren,\n _lineJustifyStarts,\n _lineItemSpacings,\n breakIntoLines,\n distributeFlexSpaceForLine,\n enterLayout,\n exitLayout,\n} from \"./layout-flex-lines.js\"\n\n/**\n * Compute layout for a node tree.\n */\nexport function computeLayout(\n root: Node,\n availableWidth: number,\n availableHeight: number,\n direction: number = C.DIRECTION_LTR,\n): void {\n // Save line state if re-entrant (nested calculateLayout from measureFunc)\n const saved = enterLayout()\n try {\n resetLayoutStats()\n getTrace()?.resetCounter()\n // Clear layout cache from previous pass (important for correct layout after tree changes)\n root.resetLayoutCache()\n // Pass absolute position (0,0) for root node - used for Yoga-compatible edge rounding\n layoutNode(root, availableWidth, availableHeight, 0, 0, 0, 0, direction)\n } finally {\n // Restore line state for outer pass (no-op at depth 0)\n exitLayout(saved)\n }\n}\n\n/**\n * Layout a node and its children.\n *\n * @param absX - Absolute X position from document root (for Yoga-compatible edge rounding)\n * @param absY - Absolute Y position from document root (for Yoga-compatible edge rounding)\n */\nfunction layoutNode(\n node: Node,\n availableWidth: number,\n availableHeight: number,\n offsetX: number,\n offsetY: number,\n absX: number,\n absY: number,\n direction: number = C.DIRECTION_LTR,\n): void {\n incLayoutNodeCalls()\n // Track sizing vs positioning calls\n const isSizingPass = offsetX === 0 && offsetY === 0 && absX === 0 && absY === 0\n if (isSizingPass && node.children.length > 0) {\n incLayoutSizingCalls()\n } else {\n incLayoutPositioningCalls()\n }\n log.debug?.(\n \"layoutNode called: availW=%d, availH=%d, offsetX=%d, offsetY=%d, absX=%d, absY=%d, children=%d\",\n availableWidth,\n availableHeight,\n offsetX,\n offsetY,\n absX,\n absY,\n node.children.length,\n )\n const _t = getTrace()\n const _tn = _t?.nextNode() ?? 0\n _t?.layoutEnter(_tn, availableWidth, availableHeight, node.isDirty(), node.children.length)\n const style = node.style\n const layout = node.layout\n\n // ============================================================================\n // PHASE 1: Early Exit Checks\n // ============================================================================\n\n // Handle display: none\n if (style.display === C.DISPLAY_NONE) {\n layout.left = 0\n layout.top = 0\n layout.width = 0\n layout.height = 0\n return\n }\n\n // Constraint fingerprinting: skip layout if constraints unchanged and node not dirty\n // Use Object.is() for NaN-safe comparison (NaN === NaN is false, Object.is(NaN, NaN) is true)\n const flex = node.flex\n if (\n flex.layoutValid &&\n !node.isDirty() &&\n Object.is(flex.lastAvailW, availableWidth) &&\n Object.is(flex.lastAvailH, availableHeight) &&\n flex.lastDir === direction &&\n flex.lastAbsX === absX &&\n flex.lastAbsY === absY\n ) {\n // Constraints unchanged - just update position based on offset delta\n _t?.fingerprintHit(_tn, availableWidth, availableHeight)\n const deltaX = offsetX - flex.lastOffsetX\n const deltaY = offsetY - flex.lastOffsetY\n if (deltaX !== 0 || deltaY !== 0) {\n layout.left += deltaX\n layout.top += deltaY\n flex.lastOffsetX = offsetX\n flex.lastOffsetY = offsetY\n // Propagate position delta to all children\n propagatePositionDelta(node, deltaX, deltaY)\n }\n return\n }\n _t?.fingerprintMiss(_tn, availableWidth, availableHeight, {\n layoutValid: flex.layoutValid,\n isDirty: node.isDirty(),\n sameW: Object.is(flex.lastAvailW, availableWidth),\n sameH: Object.is(flex.lastAvailH, availableHeight),\n sameDir: flex.lastDir === direction,\n sameAbsX: flex.lastAbsX === absX,\n sameAbsY: flex.lastAbsY === absY,\n })\n\n // ============================================================================\n // PHASE 2: Resolve Spacing (margins, padding, borders)\n // CSS spec: percentage margins AND padding resolve against containing block's WIDTH only\n // ============================================================================\n\n const marginLeft = resolveEdgeValue(style.margin, 0, style.flexDirection, availableWidth, direction)\n const marginTop = resolveEdgeValue(style.margin, 1, style.flexDirection, availableWidth, direction)\n const marginRight = resolveEdgeValue(style.margin, 2, style.flexDirection, availableWidth, direction)\n const marginBottom = resolveEdgeValue(style.margin, 3, style.flexDirection, availableWidth, direction)\n\n const paddingLeft = resolveEdgeValue(style.padding, 0, style.flexDirection, availableWidth, direction)\n const paddingTop = resolveEdgeValue(style.padding, 1, style.flexDirection, availableWidth, direction)\n const paddingRight = resolveEdgeValue(style.padding, 2, style.flexDirection, availableWidth, direction)\n const paddingBottom = resolveEdgeValue(style.padding, 3, style.flexDirection, availableWidth, direction)\n\n const borderLeft = resolveEdgeBorderValue(style.border, 0, style.flexDirection, direction)\n const borderTop = resolveEdgeBorderValue(style.border, 1, style.flexDirection, direction)\n const borderRight = resolveEdgeBorderValue(style.border, 2, style.flexDirection, direction)\n const borderBottom = resolveEdgeBorderValue(style.border, 3, style.flexDirection, direction)\n\n // ============================================================================\n // PHASE 3: Calculate Node Dimensions\n // When available dimension is NaN (unconstrained), auto-sized nodes use NaN\n // and will be sized by shrink-wrap logic based on children\n // ============================================================================\n\n let nodeWidth: number\n if (style.width.unit === C.UNIT_POINT) {\n nodeWidth = style.width.value\n } else if (style.width.unit === C.UNIT_PERCENT) {\n // Percentage against NaN (auto-sized parent) resolves to 0 via resolveValue\n nodeWidth = resolveValue(style.width, availableWidth)\n } else if (Number.isNaN(availableWidth)) {\n // Unconstrained: use NaN to signal shrink-wrap (will be computed from children)\n nodeWidth = NaN\n } else {\n nodeWidth = availableWidth - marginLeft - marginRight\n }\n // Apply min/max constraints (works even with NaN available for point-based constraints)\n nodeWidth = applyMinMax(nodeWidth, style.minWidth, style.maxWidth, availableWidth)\n\n let nodeHeight: number\n if (style.height.unit === C.UNIT_POINT) {\n nodeHeight = style.height.value\n } else if (style.height.unit === C.UNIT_PERCENT) {\n // Percentage against NaN (auto-sized parent) resolves to 0 via resolveValue\n nodeHeight = resolveValue(style.height, availableHeight)\n } else if (Number.isNaN(availableHeight)) {\n // Unconstrained: use NaN to signal shrink-wrap (will be computed from children)\n nodeHeight = NaN\n } else {\n nodeHeight = availableHeight - marginTop - marginBottom\n }\n\n // Apply aspect ratio constraint (CSS aspect-ratio spec)\n // If aspectRatio is set and one dimension is auto (NaN), derive it from the other.\n // Re-apply min/max constraints on the derived dimension to respect CSS box model.\n const aspectRatio = style.aspectRatio\n if (!Number.isNaN(aspectRatio) && aspectRatio > 0) {\n const widthIsAuto = Number.isNaN(nodeWidth) || style.width.unit === C.UNIT_AUTO\n const heightIsAuto = Number.isNaN(nodeHeight) || style.height.unit === C.UNIT_AUTO\n\n if (widthIsAuto && !heightIsAuto && !Number.isNaN(nodeHeight)) {\n // Height is defined, width is auto: width = height * aspectRatio\n nodeWidth = nodeHeight * aspectRatio\n // Re-apply min/max for derived width\n nodeWidth = applyMinMax(nodeWidth, style.minWidth, style.maxWidth, availableWidth)\n } else if (heightIsAuto && !widthIsAuto && !Number.isNaN(nodeWidth)) {\n // Width is defined, height is auto: height = width / aspectRatio\n nodeHeight = nodeWidth / aspectRatio\n }\n // If both are defined or both are auto, aspectRatio doesn't apply at this stage\n }\n\n // Apply min/max constraints (works even with NaN available for point-based constraints)\n nodeHeight = applyMinMax(nodeHeight, style.minHeight, style.maxHeight, availableHeight)\n\n // Content area (inside border and padding)\n // When node dimensions are NaN (unconstrained), content dimensions are also NaN\n const innerLeft = borderLeft + paddingLeft\n const innerTop = borderTop + paddingTop\n const innerRight = borderRight + paddingRight\n const innerBottom = borderBottom + paddingBottom\n\n // Enforce box model constraint: minimum size = padding + border\n const minInnerWidth = innerLeft + innerRight\n const minInnerHeight = innerTop + innerBottom\n if (!Number.isNaN(nodeWidth) && nodeWidth < minInnerWidth) {\n nodeWidth = minInnerWidth\n }\n if (!Number.isNaN(nodeHeight) && nodeHeight < minInnerHeight) {\n nodeHeight = minInnerHeight\n }\n\n const contentWidth = Number.isNaN(nodeWidth) ? NaN : Math.max(0, nodeWidth - innerLeft - innerRight)\n const contentHeight = Number.isNaN(nodeHeight) ? NaN : Math.max(0, nodeHeight - innerTop - innerBottom)\n\n // Compute position offsets early (needed for children's absolute position calculation)\n // This ensures children's absolute positions include parent's position offset\n let parentPosOffsetX = 0\n let parentPosOffsetY = 0\n // CSS spec: position:static ignores insets (top/left/right/bottom).\n // Only position:relative applies insets as offsets from normal flow position.\n if (style.positionType === C.POSITION_TYPE_RELATIVE) {\n // Resolve logical EDGE_START/EDGE_END to physical left/right based on direction\n const leftPos = resolvePositionEdge(style.position, 0, direction)\n const topPos = style.position[1]\n const rightPos = resolvePositionEdge(style.position, 2, direction)\n const bottomPos = style.position[3]\n\n if (leftPos.unit !== C.UNIT_UNDEFINED) {\n parentPosOffsetX = resolveValue(leftPos, availableWidth)\n } else if (rightPos.unit !== C.UNIT_UNDEFINED) {\n parentPosOffsetX = -resolveValue(rightPos, availableWidth)\n }\n\n if (topPos.unit !== C.UNIT_UNDEFINED) {\n parentPosOffsetY = resolveValue(topPos, availableHeight)\n } else if (bottomPos.unit !== C.UNIT_UNDEFINED) {\n parentPosOffsetY = -resolveValue(bottomPos, availableHeight)\n }\n }\n\n // =========================================================================\n // PHASE 4: Handle Leaf Nodes (nodes without children)\n // =========================================================================\n // Two cases:\n // - With measureFunc: Call measure to get intrinsic size (text nodes)\n // - Without measureFunc: Use padding+border as intrinsic size (empty boxes)\n\n // Handle measure function (text nodes)\n if (node.hasMeasureFunc() && node.children.length === 0) {\n // For unconstrained dimensions (NaN), treat as auto-sizing\n const widthIsAuto =\n style.width.unit === C.UNIT_AUTO || style.width.unit === C.UNIT_UNDEFINED || Number.isNaN(nodeWidth)\n const heightIsAuto =\n style.height.unit === C.UNIT_AUTO || style.height.unit === C.UNIT_UNDEFINED || Number.isNaN(nodeHeight)\n const widthMode = widthIsAuto ? C.MEASURE_MODE_AT_MOST : C.MEASURE_MODE_EXACTLY\n const heightMode = heightIsAuto ? C.MEASURE_MODE_UNDEFINED : C.MEASURE_MODE_EXACTLY\n\n // For unconstrained width, use a large value; measureFunc should return intrinsic size\n const measureWidth = Number.isNaN(contentWidth) ? Infinity : contentWidth\n const measureHeight = Number.isNaN(contentHeight) ? Infinity : contentHeight\n\n // Use cached measure to avoid redundant calls within a layout pass\n const measured = node.cachedMeasure(measureWidth, widthMode, measureHeight, heightMode)!\n\n if (widthIsAuto) {\n nodeWidth = measured.width + innerLeft + innerRight\n }\n if (heightIsAuto) {\n nodeHeight = measured.height + innerTop + innerBottom\n }\n\n layout.width = Math.round(nodeWidth)\n layout.height = Math.round(nodeHeight)\n layout.left = Math.round(offsetX + marginLeft)\n layout.top = Math.round(offsetY + marginTop)\n return\n }\n\n // Handle leaf nodes without measureFunc - when unconstrained, use padding+border as intrinsic size\n if (node.children.length === 0) {\n // For leaf nodes without measureFunc, intrinsic size is just padding+border\n if (Number.isNaN(nodeWidth)) {\n nodeWidth = innerLeft + innerRight\n }\n if (Number.isNaN(nodeHeight)) {\n nodeHeight = innerTop + innerBottom\n }\n layout.width = Math.round(nodeWidth)\n layout.height = Math.round(nodeHeight)\n layout.left = Math.round(offsetX + marginLeft)\n layout.top = Math.round(offsetY + marginTop)\n return\n }\n\n // =========================================================================\n // PHASE 5: Flex Layout - Collect Children and Compute Base Sizes\n // =========================================================================\n // Single pass over children:\n // - Skip absolute/hidden children (relativeIndex = -1)\n // - Cache resolved margins for each relative child\n // - Compute base main size from flex-basis, explicit size, or intrinsic size\n // - Track flex grow/shrink factors and min/max constraints\n // - Count auto margins for later distribution\n\n const isRow = isRowDirection(style.flexDirection)\n const isReverse = isReverseDirection(style.flexDirection)\n // For RTL, row direction is reversed (XOR with isReverse)\n const isRTL = direction === C.DIRECTION_RTL\n const effectiveReverse = isRow ? isRTL !== isReverse : isReverse\n\n const mainAxisSize = isRow ? contentWidth : contentHeight\n const crossAxisSize = isRow ? contentHeight : contentWidth\n const mainGap = isRow ? style.gap[0] : style.gap[1]\n\n // Prepare child flex info (stored on each child node - zero allocation)\n let totalBaseMain = 0\n let relativeCount = 0\n let totalAutoMargins = 0 // Count auto margins during this pass\n let hasBaselineAlignment = style.alignItems === C.ALIGN_BASELINE\n\n for (const child of node.children) {\n // Mark relativeIndex (-1 for absolute/hidden, 0+ for relative)\n if (child.style.display === C.DISPLAY_NONE || child.style.positionType === C.POSITION_TYPE_ABSOLUTE) {\n child.flex.relativeIndex = -1\n continue\n }\n child.flex.relativeIndex = relativeCount++\n const childStyle = child.style\n const cflex = child.flex\n\n // Check for auto margins on main axis\n // Physical indices depend on axis and effective reverse (including RTL):\n // - Row LTR: main-start=left(0), main-end=right(2)\n // - Row RTL: main-start=right(2), main-end=left(0)\n // - Row-reverse LTR: main-start=right(2), main-end=left(0)\n // - Row-reverse RTL: main-start=left(0), main-end=right(2)\n // - Column: main-start=top(1), main-end=bottom(3) (RTL doesn't affect column)\n // - Column-reverse: main-start=bottom(3), main-end=top(1)\n // For row layouts, use effectiveReverse (which XORs RTL with isReverse)\n const mainStartIndex = isRow ? (effectiveReverse ? 2 : 0) : isReverse ? 3 : 1\n const mainEndIndex = isRow ? (effectiveReverse ? 0 : 2) : isReverse ? 1 : 3\n cflex.mainStartMarginAuto = isEdgeAuto(childStyle.margin, mainStartIndex, style.flexDirection, direction)\n cflex.mainEndMarginAuto = isEdgeAuto(childStyle.margin, mainEndIndex, style.flexDirection, direction)\n\n // Cache all 4 resolved margins once (CSS spec: percentages resolve against containing block's WIDTH)\n // This avoids repeated resolveEdgeValue calls throughout the layout pass\n cflex.marginL = resolveEdgeValue(childStyle.margin, 0, style.flexDirection, contentWidth, direction)\n cflex.marginT = resolveEdgeValue(childStyle.margin, 1, style.flexDirection, contentWidth, direction)\n cflex.marginR = resolveEdgeValue(childStyle.margin, 2, style.flexDirection, contentWidth, direction)\n cflex.marginB = resolveEdgeValue(childStyle.margin, 3, style.flexDirection, contentWidth, direction)\n\n // Resolve non-auto margins (auto margins resolve to 0 initially)\n // Use effectiveReverse for row layouts (accounts for RTL)\n cflex.mainStartMarginValue = cflex.mainStartMarginAuto\n ? 0\n : isRow\n ? effectiveReverse\n ? cflex.marginR\n : cflex.marginL\n : isReverse\n ? cflex.marginB\n : cflex.marginT\n cflex.mainEndMarginValue = cflex.mainEndMarginAuto\n ? 0\n : isRow\n ? effectiveReverse\n ? cflex.marginL\n : cflex.marginR\n : isReverse\n ? cflex.marginT\n : cflex.marginB\n\n // Total non-auto margin for flex calculations\n cflex.mainMargin = cflex.mainStartMarginValue + cflex.mainEndMarginValue\n\n // Determine base size (flex-basis or explicit size)\n // Guard: percent against NaN (unconstrained) resolves to 0 (CSS/Yoga behavior)\n let baseSize = 0\n if (childStyle.flexBasis.unit === C.UNIT_POINT) {\n baseSize = childStyle.flexBasis.value\n } else if (childStyle.flexBasis.unit === C.UNIT_PERCENT) {\n baseSize = Number.isNaN(mainAxisSize) ? 0 : mainAxisSize * (childStyle.flexBasis.value / 100)\n } else {\n const sizeVal = isRow ? childStyle.width : childStyle.height\n if (sizeVal.unit === C.UNIT_POINT) {\n baseSize = sizeVal.value\n } else if (sizeVal.unit === C.UNIT_PERCENT) {\n baseSize = Number.isNaN(mainAxisSize) ? 0 : mainAxisSize * (sizeVal.value / 100)\n } else if (child.hasMeasureFunc()) {\n // For auto-sized children with measureFunc,\n // pre-measure to get intrinsic content size as flex base size.\n // CSS spec section 9.2: flex base size is content-based regardless of flexGrow.\n //\n // When flexGrow > 0, measure UNCONSTRAINED on main axis to get max-content\n // size. This ensures proportional distribution based on content (e.g., two\n // text nodes with widths 10 and 20 get proportional shares of free space).\n // When flexGrow === 0, measure AT_MOST container (original behavior for\n // justify-content calculation).\n const crossMargin = isRow ? cflex.marginT + cflex.marginB : cflex.marginL + cflex.marginR\n const availCross = crossAxisSize - crossMargin\n // Measure function takes PHYSICAL (width, height), not logical (main, cross).\n // For row: main=width, cross=height. For column: main=height, cross=width.\n const wantMaxContent = childStyle.flexGrow > 0\n const mW = isRow\n ? wantMaxContent\n ? Infinity\n : Number.isNaN(mainAxisSize)\n ? Infinity\n : mainAxisSize\n : Number.isNaN(availCross)\n ? Infinity\n : availCross\n const mH = isRow\n ? Number.isNaN(availCross)\n ? Infinity\n : availCross\n : wantMaxContent\n ? Infinity\n : Number.isNaN(mainAxisSize)\n ? Infinity\n : mainAxisSize\n const mWMode = isRow\n ? wantMaxContent\n ? C.MEASURE_MODE_UNDEFINED\n : C.MEASURE_MODE_AT_MOST\n : Number.isNaN(availCross)\n ? C.MEASURE_MODE_UNDEFINED\n : C.MEASURE_MODE_AT_MOST\n const mHMode = isRow\n ? C.MEASURE_MODE_UNDEFINED\n : wantMaxContent\n ? C.MEASURE_MODE_UNDEFINED\n : C.MEASURE_MODE_AT_MOST\n const measured = child.cachedMeasure(mW, mWMode, mH, mHMode)!\n baseSize = isRow ? measured.width : measured.height\n } else if (child.children.length > 0) {\n // For auto-sized children WITH children but no measureFunc,\n // recursively compute intrinsic size by laying out with unconstrained main axis\n // Check cache first to avoid redundant recursive calls\n const sizingW = isRow ? NaN : crossAxisSize\n const sizingH = isRow ? crossAxisSize : NaN\n const cached = child.getCachedLayout(sizingW, sizingH)\n if (cached) {\n incLayoutCacheHits()\n _t?.cacheHit(_tn, sizingW, sizingH, cached.width, cached.height)\n baseSize = isRow ? cached.width : cached.height\n } else {\n _t?.cacheMiss(_tn, sizingW, sizingH)\n // Use measureNode for sizing-only pass (faster than full layoutNode)\n // Save layout before measureNode — it overwrites node.layout.width/height\n // with intrinsic measurements (unconstrained widths -> text doesn't wrap ->\n // shorter height). Without save/restore, layoutNode's fingerprint check\n // in Phase 9 would skip re-computation and preserve the corrupted values.\n const savedW = child.layout.width\n const savedH = child.layout.height\n measureNode(child, sizingW, sizingH, direction)\n const measuredW = child.layout.width\n const measuredH = child.layout.height\n child.layout.width = savedW\n child.layout.height = savedH\n _t?.measureSaveRestore(_tn, savedW, savedH, measuredW, measuredH)\n baseSize = isRow ? measuredW : measuredH\n // Cache the result for potential reuse\n child.setCachedLayout(sizingW, sizingH, measuredW, measuredH)\n }\n } else {\n // For auto-sized LEAF children without measureFunc, use padding + border as minimum\n // This ensures elements with only padding still have proper size\n // CSS spec: percentage padding resolves against containing block's WIDTH only\n // Use resolveEdgeValue to respect logical EDGE_START/END\n // For row: mainAxisSize is contentWidth; for column: crossAxisSize is contentWidth\n const parentWidth = isRow ? mainAxisSize : crossAxisSize\n const childPadding = isRow\n ? resolveEdgeValue(childStyle.padding, 0, childStyle.flexDirection, parentWidth, direction) +\n resolveEdgeValue(childStyle.padding, 2, childStyle.flexDirection, parentWidth, direction)\n : resolveEdgeValue(childStyle.padding, 1, childStyle.flexDirection, parentWidth, direction) +\n resolveEdgeValue(childStyle.padding, 3, childStyle.flexDirection, parentWidth, direction)\n const childBorder = isRow\n ? resolveEdgeBorderValue(childStyle.border, 0, childStyle.flexDirection, direction) +\n resolveEdgeBorderValue(childStyle.border, 2, childStyle.flexDirection, direction)\n : resolveEdgeBorderValue(childStyle.border, 1, childStyle.flexDirection, direction) +\n resolveEdgeBorderValue(childStyle.border, 3, childStyle.flexDirection, direction)\n baseSize = childPadding + childBorder\n }\n }\n\n // Min/max on main axis\n const minVal = isRow ? childStyle.minWidth : childStyle.minHeight\n const maxVal = isRow ? childStyle.maxWidth : childStyle.maxHeight\n cflex.minMain = minVal.unit !== C.UNIT_UNDEFINED ? resolveValue(minVal, mainAxisSize) : 0\n cflex.maxMain = maxVal.unit !== C.UNIT_UNDEFINED ? resolveValue(maxVal, mainAxisSize) : Infinity\n\n // Store flex factors from style\n cflex.flexGrow = childStyle.flexGrow\n // CSS spec 4.5: overflow containers have automatic min-size = 0 and can shrink\n // below content size. Yoga defaults flexShrink to 0, preventing this. For\n // overflow:hidden/scroll children, ensure flexShrink >= 1 so they participate\n // in negative free space distribution (matching CSS behavior).\n //\n // Measured items with flexGrow > 0 use max-content as base size (CSS section 9.2).\n // When their total base sizes exceed the container, they must be shrinkable so\n // the flex algorithm can distribute negative free space. Without this, a single\n // flexGrow text node whose content exceeds the container would overflow instead\n // of filling the remaining space.\n let shrink = childStyle.flexShrink\n if (childStyle.overflow !== C.OVERFLOW_VISIBLE) shrink = Math.max(shrink, 1)\n if (child.hasMeasureFunc() && childStyle.flexGrow > 0) shrink = Math.max(shrink, 1)\n cflex.flexShrink = shrink\n\n // Store base and main size (start from base size - distribution happens from here)\n cflex.baseSize = baseSize\n cflex.mainSize = baseSize\n cflex.frozen = false // Will be set during distribution\n\n // Free space calculation uses BASE sizes (per Yoga/CSS spec algorithm)\n // The freeze loop handles min/max clamping iteratively\n totalBaseMain += baseSize + cflex.mainMargin\n\n // Count auto margins for later distribution\n if (cflex.mainStartMarginAuto) totalAutoMargins++\n if (cflex.mainEndMarginAuto) totalAutoMargins++\n\n // Check for baseline alignment\n if (!hasBaselineAlignment && childStyle.alignSelf === C.ALIGN_BASELINE) {\n hasBaselineAlignment = true\n }\n }\n\n log.debug?.(\"layoutNode: node.children=%d, relativeCount=%d\", node.children.length, relativeCount)\n if (relativeCount > 0) {\n // -----------------------------------------------------------------------\n // PHASE 6a: Flex Line Breaking and Space Distribution\n // -----------------------------------------------------------------------\n // Break children into lines (for flex-wrap).\n // Distribute free space using grow/shrink factors.\n // Apply min/max constraints.\n\n // Break children into flex lines for wrap support (zero allocation - sets child.flex.lineIndex)\n const numLines = breakIntoLines(node, relativeCount, mainAxisSize, mainGap, style.flexWrap)\n const crossGap = isRow ? style.gap[1] : style.gap[0]\n\n // Process each line: distribute flex space\n // Uses pre-collected _lineChildren to avoid O(n*m) iteration\n for (let lineIdx = 0; lineIdx < numLines; lineIdx++) {\n const lineChildren = _lineChildren[lineIdx]!\n const lineLength = lineChildren.length\n if (lineLength === 0) continue\n\n // Calculate total base main and gaps for this line\n let lineTotalBaseMain = 0\n for (let i = 0; i < lineLength; i++) {\n const c = lineChildren[i]!\n lineTotalBaseMain += c.flex.baseSize + c.flex.mainMargin\n }\n const lineTotalGaps = lineLength > 1 ? mainGap * (lineLength - 1) : 0\n\n // Distribute free space using grow or shrink factors\n let effectiveMainSize = mainAxisSize\n if (Number.isNaN(mainAxisSize)) {\n // Shrink-wrap mode - check if max constraint applies\n const maxMainVal = isRow ? style.maxWidth : style.maxHeight\n if (maxMainVal.unit !== C.UNIT_UNDEFINED) {\n const maxMain = resolveValue(maxMainVal, isRow ? availableWidth : availableHeight)\n if (!Number.isNaN(maxMain) && lineTotalBaseMain + lineTotalGaps > maxMain) {\n const innerMain = isRow ? innerLeft + innerRight : innerTop + innerBottom\n effectiveMainSize = maxMain - innerMain\n }\n }\n }\n\n if (!Number.isNaN(effectiveMainSize)) {\n const adjustedFreeSpace = effectiveMainSize - lineTotalBaseMain - lineTotalGaps\n distributeFlexSpaceForLine(lineChildren, adjustedFreeSpace)\n }\n\n // Apply min/max constraints to final sizes\n for (let i = 0; i < lineLength; i++) {\n const f = lineChildren[i]!.flex\n f.mainSize = Math.max(f.minMain, Math.min(f.maxMain, f.mainSize))\n }\n }\n\n // -----------------------------------------------------------------------\n // PHASE 6b: Justify-Content and Auto Margins (Per-Line)\n // -----------------------------------------------------------------------\n // Distribute remaining free space on main axis PER LINE.\n // Auto margins absorb space first, then justify-content applies.\n // This fixes multi-line wrap layouts to match CSS spec behavior.\n\n // Compute per-line justify-content and auto margins\n for (let lineIdx = 0; lineIdx < numLines; lineIdx++) {\n const lineChildren = _lineChildren[lineIdx]!\n const lineLength = lineChildren.length\n if (lineLength === 0) {\n _lineJustifyStarts[lineIdx] = 0\n _lineItemSpacings[lineIdx] = mainGap\n continue\n }\n\n // Calculate used main axis space for this line\n let lineUsedMain = 0\n let lineAutoMargins = 0\n for (let i = 0; i < lineLength; i++) {\n const c = lineChildren[i]!\n lineUsedMain += c.flex.mainSize + c.flex.mainMargin\n if (c.flex.mainStartMarginAuto) lineAutoMargins++\n if (c.flex.mainEndMarginAuto) lineAutoMargins++\n }\n const lineGaps = lineLength > 1 ? mainGap * (lineLength - 1) : 0\n lineUsedMain += lineGaps\n\n // For auto-sized containers (NaN mainAxisSize), there's no remaining space to justify\n const lineRemainingSpace = Number.isNaN(mainAxisSize) ? 0 : mainAxisSize - lineUsedMain\n\n // Handle auto margins on main axis (per-line)\n // Auto margins absorb free space BEFORE justify-content\n const lineHasAutoMargins = lineAutoMargins > 0\n\n if (lineHasAutoMargins) {\n // Auto margins absorb remaining space for this line\n // CSS spec: auto margins don't absorb negative free space (overflow case)\n const positiveRemaining = Math.max(0, lineRemainingSpace)\n const autoMarginValue = positiveRemaining / lineAutoMargins\n for (let i = 0; i < lineLength; i++) {\n const child = lineChildren[i]!\n if (child.flex.mainStartMarginAuto) {\n child.flex.mainStartMarginValue = autoMarginValue\n }\n if (child.flex.mainEndMarginAuto) {\n child.flex.mainEndMarginValue = autoMarginValue\n }\n }\n }\n\n // Calculate justify-content offset and spacing for this line\n let lineStartOffset = 0\n let lineItemSpacing = mainGap\n\n // justify-content is ignored when any auto margins exist on this line\n if (!lineHasAutoMargins) {\n // CSS spec behavior for overflow (negative remaining space):\n // - flex-end/center: allow negative offset (items can overflow at start)\n // - space-between/around/evenly: fall back to flex-start (no negative spacing)\n switch (style.justifyContent) {\n case C.JUSTIFY_FLEX_END:\n // Allow negative offset for overflow (matches Yoga/CSS behavior)\n lineStartOffset = lineRemainingSpace\n break\n case C.JUSTIFY_CENTER:\n // Allow negative offset for overflow (matches Yoga/CSS behavior)\n lineStartOffset = lineRemainingSpace / 2\n break\n case C.JUSTIFY_SPACE_BETWEEN:\n // Only apply space-between when remaining space is positive\n if (lineLength > 1 && lineRemainingSpace > 0) {\n lineItemSpacing = mainGap + lineRemainingSpace / (lineLength - 1)\n }\n break\n case C.JUSTIFY_SPACE_AROUND:\n // Only apply space-around when remaining space is positive\n if (lineLength > 0 && lineRemainingSpace > 0) {\n const extraSpace = lineRemainingSpace / lineLength\n lineStartOffset = extraSpace / 2\n lineItemSpacing = mainGap + extraSpace\n }\n break\n case C.JUSTIFY_SPACE_EVENLY:\n // Only apply space-evenly when remaining space is positive\n if (lineLength > 0 && lineRemainingSpace > 0) {\n const extraSpace = lineRemainingSpace / (lineLength + 1)\n lineStartOffset = extraSpace\n lineItemSpacing = mainGap + extraSpace\n }\n break\n }\n }\n\n _lineJustifyStarts[lineIdx] = lineStartOffset\n _lineItemSpacings[lineIdx] = lineItemSpacing\n }\n\n // For backwards compatibility, set global values for single-line case\n const startOffset = _lineJustifyStarts[0]\n const itemSpacing = _lineItemSpacings[0]\n\n // NOTE: We do NOT round sizes here. Instead, we use edge-based rounding below.\n // This ensures adjacent elements share exact boundaries without gaps.\n // The key insight: round(pos) gives the edge position, width = round(end) - round(start)\n\n // -----------------------------------------------------------------------\n // PHASE 6c: Baseline Alignment (Pre-computation)\n // -----------------------------------------------------------------------\n // For align-items: baseline, compute each child's baseline and find max.\n // Uses baselineFunc if provided, otherwise falls back to content box bottom.\n\n // Compute baseline alignment info if needed (hasBaselineAlignment computed in flex info pass)\n // For ALIGN_BASELINE in row direction, we need to know the max baseline first\n // Zero-alloc: store baseline in child.flex.baseline, not a temporary array\n let maxBaseline = 0\n // baselineZoneHeight: the effective cross-axis size that non-baseline children\n // align within when baseline alignment is present. This is max(maxBaseline, maxChildHeight).\n // Only meaningful when alignItems != ALIGN_BASELINE but some children have alignSelf=baseline.\n let baselineZoneHeight = 0\n const alignItemsIsBaseline = style.alignItems === C.ALIGN_BASELINE\n\n if (hasBaselineAlignment && isRow) {\n // First pass: compute each child's baseline and find the maximum\n let maxChildHeight = 0\n for (const child of node.children) {\n if (child.flex.relativeIndex < 0) continue\n const childStyle = child.style\n\n // Get cross-axis (top) margin for this child - use cached value\n const topMargin = child.flex.marginT\n\n // Compute child's dimensions - need to do a mini-layout or use the cached size\n // For children with explicit dimensions, use those\n // For auto-sized children, we need to layout them first\n let childWidth: number\n let childHeight: number\n const widthDim = childStyle.width\n const heightDim = childStyle.height\n\n // Get width for baseline function\n if (widthDim.unit === C.UNIT_POINT) {\n childWidth = widthDim.value\n } else if (widthDim.unit === C.UNIT_PERCENT && !Number.isNaN(mainAxisSize)) {\n childWidth = mainAxisSize * (widthDim.value / 100)\n } else {\n childWidth = child.flex.mainSize\n }\n\n // Get height for baseline\n if (heightDim.unit === C.UNIT_POINT) {\n childHeight = heightDim.value\n } else if (heightDim.unit === C.UNIT_PERCENT && !Number.isNaN(crossAxisSize)) {\n childHeight = crossAxisSize * (heightDim.value / 100)\n } else {\n // Auto height - need to layout to get intrinsic size\n // Check cache first to avoid redundant recursive calls\n const cached = child.getCachedLayout(child.flex.mainSize, NaN)\n if (cached) {\n incLayoutCacheHits()\n _t?.cacheHit(_tn, child.flex.mainSize, NaN, cached.width, cached.height)\n childWidth = cached.width\n childHeight = cached.height\n } else {\n _t?.cacheMiss(_tn, child.flex.mainSize, NaN)\n // Use measureNode for sizing-only pass (faster than full layoutNode)\n // Save layout before measureNode — it overwrites node.layout.width/height\n // with intrinsic measurements. Without save/restore, layoutNode's fingerprint\n // check in Phase 9 would skip re-computation and preserve corrupted values.\n const savedW = child.layout.width\n const savedH = child.layout.height\n measureNode(child, child.flex.mainSize, NaN, direction)\n childWidth = child.layout.width\n childHeight = child.layout.height\n child.layout.width = savedW\n child.layout.height = savedH\n _t?.measureSaveRestore(_tn, savedW, savedH, childWidth, childHeight)\n child.setCachedLayout(child.flex.mainSize, NaN, childWidth, childHeight)\n }\n }\n\n // Compute baseline: use baselineFunc if available, otherwise use bottom of content box\n // Store directly in child.flex.baseline (zero-alloc)\n if (child.baselineFunc !== null) {\n // Custom baseline function provided (e.g., for text nodes)\n child.flex.baseline = topMargin + child.baselineFunc(childWidth, childHeight)\n } else {\n // Fallback: bottom of content box (default for non-text elements)\n // Note: We don't recursively propagate first-child baselines to avoid O(n^depth) cost\n // This is a simplification from CSS spec but acceptable for TUI use cases\n child.flex.baseline = topMargin + childHeight\n }\n\n // Track max child height (including margin) for baseline zone calculation\n maxChildHeight = Math.max(maxChildHeight, topMargin + childHeight + child.flex.marginB)\n\n // When alignItems is baseline, ALL children participate in baseline computation.\n // When alignItems is NOT baseline, only children with alignSelf=baseline participate.\n // This matches Yoga's behavior: non-baseline children are positioned within the\n // \"baseline zone\" (the effective height determined by baseline-aligned children),\n // not the full container cross-axis.\n if (alignItemsIsBaseline || childStyle.alignSelf === C.ALIGN_BASELINE) {\n maxBaseline = Math.max(maxBaseline, child.flex.baseline)\n }\n }\n\n // Baseline zone height: the max of maxBaseline and the tallest child.\n // Non-baseline children are aligned within this zone, not the full container.\n baselineZoneHeight = Math.max(maxBaseline, maxChildHeight)\n }\n\n // -----------------------------------------------------------------------\n // PHASE 7a: Estimate Flex Line Cross-Axis Sizes (Tentative)\n // -----------------------------------------------------------------------\n // Estimate cross-axis size of each flex line from definite child dimensions.\n // Auto-sized children use 0 here; actual sizes computed during Phase 8.\n // These are tentative values used for alignContent distribution.\n\n // Compute line cross-axis sizes and offsets for flex-wrap\n // Each child already has lineIndex set by breakIntoLines\n // Use pre-allocated _lineCrossOffsets and _lineCrossSizes arrays\n let cumulativeCrossOffset = 0\n const isWrapReverse = style.flexWrap === C.WRAP_WRAP_REVERSE\n\n for (let lineIdx = 0; lineIdx < numLines; lineIdx++) {\n _lineCrossOffsets[lineIdx] = cumulativeCrossOffset\n\n // Calculate max cross size for this line using pre-collected _lineChildren\n const lineChildren = _lineChildren[lineIdx]!\n const lineLength = lineChildren.length\n let maxLineCross = 0\n for (let i = 0; i < lineLength; i++) {\n const child = lineChildren[i]!\n // Estimate child cross size (will be computed more precisely during layout)\n const childStyle = child.style\n const crossDim = isRow ? childStyle.height : childStyle.width\n // Use cached margins\n const crossMarginStart = isRow ? child.flex.marginT : child.flex.marginL\n const crossMarginEnd = isRow ? child.flex.marginB : child.flex.marginR\n\n let childCross = 0\n if (crossDim.unit === C.UNIT_POINT) {\n childCross = crossDim.value\n } else if (crossDim.unit === C.UNIT_PERCENT && !Number.isNaN(crossAxisSize)) {\n childCross = crossAxisSize * (crossDim.value / 100)\n } else if (child.hasMeasureFunc()) {\n // Auto-sized with measureFunc: get tentative cross size from cached measure.\n // Phase 5 already called cachedMeasure, so this is typically a cache hit (no alloc).\n const crossMargin = crossMarginStart + crossMarginEnd\n const availCross = Number.isNaN(crossAxisSize) ? Infinity : crossAxisSize - crossMargin\n // Use child's resolved mainSize (from flex distribution) instead of parent's\n // mainAxisSize. After Phase 6a, child.flex.mainSize may be smaller than\n // mainAxisSize (e.g., due to wrapping). Measuring at parent width would\n // underestimate text wrapping height (fewer lines → shorter cross size).\n const childMainSize = child.flex.mainSize\n const mW = isRow ? childMainSize : availCross\n const mH = isRow ? availCross : childMainSize\n const mWMode = Number.isNaN(mW) ? C.MEASURE_MODE_UNDEFINED : C.MEASURE_MODE_AT_MOST\n const mHMode = Number.isNaN(mH) ? C.MEASURE_MODE_UNDEFINED : C.MEASURE_MODE_AT_MOST\n const measured = child.cachedMeasure(\n Number.isNaN(mW) ? Infinity : mW,\n mWMode,\n Number.isNaN(mH) ? Infinity : mH,\n mHMode,\n )\n if (measured) {\n childCross = isRow ? measured.height : measured.width\n }\n } else if (child.children.length > 0) {\n // Auto-sized container children (no measureFunc, has children):\n // Compute intrinsic cross-axis size by measuring with unconstrained\n // dimensions. This gives the shrink-wrap size, which is what we need\n // for line cross-size estimation. Passing NaN for both axes ensures\n // measureNode returns the content-determined size rather than\n // filling the available space.\n const savedW = child.layout.width\n const savedH = child.layout.height\n measureNode(child, NaN, NaN, direction)\n childCross = isRow ? child.layout.height : child.layout.width\n child.layout.width = savedW\n child.layout.height = savedH\n }\n maxLineCross = Math.max(maxLineCross, childCross + crossMarginStart + crossMarginEnd)\n }\n // Use measured max cross size. If all children are auto-sized (maxLineCross === 0),\n // use 0 — NOT crossAxisSize/numLines, which would consume all free space and\n // prevent alignContent from distributing it. Actual sizes are computed in Phase 8.\n const lineCrossSize = maxLineCross\n _lineCrossSizes[lineIdx] = lineCrossSize\n cumulativeCrossOffset += lineCrossSize + crossGap\n }\n\n // -----------------------------------------------------------------------\n // PHASE 7b: Apply alignContent\n // -----------------------------------------------------------------------\n // Distribute flex lines within the container's cross-axis.\n // Only applies when flex-wrap creates multiple lines.\n\n // Apply alignContent to distribute lines in the cross axis\n // Note: While CSS spec says alignContent only applies to multi-line containers,\n // Yoga applies ALIGN_STRETCH to single-line layouts as well. We match Yoga behavior.\n if (!Number.isNaN(crossAxisSize) && numLines > 0) {\n const totalLineCrossSize = cumulativeCrossOffset - crossGap // Remove trailing gap\n const freeSpace = crossAxisSize - totalLineCrossSize\n const alignContent = style.alignContent\n\n // Apply alignContent offset based on free space.\n // flex-end and center apply with both positive and negative free space.\n // space-between/around/evenly only distribute with positive free space;\n // with negative space they collapse to flex-start or center (CSS spec).\n // stretch only expands lines with positive free space.\n switch (alignContent) {\n case C.ALIGN_FLEX_END:\n // Lines packed at end (works with negative free space too — shifts lines up)\n for (let i = 0; i < numLines; i++) {\n _lineCrossOffsets[i]! += freeSpace\n }\n break\n\n case C.ALIGN_CENTER:\n // Lines centered (works with negative free space — equal overflow both sides)\n {\n const centerOffset = freeSpace / 2\n for (let i = 0; i < numLines; i++) {\n _lineCrossOffsets[i]! += centerOffset\n }\n }\n break\n\n case C.ALIGN_SPACE_BETWEEN:\n // First line at start, last at end, evenly distributed\n // With negative free space: collapses to flex-start (no adjustment)\n if (freeSpace > 0 && numLines > 1) {\n const gap = freeSpace / (numLines - 1)\n for (let i = 1; i < numLines; i++) {\n _lineCrossOffsets[i]! += gap * i\n }\n }\n break\n\n case C.ALIGN_SPACE_AROUND:\n // Even spacing with half-space at edges\n // With negative free space: collapses to center (CSS spec)\n if (freeSpace > 0) {\n const halfGap = freeSpace / (numLines * 2)\n for (let i = 0; i < numLines; i++) {\n _lineCrossOffsets[i]! += halfGap + halfGap * 2 * i\n }\n } else {\n // Negative space: center fallback\n const centerOffset = freeSpace / 2\n for (let i = 0; i < numLines; i++) {\n _lineCrossOffsets[i]! += centerOffset\n }\n }\n break\n\n case C.ALIGN_SPACE_EVENLY:\n // Equal spacing between lines and at edges\n // With negative free space: collapses to center (CSS spec)\n if (freeSpace > 0 && numLines > 0) {\n const gap = freeSpace / (numLines + 1)\n for (let i = 0; i < numLines; i++) {\n _lineCrossOffsets[i]! += gap * (i + 1)\n }\n } else if (freeSpace < 0) {\n // Negative space: center fallback\n const centerOffset = freeSpace / 2\n for (let i = 0; i < numLines; i++) {\n _lineCrossOffsets[i]! += centerOffset\n }\n }\n break\n\n case C.ALIGN_STRETCH:\n // Distribute extra space evenly among lines (only with positive free space)\n if (freeSpace > 0 && numLines > 0) {\n const extraPerLine = freeSpace / numLines\n for (let i = 0; i < numLines; i++) {\n _lineCrossSizes[i]! += extraPerLine\n // Recalculate offset for subsequent lines\n if (i > 0) {\n _lineCrossOffsets[i] = _lineCrossOffsets[i - 1]! + _lineCrossSizes[i - 1]! + crossGap\n }\n }\n }\n break\n\n // ALIGN_FLEX_START is the default - lines already at start\n }\n\n // For wrap-reverse, lines should be positioned from the end of the cross axis\n // The lines are already in reversed order from breakIntoLines().\n // We just need to shift them so they align to the end instead of the start.\n if (isWrapReverse) {\n let totalLineCrossSize = 0\n for (let i = 0; i < numLines; i++) {\n totalLineCrossSize += _lineCrossSizes[i]!\n }\n totalLineCrossSize += crossGap * (numLines - 1)\n const crossStartOffset = crossAxisSize - totalLineCrossSize\n for (let i = 0; i < numLines; i++) {\n _lineCrossOffsets[i]! += crossStartOffset\n }\n }\n }\n\n // Save line data before Phase 8: recursive layoutNode calls for children\n // with sub-children overwrite the global pre-allocated _lineCrossSizes,\n // _lineCrossOffsets, _lineJustifyStarts, and _lineItemSpacings arrays.\n // For multi-line layouts, we copy the values into small local arrays.\n // This allocation is rare (only for multi-line wrapping containers) and\n // tiny (4 arrays x numLines x 8 bytes).\n let savedLineCrossSizes: Float64Array | null = null\n let savedLineCrossOffsets: Float64Array | null = null\n let savedLineJustifyStarts: Float64Array | null = null\n let savedLineItemSpacings: Float64Array | null = null\n if (numLines > 1) {\n savedLineCrossSizes = new Float64Array(numLines)\n savedLineCrossOffsets = new Float64Array(numLines)\n savedLineJustifyStarts = new Float64Array(numLines)\n savedLineItemSpacings = new Float64Array(numLines)\n for (let i = 0; i < numLines; i++) {\n savedLineCrossSizes[i] = _lineCrossSizes[i]!\n savedLineCrossOffsets[i] = _lineCrossOffsets[i]!\n savedLineJustifyStarts[i] = _lineJustifyStarts[i]!\n savedLineItemSpacings[i] = _lineItemSpacings[i]!\n }\n }\n\n // -----------------------------------------------------------------------\n // PHASE 8: Position and Layout Children\n // -----------------------------------------------------------------------\n // Calculate each child's position in the container.\n // Apply cross-axis alignment (align-items, align-self).\n // Recursively layout grandchildren.\n\n // Position and layout children\n // For reverse directions (including RTL for row), start from the END of the container\n // RTL + reverse cancels out (XOR behavior)\n // For shrink-wrap containers, compute effective main size first\n let effectiveMainAxisSize = mainAxisSize\n const mainIsAuto = isRow\n ? style.width.unit !== C.UNIT_POINT && style.width.unit !== C.UNIT_PERCENT\n : style.height.unit !== C.UNIT_POINT && style.height.unit !== C.UNIT_PERCENT\n\n // Calculate total gaps for all children (used for shrink-wrap sizing)\n const totalGaps = relativeCount > 1 ? mainGap * (relativeCount - 1) : 0\n\n if (effectiveReverse && mainIsAuto) {\n // For reverse with auto size, compute total content size for positioning\n let totalContent = 0\n for (const child of node.children) {\n if (child.flex.relativeIndex < 0) continue\n totalContent += child.flex.mainSize + child.flex.mainStartMarginValue + child.flex.mainEndMarginValue\n }\n totalContent += totalGaps\n effectiveMainAxisSize = totalContent\n }\n\n // Use fractional mainPos for edge-based rounding\n // Initialize with first line's startOffset (may be overridden when processing lines)\n let mainPos = effectiveReverse ? effectiveMainAxisSize - startOffset! : startOffset!\n let currentLineIdx = -1\n let relIdx = 0 // Track relative child index globally\n let lineChildIdx = 0 // Track position within current line (for gap handling)\n let currentLineLength = 0 // Length of current line\n let currentItemSpacing = itemSpacing // Track current line's item spacing\n\n log.debug?.(\n \"positioning children: isRow=%s, startOffset=%d, relativeCount=%d, effectiveReverse=%s, numLines=%d\",\n isRow,\n startOffset,\n relativeCount,\n effectiveReverse,\n numLines,\n )\n\n for (const child of node.children) {\n if (child.flex.relativeIndex < 0) continue\n const cflex = child.flex\n const childStyle = child.style\n\n // Check if we've moved to a new line (for flex-wrap)\n const childLineIdx = cflex.lineIndex\n if (childLineIdx !== currentLineIdx) {\n currentLineIdx = childLineIdx\n lineChildIdx = 0 // Reset position within line\n currentLineLength = _lineChildren[childLineIdx]!.length\n // Reset mainPos for new line using line-specific justify offset\n // Use saved arrays for multi-line to avoid corruption by recursive layoutNode\n const lineOffset = savedLineJustifyStarts\n ? savedLineJustifyStarts[childLineIdx]!\n : _lineJustifyStarts[childLineIdx]!\n currentItemSpacing = savedLineItemSpacings\n ? savedLineItemSpacings[childLineIdx]!\n : _lineItemSpacings[childLineIdx]!\n mainPos = effectiveReverse ? effectiveMainAxisSize - lineOffset : lineOffset\n }\n\n // Get cross-axis offset for this child's line\n // Use saved arrays for multi-line to avoid corruption by recursive layoutNode\n const lineCrossOffset = savedLineCrossOffsets\n ? savedLineCrossOffsets[childLineIdx]!\n : childLineIdx < MAX_FLEX_LINES\n ? _lineCrossOffsets[childLineIdx]\n : 0\n\n // For main-axis margins, use computed auto margin values\n // For cross-axis margins, use cached values (auto margins on cross axis handled separately)\n let childMarginLeft: number\n let childMarginTop: number\n let childMarginRight: number\n let childMarginBottom: number\n\n // Use cached margins, with auto margin override for main axis\n // For row layouts, use effectiveReverse (accounts for RTL)\n if (isRow) {\n // Row: main axis is horizontal\n // effectiveReverse handles both row-reverse AND RTL\n childMarginLeft =\n cflex.mainStartMarginAuto && !effectiveReverse\n ? cflex.mainStartMarginValue\n : cflex.mainEndMarginAuto && effectiveReverse\n ? cflex.mainEndMarginValue\n : cflex.marginL\n childMarginRight =\n cflex.mainEndMarginAuto && !effectiveReverse\n ? cflex.mainEndMarginValue\n : cflex.mainStartMarginAuto && effectiveReverse\n ? cflex.mainStartMarginValue\n : cflex.marginR\n childMarginTop = cflex.marginT\n childMarginBottom = cflex.marginB\n } else {\n // Column: main axis is vertical (RTL doesn't affect column)\n // In column-reverse, mainStart=bottom(3), mainEnd=top(1)\n childMarginTop =\n cflex.mainStartMarginAuto && !isReverse\n ? cflex.mainStartMarginValue\n : cflex.mainEndMarginAuto && isReverse\n ? cflex.mainEndMarginValue\n : cflex.marginT\n childMarginBottom =\n cflex.mainEndMarginAuto && !isReverse\n ? cflex.mainEndMarginValue\n : cflex.mainStartMarginAuto && isReverse\n ? cflex.mainStartMarginValue\n : cflex.marginB\n childMarginLeft = cflex.marginL\n childMarginRight = cflex.marginR\n }\n\n // Main axis size comes from flex algorithm (already rounded)\n const childMainSize = cflex.mainSize\n\n // Cross axis: determine alignment mode\n let alignment = style.alignItems\n if (childStyle.alignSelf !== C.ALIGN_AUTO) {\n alignment = childStyle.alignSelf\n }\n\n // CSS Alignment spec: aspect-ratio fallback alignment\n // When a flex item has aspect-ratio and auto cross-axis dimension,\n // the fallback alignment is flex-start (not stretch). This prevents\n // stretch from overriding the AR-derived dimension.\n // Only applies when stretch is inherited (align-self: auto), not explicit.\n const childCrossDimForAR = isRow ? childStyle.height : childStyle.width\n const childCrossIsAutoForAR =\n childCrossDimForAR.unit === C.UNIT_AUTO || childCrossDimForAR.unit === C.UNIT_UNDEFINED\n if (\n alignment === C.ALIGN_STRETCH &&\n childStyle.alignSelf === C.ALIGN_AUTO &&\n !Number.isNaN(childStyle.aspectRatio) &&\n childStyle.aspectRatio > 0 &&\n childCrossIsAutoForAR\n ) {\n alignment = C.ALIGN_FLEX_START\n }\n\n // Cross axis size depends on alignment and child's explicit dimensions\n // IMPORTANT: Resolve percent against parent's cross axis, not child's available\n let childCrossSize: number\n const crossDim = isRow ? childStyle.height : childStyle.width\n const crossMargin = isRow ? childMarginTop + childMarginBottom : childMarginLeft + childMarginRight\n\n // Check if parent has definite cross-axis size\n // Parent can have definite cross from either:\n // 1. Explicit style (width/height in points or percent)\n // 2. Definite available space (crossAxisSize is not NaN)\n const parentCrossDim = isRow ? style.height : style.width\n const parentHasDefiniteCrossStyle = parentCrossDim.unit === C.UNIT_POINT || parentCrossDim.unit === C.UNIT_PERCENT\n // crossAxisSize comes from available space - if it's a real number, we have a constraint\n const parentHasDefiniteCross = parentHasDefiniteCrossStyle || !Number.isNaN(crossAxisSize)\n\n if (crossDim.unit === C.UNIT_POINT) {\n // Explicit cross size\n childCrossSize = crossDim.value\n } else if (crossDim.unit === C.UNIT_PERCENT) {\n // Percent of PARENT's cross axis (resolveValue handles NaN -> 0)\n childCrossSize = resolveValue(crossDim, crossAxisSize)\n } else if (parentHasDefiniteCross && alignment === C.ALIGN_STRETCH) {\n // Stretch alignment with definite parent cross size - fill the line's cross axis\n // For wrapping layouts, stretch to line cross size, not full container cross size\n // Use saved arrays for multi-line to avoid corruption by recursive layoutNode\n const lineCross =\n numLines > 1\n ? savedLineCrossSizes\n ? savedLineCrossSizes[childLineIdx]!\n : _lineCrossSizes[childLineIdx]!\n : crossAxisSize\n childCrossSize = lineCross - crossMargin\n } else {\n // Non-stretch alignment or no definite cross size - shrink-wrap to content\n childCrossSize = NaN\n }\n\n // Apply cross-axis min/max constraints\n const crossMinVal = isRow ? childStyle.minHeight : childStyle.minWidth\n const crossMaxVal = isRow ? childStyle.maxHeight : childStyle.maxWidth\n const crossMin = crossMinVal.unit !== C.UNIT_UNDEFINED ? resolveValue(crossMinVal, crossAxisSize) : 0\n const crossMax = crossMaxVal.unit !== C.UNIT_UNDEFINED ? resolveValue(crossMaxVal, crossAxisSize) : Infinity\n\n // Apply constraints - for NaN (shrink-wrap), use min as floor\n if (Number.isNaN(childCrossSize)) {\n // For shrink-wrap, min sets the floor - child will be at least this size\n if (crossMin > 0) {\n childCrossSize = crossMin\n }\n } else {\n childCrossSize = Math.max(crossMin, Math.min(crossMax, childCrossSize))\n }\n\n // Handle intrinsic sizing for auto-sized children\n // For auto main size children, use flex-computed size if flexGrow > 0,\n // otherwise pass remaining available space for shrink-wrap behavior\n const mainDim = isRow ? childStyle.width : childStyle.height\n // A child has definite main size if it has explicit width/height OR non-auto flexBasis\n const hasDefiniteFlexBasis =\n childStyle.flexBasis.unit === C.UNIT_POINT || childStyle.flexBasis.unit === C.UNIT_PERCENT\n const mainIsAutoChild =\n (mainDim.unit === C.UNIT_AUTO || mainDim.unit === C.UNIT_UNDEFINED) && !hasDefiniteFlexBasis\n const hasFlexGrow = cflex.flexGrow > 0\n // Use flex-computed mainSize for all cases - it includes padding/border as minimum\n // The flex algorithm already computed the proper size based on content/padding/border\n const effectiveMainSize = childMainSize\n\n let childWidth = isRow ? effectiveMainSize : childCrossSize\n let childHeight = isRow ? childCrossSize : effectiveMainSize\n\n // Only use measure function for intrinsic sizing when flexGrow is NOT set\n // When flexGrow > 0, the flex algorithm determines size, not the content\n const shouldMeasure = child.hasMeasureFunc() && child.children.length === 0 && !hasFlexGrow\n if (shouldMeasure) {\n const widthAuto = childStyle.width.unit === C.UNIT_AUTO || childStyle.width.unit === C.UNIT_UNDEFINED\n const heightAuto = childStyle.height.unit === C.UNIT_AUTO || childStyle.height.unit === C.UNIT_UNDEFINED\n\n if (widthAuto || heightAuto) {\n // Call measure function with available space\n const widthMode = widthAuto ? C.MEASURE_MODE_AT_MOST : C.MEASURE_MODE_EXACTLY\n const heightMode = heightAuto ? C.MEASURE_MODE_UNDEFINED : C.MEASURE_MODE_EXACTLY\n\n // For unconstrained dimensions (NaN), use Infinity for measure func\n const rawAvailW = widthAuto\n ? isRow\n ? mainAxisSize - mainPos! // Remaining space after previous children\n : crossAxisSize - crossMargin\n : childStyle.width.value\n const rawAvailH = heightAuto\n ? isRow\n ? crossAxisSize - crossMargin\n : mainAxisSize - mainPos! // Remaining space for COLUMN\n : childStyle.height.value\n const availW = Number.isNaN(rawAvailW) ? Infinity : rawAvailW\n const availH = Number.isNaN(rawAvailH) ? Infinity : rawAvailH\n\n // Use cached measure to avoid redundant calls within a layout pass\n const measured = child.cachedMeasure(availW, widthMode, availH, heightMode)!\n\n // For measure function nodes without flexGrow, intrinsic size takes precedence\n if (widthAuto) {\n childWidth = measured.width\n }\n if (heightAuto) {\n childHeight = measured.height\n }\n }\n }\n\n // Child position within content area (fractional for edge-based rounding)\n // For reverse directions (including RTL for row), position from mainPos - childSize\n // IMPORTANT: In reverse, swap which margin is applied to which side\n // For RTL row: items flow right-to-left, so right margin becomes trailing\n // For flex-wrap, add lineCrossOffset to cross-axis position\n let childX: number\n let childY: number\n if (effectiveReverse) {\n if (isRow) {\n // Row-reverse or RTL: items positioned from right\n // In RTL/reverse, use right margin as trailing margin\n childX = mainPos! - childMainSize - childMarginRight\n childY = lineCrossOffset! + childMarginTop\n } else {\n // Column-reverse: items positioned from bottom\n childX = lineCrossOffset! + childMarginLeft\n childY = mainPos! - childMainSize - childMarginTop\n }\n } else {\n childX = isRow ? mainPos! + childMarginLeft : lineCrossOffset! + childMarginLeft\n childY = isRow ? lineCrossOffset! + childMarginTop : mainPos! + childMarginTop\n }\n\n // Edge-based rounding using ABSOLUTE coordinates (Yoga-compatible)\n // This ensures adjacent elements share exact boundaries without gaps\n // Key insight: round absolute edges, derive sizes from differences\n const fractionalLeft = innerLeft + childX\n const fractionalTop = innerTop + childY\n\n // Compute position offsets for RELATIVE positioned children\n // CSS spec: position:static ignores insets; only position:relative applies them.\n // These must be included in the absolute position BEFORE rounding (Yoga-compatible)\n let posOffsetX = 0\n let posOffsetY = 0\n if (childStyle.positionType === C.POSITION_TYPE_RELATIVE) {\n // Resolve logical EDGE_START/EDGE_END to physical left/right based on direction\n const relLeftPos = resolvePositionEdge(childStyle.position, 0, direction)\n const relTopPos = childStyle.position[1]\n const relRightPos = resolvePositionEdge(childStyle.position, 2, direction)\n const relBottomPos = childStyle.position[3]\n\n // Left offset (takes precedence over right)\n if (relLeftPos.unit !== C.UNIT_UNDEFINED) {\n posOffsetX = resolveValue(relLeftPos, contentWidth)\n } else if (relRightPos.unit !== C.UNIT_UNDEFINED) {\n posOffsetX = -resolveValue(relRightPos, contentWidth)\n }\n\n // Top offset (takes precedence over bottom)\n if (relTopPos.unit !== C.UNIT_UNDEFINED) {\n posOffsetY = resolveValue(relTopPos, contentHeight)\n } else if (relBottomPos.unit !== C.UNIT_UNDEFINED) {\n posOffsetY = -resolveValue(relBottomPos, contentHeight)\n }\n }\n\n // Compute ABSOLUTE float positions for edge rounding (including position offsets)\n // absX/absY are the parent's absolute position from document root\n // Include BOTH parent's position offset and child's position offset\n const absChildLeft = absX + marginLeft + parentPosOffsetX + fractionalLeft + posOffsetX\n const absChildTop = absY + marginTop + parentPosOffsetY + fractionalTop + posOffsetY\n\n // For main axis: round ABSOLUTE edges and derive size\n // Only use edge-based rounding when childMainSize is valid (positive)\n let roundedAbsMainStart: number\n let roundedAbsMainEnd: number\n let edgeBasedMainSize: number\n const useEdgeBasedRounding = childMainSize > 0\n\n // Compute child's box model minimum early (needed for edge-based rounding)\n // Use resolveEdgeValue to respect logical EDGE_START/END for padding\n const childPaddingL = resolveEdgeValue(childStyle.padding, 0, childStyle.flexDirection, contentWidth, direction)\n const childPaddingT = resolveEdgeValue(childStyle.padding, 1, childStyle.flexDirection, contentWidth, direction)\n const childPaddingR = resolveEdgeValue(childStyle.padding, 2, childStyle.flexDirection, contentWidth, direction)\n const childPaddingB = resolveEdgeValue(childStyle.padding, 3, childStyle.flexDirection, contentWidth, direction)\n const childBorderL = resolveEdgeBorderValue(childStyle.border, 0, childStyle.flexDirection, direction)\n const childBorderT = resolveEdgeBorderValue(childStyle.border, 1, childStyle.flexDirection, direction)\n const childBorderR = resolveEdgeBorderValue(childStyle.border, 2, childStyle.flexDirection, direction)\n const childBorderB = resolveEdgeBorderValue(childStyle.border, 3, childStyle.flexDirection, direction)\n const childMinW = childPaddingL + childPaddingR + childBorderL + childBorderR\n const childMinH = childPaddingT + childPaddingB + childBorderT + childBorderB\n const childMinMain = isRow ? childMinW : childMinH\n\n // Apply box model constraint to childMainSize before edge rounding\n const constrainedMainSize = Math.max(childMainSize, childMinMain)\n\n if (useEdgeBasedRounding) {\n if (isRow) {\n roundedAbsMainStart = Math.round(absChildLeft)\n roundedAbsMainEnd = Math.round(absChildLeft + constrainedMainSize)\n edgeBasedMainSize = roundedAbsMainEnd - roundedAbsMainStart\n } else {\n roundedAbsMainStart = Math.round(absChildTop)\n roundedAbsMainEnd = Math.round(absChildTop + constrainedMainSize)\n edgeBasedMainSize = roundedAbsMainEnd - roundedAbsMainStart\n }\n } else {\n // For children without valid main size, use simple rounding\n roundedAbsMainStart = isRow ? Math.round(absChildLeft) : Math.round(absChildTop)\n edgeBasedMainSize = childMinMain // Use minimum size instead of 0\n }\n\n // Calculate child's RELATIVE position (stored in layout)\n // Yoga behavior: position is rounded locally, size uses absolute edge rounding\n // This ensures sizes are pixel-perfect at document level while positions remain intuitive\n // Yoga 3.x quirk: measureFunc leaf nodes use Math.floor for position rounding,\n // while explicit-sized children use Math.round. This affects any justify/align mode\n // that produces fractional offsets (center, space-around, space-evenly).\n const posRound = shouldMeasure ? Math.floor : Math.round\n const childLeft = posRound(fractionalLeft + posOffsetX)\n const childTop = posRound(fractionalTop + posOffsetY)\n\n // Check if cross axis is auto-sized (needed for deciding what to pass to layoutNode)\n const crossDimForLayoutCall = isRow ? childStyle.height : childStyle.width\n const crossIsAutoForLayoutCall =\n crossDimForLayoutCall.unit === C.UNIT_AUTO || crossDimForLayoutCall.unit === C.UNIT_UNDEFINED\n const mainDimForLayoutCall = isRow ? childStyle.width : childStyle.height\n const mainIsPercentForLayoutCall = mainDimForLayoutCall.unit === C.UNIT_PERCENT\n const crossIsPercentForLayoutCall = crossDimForLayoutCall.unit === C.UNIT_PERCENT\n\n // For auto-sized children (no flexGrow, no measureFunc), pass NaN to let them compute intrinsic size\n // Otherwise layoutNode would subtract margins from the available size\n // IMPORTANT: For percent-sized children, pass parent's content size (not child's computed size)\n // so that grandchildren's percents resolve correctly against the child's actual dimensions.\n // The child will resolve its own percent against this value, getting the same result the parent computed.\n //\n // CRITICAL: When flex distribution changed the child's size (shrinkage/growth applied),\n // pass the actual childWidth instead of NaN. This ensures layoutNode's fingerprint check\n // detects the change — otherwise NaN===NaN matches across passes with different flex\n // distributions, preserving stale overridden dimensions from the previous pass.\n //\n // CRITICAL: Measure-func leaf nodes (text) must receive the actual constraint, not NaN.\n // Their cross-axis size (e.g. height in a row) depends on the main-axis constraint\n // (e.g. text wrapping width). Passing NaN causes them to measure unconstrained,\n // producing height=1 instead of the correct wrapped height. The parent's Phase 8\n // shouldMeasure path computes the correct childWidth/childHeight, but layoutNode\n // would recompute with NaN and get a different result.\n const flexDistChanged = child.flex.mainSize !== child.flex.baseSize\n const hasMeasureLeaf = child.hasMeasureFunc() && child.children.length === 0\n const passWidthToChild =\n isRow && mainIsAutoChild && !hasFlexGrow && !flexDistChanged && !hasMeasureLeaf\n ? NaN\n : !isRow && crossIsAutoForLayoutCall && !parentHasDefiniteCross\n ? NaN\n : isRow && mainIsPercentForLayoutCall\n ? mainAxisSize\n : !isRow && crossIsPercentForLayoutCall\n ? crossAxisSize\n : childWidth\n const passHeightToChild =\n !isRow && mainIsAutoChild && !hasFlexGrow && !flexDistChanged && !hasMeasureLeaf\n ? NaN\n : isRow && crossIsAutoForLayoutCall && !parentHasDefiniteCross\n ? NaN\n : !isRow && mainIsPercentForLayoutCall\n ? mainAxisSize\n : isRow && crossIsPercentForLayoutCall\n ? crossAxisSize\n : childHeight\n\n // Recurse to layout any grandchildren\n // Pass the child's FLOAT absolute position (margin box start, before child's own margin)\n // absChildLeft/Top include the child's margins, so subtract them to get margin box start\n const childAbsX = absChildLeft - childMarginLeft\n const childAbsY = absChildTop - childMarginTop\n layoutNode(child, passWidthToChild, passHeightToChild, childLeft, childTop, childAbsX, childAbsY, direction)\n\n // Enforce box model constraint: child can't be smaller than its padding + border\n // (using childMinW/childMinH computed earlier for edge-based rounding)\n if (childWidth < childMinW) childWidth = childMinW\n if (childHeight < childMinH) childHeight = childMinH\n\n // Set this child's layout - override what layoutNode computed\n // Override if any of:\n // - Child has explicit main dimension AND parent has explicit main dimension (edge-based rounding)\n // - Child has flexGrow > 0 (flex distribution applied)\n // - Child has measureFunc (leaf text node)\n // - Flex distribution actually changed the size (grow or shrink)\n //\n // IMPORTANT: Don't override auto-sized containers when flex distribution\n // didn't change their size. The pre-measurement (Phase 5) computes intrinsic\n // size at unconstrained main axis, but layoutNode recomputes with actual\n // cross-axis constraints. For containers with children that wrap text,\n // layoutNode's result is correct because it accounts for the actual width\n // after flex distribution of grandchildren. The Phase 5 measureNode pass\n // measures row children with NaN main width, so text doesn't wrap —\n // producing height=1 instead of the correct wrapped height.\n const hasMeasure = child.hasMeasureFunc() && child.children.length === 0\n const flexDistributionChangedSize = child.flex.mainSize !== child.flex.baseSize\n if ((!mainIsAuto && !mainIsAutoChild) || hasFlexGrow || hasMeasure || flexDistributionChangedSize) {\n // Use edge-based rounding: size = round(end_edge) - round(start_edge)\n if (isRow) {\n _t?.parentOverride(_tn, \"main\", child.layout.width, edgeBasedMainSize)\n child.layout.width = edgeBasedMainSize\n } else {\n _t?.parentOverride(_tn, \"main\", child.layout.height, edgeBasedMainSize)\n child.layout.height = edgeBasedMainSize\n }\n }\n // Cross axis: only override for explicit sizing or when we have a real constraint\n // For auto-sized children, let layoutNode determine the size\n const crossDimForCheck = isRow ? childStyle.height : childStyle.width\n const crossIsAuto = crossDimForCheck.unit === C.UNIT_AUTO || crossDimForCheck.unit === C.UNIT_UNDEFINED\n // Only override if child has explicit sizing OR parent has explicit cross size\n // When parent has auto cross size, let children shrink-wrap first\n // Note: parentCrossDim and parentHasDefiniteCross already computed above\n const parentCrossIsAuto = !parentHasDefiniteCross\n // Also check if childCrossSize was constrained by min/max - if so, we should override\n const hasCrossMinMax = crossMinVal.unit !== C.UNIT_UNDEFINED || crossMaxVal.unit !== C.UNIT_UNDEFINED\n const shouldOverrideCross =\n !crossIsAuto ||\n (!parentCrossIsAuto && alignment === C.ALIGN_STRETCH) ||\n (hasCrossMinMax && !Number.isNaN(childCrossSize))\n if (shouldOverrideCross) {\n if (isRow) {\n child.layout.height = Math.round(childHeight)\n } else {\n child.layout.width = Math.round(childWidth)\n }\n }\n // Store RELATIVE position (within parent's content area), not absolute\n // This matches Yoga's behavior where getComputedLeft/Top return relative positions\n // Position offsets are already included in childLeft/childTop via edge-based rounding\n child.layout.left = childLeft\n child.layout.top = childTop\n\n // Update childWidth/childHeight to match actual computed layout for mainPos calculation\n childWidth = child.layout.width\n childHeight = child.layout.height\n\n // Apply cross-axis alignment offset\n const finalCrossSize = isRow ? child.layout.height : child.layout.width\n let crossOffset = 0\n\n // Check for auto margins on cross axis - they override alignment\n // Use isEdgeAuto to correctly respect logical EDGE_START/END margins\n const crossStartIndex = isRow ? 1 : 0 // top for row, left for column\n const crossEndIndex = isRow ? 3 : 2 // bottom for row, right for column\n const hasAutoStartMargin = isEdgeAuto(childStyle.margin, crossStartIndex, style.flexDirection, direction)\n const hasAutoEndMargin = isEdgeAuto(childStyle.margin, crossEndIndex, style.flexDirection, direction)\n // When baseline alignment is present (hasBaselineAlignment) and this child is NOT using\n // baseline alignment, align within the baseline zone instead of the full container.\n // Yoga behavior: non-baseline children are positioned relative to the effective height\n // of the baseline group (max of maxBaseline and tallest child), not the container.\n const useBaselineZone =\n hasBaselineAlignment &&\n isRow &&\n !alignItemsIsBaseline &&\n alignment !== C.ALIGN_BASELINE &&\n baselineZoneHeight > 0\n const effectiveCrossSize = useBaselineZone ? baselineZoneHeight : crossAxisSize\n const availableCrossSpace = effectiveCrossSize - finalCrossSize - crossMargin\n\n if (hasAutoStartMargin && hasAutoEndMargin) {\n // Both auto: center the item\n // CSS spec: auto margins don't absorb negative free space (clamp to 0)\n crossOffset = Math.max(0, availableCrossSpace) / 2\n } else if (hasAutoStartMargin) {\n // Auto start margin: push to end\n // CSS spec: auto margins don't absorb negative free space (clamp to 0)\n crossOffset = Math.max(0, availableCrossSpace)\n } else if (hasAutoEndMargin) {\n // Auto end margin: stay at start (crossOffset = 0)\n crossOffset = 0\n } else {\n // No auto margins: use alignment\n switch (alignment) {\n case C.ALIGN_FLEX_END:\n crossOffset = availableCrossSpace\n break\n case C.ALIGN_CENTER:\n crossOffset = availableCrossSpace / 2\n break\n case C.ALIGN_BASELINE:\n // Baseline alignment only applies to row direction\n // For column direction, it falls through to flex-start (default)\n if (isRow && hasBaselineAlignment) {\n // Use pre-computed baseline from Phase 6c (stored in child.flex.baseline)\n crossOffset = maxBaseline - child.flex.baseline\n }\n break\n }\n }\n\n if (crossOffset !== 0) {\n // Yoga 3.x quirk: measureFunc leaf nodes use Math.floor for cross-axis alignment\n // offset, matching the main-axis floor rounding behavior\n const crossRound = shouldMeasure ? Math.floor : Math.round\n if (isRow) {\n child.layout.top += crossRound(crossOffset)\n } else {\n child.layout.left += crossRound(crossOffset)\n }\n }\n\n // Position advancement: use the right size depending on Phase 8 behavior.\n // - Phase 8 overrode (explicit size, flexGrow, measure, or flex distribution changed):\n // Use constrainedMainSize (float) for precise gap/position calculations.\n // child.layout is edge-rounded (integer), which causes rounding drift in gaps.\n // - Phase 8 did NOT override (auto-sized container, no grow, no measure):\n // Use child.layout (from layoutNode), which reflects actual content size.\n // constrainedMainSize is a stale pre-layout estimate from unconstrained measurement.\n const phaseEightOverrode =\n (!mainIsAuto && !mainIsAutoChild) || hasFlexGrow || hasMeasure || flexDistributionChangedSize\n const fractionalMainSize = phaseEightOverrode\n ? constrainedMainSize\n : isRow\n ? child.layout.width\n : child.layout.height\n // Use computed margin values (including auto margins)\n const totalMainMargin = cflex.mainStartMarginValue + cflex.mainEndMarginValue\n log.debug?.(\n \" child %d: mainPos=%d -> top=%d (fractionalMainSize=%d, totalMainMargin=%d)\",\n relIdx,\n mainPos,\n child.layout.top,\n fractionalMainSize,\n totalMainMargin,\n )\n if (effectiveReverse) {\n mainPos! -= fractionalMainSize + totalMainMargin\n // Add spacing only between items on the SAME LINE (not across line breaks)\n if (lineChildIdx < currentLineLength - 1) {\n mainPos! -= currentItemSpacing!\n }\n } else {\n mainPos! += fractionalMainSize + totalMainMargin\n // Add spacing only between items on the SAME LINE (not across line breaks)\n if (lineChildIdx < currentLineLength - 1) {\n mainPos! += currentItemSpacing!\n }\n }\n relIdx++\n lineChildIdx++\n }\n\n // -----------------------------------------------------------------------\n // PHASE 9: Shrink-Wrap Auto-Sized Containers\n // -----------------------------------------------------------------------\n // For containers without explicit size, compute intrinsic size from children.\n\n // For auto-sized containers (including root), shrink-wrap to content\n // Compute actual used main space from child layouts (not pre-computed flex.mainSize which may be 0)\n let actualUsedMain = 0\n for (const child of node.children) {\n if (child.flex.relativeIndex < 0) continue\n const childMainSize = isRow ? child.layout.width : child.layout.height\n const totalMainMargin = child.flex.mainStartMarginValue + child.flex.mainEndMarginValue\n actualUsedMain += childMainSize + totalMainMargin\n }\n actualUsedMain += totalGaps\n\n // Skip main-axis shrink-wrap when aspect ratio determined this dimension\n const hasAR = !Number.isNaN(aspectRatio) && aspectRatio > 0\n if (isRow && style.width.unit !== C.UNIT_POINT && style.width.unit !== C.UNIT_PERCENT && !hasAR) {\n // Auto-width row: shrink-wrap to content\n nodeWidth = actualUsedMain + innerLeft + innerRight\n }\n if (!isRow && style.height.unit !== C.UNIT_POINT && style.height.unit !== C.UNIT_PERCENT && !hasAR) {\n // Auto-height column: shrink-wrap to content\n nodeHeight = actualUsedMain + innerTop + innerBottom\n }\n // For cross axis, compute shrink-wrap size\n // For multi-line (flex-wrap), sum line cross sizes + cross gaps\n // For single line, use max child cross size (existing behavior)\n let totalCrossSize = 0\n if (numLines > 1) {\n // Multi-line: sum line cross sizes + cross gaps between lines\n // Use saved arrays to avoid corruption by recursive layoutNode\n for (let i = 0; i < numLines; i++) {\n totalCrossSize += savedLineCrossSizes ? savedLineCrossSizes[i]! : _lineCrossSizes[i]!\n }\n totalCrossSize += crossGap * (numLines - 1)\n } else {\n // Single line: max child cross size\n // CSS spec: percentage margins resolve against containing block's WIDTH only\n // Use resolveEdgeValue to respect logical EDGE_START/END\n for (const child of node.children) {\n if (child.flex.relativeIndex < 0) continue\n const childCross = isRow ? child.layout.height : child.layout.width\n const childMargin = isRow\n ? resolveEdgeValue(child.style.margin, 1, style.flexDirection, contentWidth, direction) +\n resolveEdgeValue(child.style.margin, 3, style.flexDirection, contentWidth, direction)\n : resolveEdgeValue(child.style.margin, 0, style.flexDirection, contentWidth, direction) +\n resolveEdgeValue(child.style.margin, 2, style.flexDirection, contentWidth, direction)\n totalCrossSize = Math.max(totalCrossSize, childCross + childMargin)\n }\n }\n // Cross-axis shrink-wrap for auto-sized dimension\n // Only shrink-wrap when the available dimension is NaN (unconstrained)\n // When availableHeight/Width is defined, Yoga uses it for AUTO-sized root nodes\n // Skip if aspect ratio already determined this dimension (aspect ratio > shrink-wrap)\n if (\n isRow &&\n style.height.unit !== C.UNIT_POINT &&\n style.height.unit !== C.UNIT_PERCENT &&\n Number.isNaN(availableHeight) &&\n !hasAR\n ) {\n // Auto-height row: shrink-wrap to total cross size (accounts for multi-line)\n nodeHeight = totalCrossSize + innerTop + innerBottom\n }\n if (\n !isRow &&\n style.width.unit !== C.UNIT_POINT &&\n style.width.unit !== C.UNIT_PERCENT &&\n Number.isNaN(availableWidth) &&\n !hasAR\n ) {\n // Auto-width column: shrink-wrap to total cross size (accounts for multi-line)\n nodeWidth = totalCrossSize + innerLeft + innerRight\n }\n }\n\n // Re-apply min/max constraints after any shrink-wrap adjustments\n // This ensures containers don't violate their constraints after auto-sizing\n nodeWidth = applyMinMax(nodeWidth, style.minWidth, style.maxWidth, availableWidth)\n nodeHeight = applyMinMax(nodeHeight, style.minHeight, style.maxHeight, availableHeight)\n\n // Re-enforce box model constraint: minimum size = padding + border\n // This must be applied AFTER applyMinMax since min/max can't reduce below padding+border\n if (!Number.isNaN(nodeWidth) && nodeWidth < minInnerWidth) {\n nodeWidth = minInnerWidth\n }\n if (!Number.isNaN(nodeHeight) && nodeHeight < minInnerHeight) {\n nodeHeight = minInnerHeight\n }\n\n // -----------------------------------------------------------------------\n // PHASE 9b: Re-stretch children after shrink-wrap (Yoga compat)\n // -----------------------------------------------------------------------\n // When the parent's cross axis was auto (NaN during Phase 8), children with\n // stretch alignment were shrink-wrapped to content. Now that the cross size\n // is known from shrink-wrap, re-layout those children with the definite size.\n // This matches Yoga's two-pass approach for auto-sized containers.\n if (Number.isNaN(crossAxisSize) && relativeCount > 0) {\n const finalCross = isRow ? nodeHeight - innerTop - innerBottom : nodeWidth - innerLeft - innerRight\n if (!Number.isNaN(finalCross) && finalCross > 0) {\n for (const child of node.children) {\n if (child.flex.relativeIndex < 0) continue\n const cstyle = child.style\n // Determine alignment for this child\n let childAlign = style.alignItems\n if (cstyle.alignSelf !== C.ALIGN_AUTO) {\n childAlign = cstyle.alignSelf\n }\n // AR fallback: aspect-ratio prevents implicit stretch\n const cCrossDim = isRow ? cstyle.height : cstyle.width\n const cCrossIsAuto = cCrossDim.unit === C.UNIT_AUTO || cCrossDim.unit === C.UNIT_UNDEFINED\n if (\n childAlign === C.ALIGN_STRETCH &&\n cstyle.alignSelf === C.ALIGN_AUTO &&\n !Number.isNaN(cstyle.aspectRatio) &&\n cstyle.aspectRatio > 0 &&\n cCrossIsAuto\n ) {\n childAlign = C.ALIGN_FLEX_START\n }\n if (childAlign !== C.ALIGN_STRETCH) continue\n if (!cCrossIsAuto) continue\n\n // Compute child's cross margin\n const cCrossMargin = isRow\n ? resolveEdgeValue(cstyle.margin, 1, style.flexDirection, contentWidth, direction) +\n resolveEdgeValue(cstyle.margin, 3, style.flexDirection, contentWidth, direction)\n : resolveEdgeValue(cstyle.margin, 0, style.flexDirection, contentWidth, direction) +\n resolveEdgeValue(cstyle.margin, 2, style.flexDirection, contentWidth, direction)\n const stretchedCross = finalCross - cCrossMargin\n\n // Only re-layout if the cross size actually changed\n const currentCross = isRow ? child.layout.height : child.layout.width\n if (Math.round(stretchedCross) <= currentCross) continue\n\n // Re-layout child with the definite cross size\n // Save position — layoutNode overwrites layout.left/top\n const savedLeft = child.layout.left\n const savedTop = child.layout.top\n const cMarginL = resolveEdgeValue(cstyle.margin, 0, style.flexDirection, contentWidth, direction)\n const cMarginT = resolveEdgeValue(cstyle.margin, 1, style.flexDirection, contentWidth, direction)\n const cAbsX = absX + innerLeft + savedLeft - cMarginL\n const cAbsY = absY + innerTop + savedTop - cMarginT\n const passW = isRow ? child.layout.width : stretchedCross\n const passH = isRow ? stretchedCross : child.layout.height\n layoutNode(child, passW, passH, savedLeft, savedTop, cAbsX, cAbsY, direction)\n // Restore position and override cross dimension to stretched size\n child.layout.left = savedLeft\n child.layout.top = savedTop\n if (isRow) {\n child.layout.height = Math.round(stretchedCross)\n } else {\n child.layout.width = Math.round(stretchedCross)\n }\n }\n\n // -----------------------------------------------------------------------\n // PHASE 9c: Recompute cross-axis alignment after shrink-wrap\n // -----------------------------------------------------------------------\n // When the parent's cross axis was auto (NaN during Phase 8), alignment\n // offsets for CENTER, FLEX_END, and auto margins computed NaN because\n // availableCrossSpace = NaN - childSize - margin = NaN.\n // Now that cross size is known from shrink-wrap, recompute those offsets.\n if (Number.isNaN(crossAxisSize) && relativeCount > 0) {\n const finalCross9c = isRow ? nodeHeight - innerTop - innerBottom : nodeWidth - innerLeft - innerRight\n if (!Number.isNaN(finalCross9c) && finalCross9c > 0) {\n for (const child of node.children) {\n if (child.flex.relativeIndex < 0) continue\n const cstyle = child.style\n let childAlign = style.alignItems\n if (cstyle.alignSelf !== C.ALIGN_AUTO) {\n childAlign = cstyle.alignSelf\n }\n const cCrossDim = isRow ? cstyle.height : cstyle.width\n const cCrossIsAuto = cCrossDim.unit === C.UNIT_AUTO || cCrossDim.unit === C.UNIT_UNDEFINED\n if (\n childAlign === C.ALIGN_STRETCH &&\n cstyle.alignSelf === C.ALIGN_AUTO &&\n !Number.isNaN(cstyle.aspectRatio) &&\n cstyle.aspectRatio > 0 &&\n cCrossIsAuto\n ) {\n childAlign = C.ALIGN_FLEX_START\n }\n\n const crossStartIdx = isRow ? 1 : 0\n const crossEndIdx = isRow ? 3 : 2\n const hasAutoStart = isEdgeAuto(cstyle.margin, crossStartIdx, style.flexDirection, direction)\n const hasAutoEnd = isEdgeAuto(cstyle.margin, crossEndIdx, style.flexDirection, direction)\n const needsAlignment =\n hasAutoStart || hasAutoEnd || childAlign === C.ALIGN_CENTER || childAlign === C.ALIGN_FLEX_END\n if (!needsAlignment) continue\n\n const childCrossSize = isRow ? child.layout.height : child.layout.width\n const cCrossMargin = isRow\n ? resolveEdgeValue(cstyle.margin, 1, style.flexDirection, contentWidth, direction) +\n resolveEdgeValue(cstyle.margin, 3, style.flexDirection, contentWidth, direction)\n : resolveEdgeValue(cstyle.margin, 0, style.flexDirection, contentWidth, direction) +\n resolveEdgeValue(cstyle.margin, 2, style.flexDirection, contentWidth, direction)\n const availSpace = finalCross9c - childCrossSize - cCrossMargin\n\n let crossOffset = 0\n if (hasAutoStart && hasAutoEnd) {\n crossOffset = Math.max(0, availSpace) / 2\n } else if (hasAutoStart) {\n crossOffset = Math.max(0, availSpace)\n } else if (hasAutoEnd) {\n crossOffset = 0\n } else {\n switch (childAlign) {\n case C.ALIGN_FLEX_END:\n crossOffset = availSpace\n break\n case C.ALIGN_CENTER:\n crossOffset = availSpace / 2\n break\n }\n }\n\n if (isRow) {\n if (Number.isNaN(child.layout.top)) {\n const cMarginT = resolveEdgeValue(cstyle.margin, 1, style.flexDirection, contentWidth, direction)\n child.layout.top = Math.round(cMarginT + crossOffset)\n } else if (crossOffset !== 0) {\n child.layout.top += Math.round(crossOffset)\n }\n } else {\n if (Number.isNaN(child.layout.left)) {\n const cMarginL = resolveEdgeValue(cstyle.margin, 0, style.flexDirection, contentWidth, direction)\n child.layout.left = Math.round(cMarginL + crossOffset)\n } else if (crossOffset !== 0) {\n child.layout.left += Math.round(crossOffset)\n }\n }\n }\n }\n }\n }\n }\n\n // =========================================================================\n // PHASE 10: Final Output - Set Node Layout\n // =========================================================================\n // Use edge-based rounding (Yoga-compatible): round absolute edges and derive sizes.\n // This ensures adjacent elements share exact boundaries without pixel gaps.\n\n // Set this node's layout using edge-based rounding (Yoga-compatible)\n // Use parentPosOffsetX/Y computed earlier (includes position offsets)\n // Compute absolute positions for edge-based rounding\n const absNodeLeft = absX + marginLeft + parentPosOffsetX\n const absNodeTop = absY + marginTop + parentPosOffsetY\n const absNodeRight = absNodeLeft + nodeWidth\n const absNodeBottom = absNodeTop + nodeHeight\n\n // Round edges and derive sizes (Yoga algorithm)\n const roundedAbsLeft = Math.round(absNodeLeft)\n const roundedAbsTop = Math.round(absNodeTop)\n const roundedAbsRight = Math.round(absNodeRight)\n const roundedAbsBottom = Math.round(absNodeBottom)\n\n layout.width = roundedAbsRight - roundedAbsLeft\n layout.height = roundedAbsBottom - roundedAbsTop\n // Position is relative to parent, derived from absolute rounding\n const roundedAbsParentLeft = Math.round(absX)\n const roundedAbsParentTop = Math.round(absY)\n layout.left = roundedAbsLeft - roundedAbsParentLeft\n layout.top = roundedAbsTop - roundedAbsParentTop\n\n // =========================================================================\n // PHASE 11: Layout Absolute Children\n // =========================================================================\n // Absolute children are positioned relative to the padding box, not content box.\n // They don't participate in flex layout - they're laid out independently.\n\n // Layout absolute children - handle left/right/top/bottom offsets\n // Absolute positioning uses the PADDING BOX as the containing block\n // (inside border but INCLUDING padding, not the content box)\n const absInnerLeft = borderLeft\n const absInnerTop = borderTop\n const absInnerRight = borderRight\n const absInnerBottom = borderBottom\n const absPaddingBoxW = nodeWidth - absInnerLeft - absInnerRight\n const absPaddingBoxH = nodeHeight - absInnerTop - absInnerBottom\n // Content box dimensions for percentage resolution of absolute children\n const absContentBoxW = absPaddingBoxW - paddingLeft - paddingRight\n const absContentBoxH = absPaddingBoxH - paddingTop - paddingBottom\n\n // Layout absolute positioned children (relativeIndex === -1 but not display:none)\n for (const child of node.children) {\n if (child.style.display === C.DISPLAY_NONE) continue\n if (child.style.positionType !== C.POSITION_TYPE_ABSOLUTE) continue\n const childStyle = child.style\n // CSS spec: percentage margins resolve against containing block's WIDTH only\n // Use resolveEdgeValue to respect logical EDGE_START/END\n // Note: Auto margins will resolve to 0 here, we handle them separately below\n const childMarginLeft = resolveEdgeValue(childStyle.margin, 0, style.flexDirection, nodeWidth, direction)\n const childMarginTop = resolveEdgeValue(childStyle.margin, 1, style.flexDirection, nodeWidth, direction)\n const childMarginRight = resolveEdgeValue(childStyle.margin, 2, style.flexDirection, nodeWidth, direction)\n const childMarginBottom = resolveEdgeValue(childStyle.margin, 3, style.flexDirection, nodeWidth, direction)\n\n // Check for auto margins (used for centering absolute children)\n const hasAutoMarginLeft = isEdgeAuto(childStyle.margin, 0, style.flexDirection, direction)\n const hasAutoMarginRight = isEdgeAuto(childStyle.margin, 2, style.flexDirection, direction)\n const hasAutoMarginTop = isEdgeAuto(childStyle.margin, 1, style.flexDirection, direction)\n const hasAutoMarginBottom = isEdgeAuto(childStyle.margin, 3, style.flexDirection, direction)\n\n // Position offsets from setPosition(edge, value)\n // Resolve logical EDGE_START/EDGE_END to physical left/right based on direction\n const leftPos = resolvePositionEdge(childStyle.position, 0, direction)\n const topPos = childStyle.position[1]\n const rightPos = resolvePositionEdge(childStyle.position, 2, direction)\n const bottomPos = childStyle.position[3]\n\n const hasLeft = leftPos.unit !== C.UNIT_UNDEFINED\n const hasRight = rightPos.unit !== C.UNIT_UNDEFINED\n const hasTop = topPos.unit !== C.UNIT_UNDEFINED\n const hasBottom = bottomPos.unit !== C.UNIT_UNDEFINED\n\n // Yoga resolves percentage position offsets against the content box dimensions\n const leftOffset = resolveValue(leftPos, absContentBoxW)\n const topOffset = resolveValue(topPos, absContentBoxH)\n const rightOffset = resolveValue(rightPos, absContentBoxW)\n const bottomOffset = resolveValue(bottomPos, absContentBoxH)\n\n // Calculate available size for absolute child using padding box\n const contentW = absPaddingBoxW\n const contentH = absPaddingBoxH\n\n // Determine child width\n // - If both left and right set with auto width: stretch to fill\n // - If auto width but NOT both left and right: shrink to intrinsic (NaN)\n // - For percentage width: resolve against content box\n // - Otherwise (explicit width): use available width as constraint\n let childAvailWidth: number\n const widthIsAuto = childStyle.width.unit === C.UNIT_AUTO || childStyle.width.unit === C.UNIT_UNDEFINED\n const widthIsPercent = childStyle.width.unit === C.UNIT_PERCENT\n if (widthIsAuto && hasLeft && hasRight) {\n childAvailWidth = contentW - leftOffset - rightOffset - childMarginLeft - childMarginRight\n } else if (widthIsAuto) {\n childAvailWidth = NaN // Shrink to intrinsic size\n } else if (widthIsPercent) {\n // Percentage widths resolve against content box (inside padding)\n childAvailWidth = absContentBoxW\n } else {\n childAvailWidth = contentW\n }\n\n // Determine child height\n // - If both top and bottom set with auto height: stretch to fill\n // - If auto height but NOT both top and bottom: shrink to intrinsic (NaN)\n // - For percentage height: resolve against content box\n // - Otherwise (explicit height): use available height as constraint\n let childAvailHeight: number\n const heightIsAuto = childStyle.height.unit === C.UNIT_AUTO || childStyle.height.unit === C.UNIT_UNDEFINED\n const heightIsPercent = childStyle.height.unit === C.UNIT_PERCENT\n if (heightIsAuto && hasTop && hasBottom) {\n childAvailHeight = contentH - topOffset - bottomOffset - childMarginTop - childMarginBottom\n } else if (heightIsAuto) {\n childAvailHeight = NaN // Shrink to intrinsic size\n } else if (heightIsPercent) {\n // Percentage heights resolve against content box (inside padding)\n childAvailHeight = absContentBoxH\n } else {\n childAvailHeight = contentH\n }\n\n // Compute child position\n let childX = childMarginLeft + leftOffset\n let childY = childMarginTop + topOffset\n\n // First, layout the child to get its dimensions\n // Use padding box origin (absInnerLeft/Top = border only)\n // Compute child's absolute position (margin box start, before child's own margin)\n // Parent's padding box = absX + marginLeft + borderLeft = absX + marginLeft + absInnerLeft\n // Child's margin box = parent's padding box + leftOffset\n const childAbsX = absX + marginLeft + absInnerLeft + leftOffset\n const childAbsY = absY + marginTop + absInnerTop + topOffset\n // Preserve NaN for shrink-wrap mode - only clamp real numbers to 0\n const clampIfNumber = (v: number) => (Number.isNaN(v) ? NaN : Math.max(0, v))\n layoutNode(\n child,\n clampIfNumber(childAvailWidth),\n clampIfNumber(childAvailHeight),\n layout.left + absInnerLeft + childX,\n layout.top + absInnerTop + childY,\n childAbsX,\n childAbsY,\n direction,\n )\n\n // Now compute final position based on right/bottom if left/top not set\n const childWidth = child.layout.width\n const childHeight = child.layout.height\n\n // Apply alignment when no explicit position set\n // For absolute children, align-items applies on cross axis, justify-content on main axis\n // Row: X = main axis (justifyContent), Y = cross axis (alignItems)\n // Column: X = cross axis (alignItems), Y = main axis (justifyContent)\n if (!hasLeft && !hasRight) {\n if (isRow) {\n // Row: X is main axis, use justifyContent\n const freeSpaceX = contentW - childWidth - childMarginLeft - childMarginRight\n switch (style.justifyContent) {\n case C.JUSTIFY_CENTER:\n childX = childMarginLeft + freeSpaceX / 2\n break\n case C.JUSTIFY_FLEX_END:\n childX = childMarginLeft + freeSpaceX\n break\n default: // FLEX_START\n childX = childMarginLeft\n break\n }\n } else {\n // Column: X is cross axis, use alignItems/alignSelf\n let alignment = style.alignItems\n if (childStyle.alignSelf !== C.ALIGN_AUTO) {\n alignment = childStyle.alignSelf\n }\n const freeSpaceX = contentW - childWidth - childMarginLeft - childMarginRight\n switch (alignment) {\n case C.ALIGN_CENTER:\n childX = childMarginLeft + freeSpaceX / 2\n break\n case C.ALIGN_FLEX_END:\n childX = childMarginLeft + freeSpaceX\n break\n case C.ALIGN_STRETCH:\n // Stretch: already handled by setting width to fill\n break\n default: // FLEX_START\n childX = childMarginLeft\n break\n }\n }\n } else if (!hasLeft && hasRight) {\n // Position from right edge\n childX = contentW - rightOffset - childMarginRight - childWidth\n } else if (hasLeft && hasRight) {\n // Both left and right are set\n if (widthIsAuto) {\n // Stretch width already handled above\n child.layout.width = Math.round(childAvailWidth)\n } else if (hasAutoMarginLeft || hasAutoMarginRight) {\n // Auto margins absorb remaining space for centering\n // CSS spec: auto margins don't absorb negative free space (clamp to 0)\n const freeSpace = Math.max(0, contentW - leftOffset - rightOffset - childWidth)\n if (hasAutoMarginLeft && hasAutoMarginRight) {\n // Both auto: center\n childX = leftOffset + freeSpace / 2\n } else if (hasAutoMarginLeft) {\n // Only left auto: push to right\n childX = leftOffset + freeSpace\n }\n // Only right auto: childX already set to leftOffset + childMarginLeft\n }\n }\n\n if (!hasTop && !hasBottom) {\n if (isRow) {\n // Row: Y is cross axis, use alignItems/alignSelf\n let alignment = style.alignItems\n if (childStyle.alignSelf !== C.ALIGN_AUTO) {\n alignment = childStyle.alignSelf\n }\n const freeSpaceY = contentH - childHeight - childMarginTop - childMarginBottom\n switch (alignment) {\n case C.ALIGN_CENTER:\n childY = childMarginTop + freeSpaceY / 2\n break\n case C.ALIGN_FLEX_END:\n childY = childMarginTop + freeSpaceY\n break\n case C.ALIGN_STRETCH:\n // Stretch: already handled by setting height to fill\n break\n default: // FLEX_START\n childY = childMarginTop\n break\n }\n } else {\n // Column: Y is main axis, use justifyContent\n const freeSpaceY = contentH - childHeight - childMarginTop - childMarginBottom\n switch (style.justifyContent) {\n case C.JUSTIFY_CENTER:\n childY = childMarginTop + freeSpaceY / 2\n break\n case C.JUSTIFY_FLEX_END:\n childY = childMarginTop + freeSpaceY\n break\n default: // FLEX_START\n childY = childMarginTop\n break\n }\n }\n } else if (!hasTop && hasBottom) {\n // Position from bottom edge\n childY = contentH - bottomOffset - childMarginBottom - childHeight\n } else if (hasTop && hasBottom) {\n // Both top and bottom are set\n if (heightIsAuto) {\n // Stretch height already handled above\n child.layout.height = Math.round(childAvailHeight)\n } else if (hasAutoMarginTop || hasAutoMarginBottom) {\n // Auto margins absorb remaining space for centering\n // CSS spec: auto margins don't absorb negative free space (clamp to 0)\n const freeSpace = Math.max(0, contentH - topOffset - bottomOffset - childHeight)\n if (hasAutoMarginTop && hasAutoMarginBottom) {\n // Both auto: center\n childY = topOffset + freeSpace / 2\n } else if (hasAutoMarginTop) {\n // Only top auto: push to bottom\n childY = topOffset + freeSpace\n }\n // Only bottom auto: childY already set to topOffset + childMarginTop\n }\n }\n\n // Set final position (relative to container padding box)\n child.layout.left = Math.round(absInnerLeft + childX)\n child.layout.top = Math.round(absInnerTop + childY)\n }\n\n // Update constraint fingerprint - layout is now valid for these constraints\n flex.lastAvailW = availableWidth\n flex.lastAvailH = availableHeight\n flex.lastOffsetX = offsetX\n flex.lastOffsetY = offsetY\n flex.lastAbsX = absX\n flex.lastAbsY = absY\n flex.lastDir = direction\n flex.layoutValid = true\n _t?.layoutExit(_tn, layout.width, layout.height)\n}\n","/**\n * Flexily Types\n *\n * TypeScript interfaces for the flexbox layout engine.\n */\n\n/**\n * A value with a unit (point, percent, or auto).\n */\nexport interface Value {\n value: number\n unit: number // UNIT_UNDEFINED | UNIT_POINT | UNIT_PERCENT | UNIT_AUTO\n}\n\n/**\n * Measure function signature for intrinsic sizing.\n * Called by the layout algorithm to determine a node's natural size.\n */\nexport type MeasureFunc = (\n width: number,\n widthMode: number,\n height: number,\n heightMode: number,\n) => { width: number; height: number }\n\n/**\n * Baseline function signature for baseline alignment.\n * Called by the layout algorithm to determine a node's baseline offset from its top edge.\n * Used with ALIGN_BASELINE to align text baselines across siblings.\n *\n * @param width - The computed width of the node\n * @param height - The computed height of the node\n * @returns The baseline offset from the top of the node (in points)\n */\nexport type BaselineFunc = (width: number, height: number) => number\n\n/**\n * Cache entry for measure results.\n * Stores input constraints (w, wm, h, hm) and output (rw, rh).\n */\nexport interface MeasureEntry {\n w: number\n wm: number\n h: number\n hm: number\n rw: number\n rh: number\n}\n\n/**\n * Cache entry for layout results.\n * Stores input available dimensions and computed size.\n * Used to avoid redundant recursive layout calls during a single pass.\n */\nexport interface LayoutCacheEntry {\n availW: number // Available width (may be NaN)\n availH: number // Available height (may be NaN)\n computedW: number // Computed width\n computedH: number // Computed height\n}\n\n/**\n * Per-node flex calculation state for zero-allocation layout.\n *\n * This interface enables the layout engine to avoid heap allocations during\n * layout passes by storing all intermediate calculation state directly on\n * each Node. Fields are mutated (not recreated) each pass.\n *\n * Design rationale:\n * - Eliminates ChildLayout object allocation (previously created per child per pass)\n * - Enables filtered iteration via relativeIndex (avoids temporary array allocation)\n * - Stores line membership for flex-wrap (avoids FlexLine[] allocation)\n *\n * All numeric fields use number (Float64 in V8) for precision. Boolean fields\n * track state that affects the CSS Flexbox algorithm's iterative distribution.\n *\n * @see layout.ts for usage in layoutNode() and distributeFlexSpaceForLine()\n */\nexport interface FlexInfo {\n /** Computed main-axis size after flex distribution */\n mainSize: number\n /** Original base size before flex distribution (used for weighted shrink) */\n baseSize: number\n /** Total main-axis margin (non-auto margins only) */\n mainMargin: number\n /** flex-grow factor from style */\n flexGrow: number\n /** flex-shrink factor from style */\n flexShrink: number\n /** Resolved min-width/height constraint on main axis */\n minMain: number\n /** Resolved max-width/height constraint on main axis (Infinity if none) */\n maxMain: number\n /** Whether main-start margin is auto (absorbs free space) */\n mainStartMarginAuto: boolean\n /** Whether main-end margin is auto (absorbs free space) */\n mainEndMarginAuto: boolean\n /** Resolved main-start margin value (0 if auto, computed later) */\n mainStartMarginValue: number\n /** Resolved main-end margin value (0 if auto, computed later) */\n mainEndMarginValue: number\n /** Cached resolved margin values [left, top, right, bottom] */\n marginL: number\n marginT: number\n marginR: number\n marginB: number\n /** Frozen in flex distribution (clamped to min/max constraint) */\n frozen: boolean\n /** Line index for flex-wrap (0-based, which line this child belongs to) */\n lineIndex: number\n /**\n * Relative index for filtered iteration.\n * -1 = absolute positioned or display:none (skip in flex layout)\n * 0+ = index among relative children (participates in flex layout)\n */\n relativeIndex: number\n /** Computed baseline offset for ALIGN_BASELINE (zero-alloc: avoids per-pass array) */\n baseline: number\n\n // Constraint fingerprinting for layout caching\n /** Last availableWidth passed to layoutNode */\n lastAvailW: number\n /** Last availableHeight passed to layoutNode */\n lastAvailH: number\n /** Last offsetX passed to layoutNode */\n lastOffsetX: number\n /** Last offsetY passed to layoutNode */\n lastOffsetY: number\n /** Last absX passed to layoutNode (affects edge-based rounding) */\n lastAbsX: number\n /** Last absY passed to layoutNode (affects edge-based rounding) */\n lastAbsY: number\n /** Whether cached layout is valid (fingerprint matched, not dirty) */\n layoutValid: boolean\n /** Last direction passed to layoutNode */\n lastDir: number\n}\n\n/**\n * Computed layout result for a node.\n */\nexport interface Layout {\n left: number\n top: number\n width: number\n height: number\n}\n\n/**\n * Internal style properties for a node.\n */\nexport interface Style {\n // Display\n display: number\n\n // Position\n positionType: number\n position: [Value, Value, Value, Value, Value, Value] // [left, top, right, bottom, start, end]\n\n // Flex\n flexDirection: number\n flexWrap: number\n flexGrow: number\n flexShrink: number\n flexBasis: Value\n\n // Alignment\n alignItems: number\n alignSelf: number\n alignContent: number\n justifyContent: number\n\n // Size\n width: Value\n height: Value\n minWidth: Value\n minHeight: Value\n maxWidth: Value\n maxHeight: Value\n aspectRatio: number // NaN = undefined, otherwise width/height ratio\n\n // Spacing (per-edge: left, top, right, bottom, start, end)\n // Physical edges: [0]=left, [1]=top, [2]=right, [3]=bottom\n // Logical edges: [4]=start, [5]=end (resolved based on flex direction)\n margin: [Value, Value, Value, Value, Value, Value]\n padding: [Value, Value, Value, Value, Value, Value]\n border: [number, number, number, number, number, number] // Border widths (always points, [4,5] = logical start/end)\n\n // Gap\n gap: [number, number] // [column, row]\n\n // Overflow\n overflow: number\n}\n\n/**\n * Create a default Value (undefined).\n */\nexport function createValue(value = 0, unit = 0): Value {\n return { value, unit }\n}\n\n/**\n * Create default style.\n *\n * Comments indicate where Yoga and CSS defaults differ.\n * Flexily follows Yoga defaults for API compatibility.\n */\nexport function createDefaultStyle(): Style {\n return {\n display: 0, // DISPLAY_FLEX (same in CSS and Yoga)\n positionType: 1, // POSITION_TYPE_RELATIVE (same in CSS and Yoga)\n position: [createValue(), createValue(), createValue(), createValue(), createValue(), createValue()],\n flexDirection: 2, // FLEX_DIRECTION_ROW — CSS default; Yoga defaults to COLUMN\n flexWrap: 0, // WRAP_NO_WRAP (same in CSS and Yoga)\n flexGrow: 0, // (same in CSS and Yoga)\n flexShrink: 0, // Yoga default; CSS defaults to 1\n flexBasis: createValue(0, 3), // AUTO (same in CSS and Yoga)\n alignItems: 4, // ALIGN_STRETCH (same in CSS and Yoga)\n alignSelf: 0, // ALIGN_AUTO (same in CSS and Yoga)\n alignContent: 1, // ALIGN_FLEX_START — Yoga default; CSS defaults to STRETCH\n justifyContent: 0, // JUSTIFY_FLEX_START (same in CSS and Yoga)\n width: createValue(0, 3), // AUTO (same in CSS and Yoga)\n height: createValue(0, 3), // AUTO (same in CSS and Yoga)\n minWidth: createValue(),\n minHeight: createValue(),\n maxWidth: createValue(),\n maxHeight: createValue(),\n aspectRatio: NaN, // undefined by default (same in CSS and Yoga)\n margin: [createValue(), createValue(), createValue(), createValue(), createValue(), createValue()],\n padding: [createValue(), createValue(), createValue(), createValue(), createValue(), createValue()],\n border: [0, 0, 0, 0, NaN, NaN],\n gap: [0, 0],\n overflow: 0, // OVERFLOW_VISIBLE (same in CSS and Yoga)\n }\n}\n","/**\n * Flexily Node\n *\n * Yoga-compatible Node class for flexbox layout.\n */\n\nimport * as C from \"./constants.js\"\nimport { computeLayout, countNodes, markSubtreeLayoutSeen } from \"./layout-zero.js\"\nimport {\n type BaselineFunc,\n type FlexInfo,\n type Layout,\n type LayoutCacheEntry,\n type MeasureEntry,\n type MeasureFunc,\n type Style,\n type Value,\n createDefaultStyle,\n} from \"./types.js\"\nimport { setEdgeValue, setEdgeBorder, getEdgeValue, getEdgeBorderValue, traversalStack } from \"./utils.js\"\nimport { log } from \"./logger.js\"\nimport { getTrace } from \"./trace.js\"\n\n/**\n * A layout node in the flexbox tree.\n */\nexport class Node {\n // Tree structure\n private _parent: Node | null = null\n private _children: Node[] = []\n\n // Style\n private _style: Style = createDefaultStyle()\n\n // Measure function for intrinsic sizing\n private _measureFunc: MeasureFunc | null = null\n\n // Baseline function for baseline alignment\n private _baselineFunc: BaselineFunc | null = null\n\n // Measure cache - 4-entry numeric cache (faster than Map<string,...>)\n // Each entry stores: w, wm, h, hm, rw, rh\n // Cleared when markDirty() is called since content may have changed\n private _m0?: MeasureEntry\n private _m1?: MeasureEntry\n private _m2?: MeasureEntry\n private _m3?: MeasureEntry\n\n // Layout cache - 2-entry cache for sizing pass (availW, availH -> computedW, computedH)\n // Cleared at start of each calculateLayout pass via resetLayoutCache()\n // This avoids redundant recursive layout calls during intrinsic sizing\n private _lc0?: LayoutCacheEntry\n private _lc1?: LayoutCacheEntry\n\n // Stable result objects for zero-allocation cache returns\n // These are mutated in place instead of creating new objects on each cache hit\n private _measureResult: { width: number; height: number } = {\n width: 0,\n height: 0,\n }\n private _layoutResult: { width: number; height: number } = {\n width: 0,\n height: 0,\n }\n\n // Static counters for cache statistics (reset per layout pass)\n static measureCalls = 0\n static measureCacheHits = 0\n\n /**\n * Reset measure statistics (call before calculateLayout).\n */\n static resetMeasureStats(): void {\n Node.measureCalls = 0\n Node.measureCacheHits = 0\n }\n\n // Computed layout\n private _layout: Layout = { left: 0, top: 0, width: 0, height: 0 }\n\n // Per-node flex calculation state (reused across layout passes to avoid allocation)\n private _flex: FlexInfo = {\n mainSize: 0,\n baseSize: 0,\n mainMargin: 0,\n flexGrow: 0,\n flexShrink: 0,\n minMain: 0,\n maxMain: Infinity,\n mainStartMarginAuto: false,\n mainEndMarginAuto: false,\n mainStartMarginValue: 0,\n mainEndMarginValue: 0,\n marginL: 0,\n marginT: 0,\n marginR: 0,\n marginB: 0,\n frozen: false,\n lineIndex: 0,\n relativeIndex: -1,\n baseline: 0,\n // Constraint fingerprinting\n lastAvailW: NaN,\n lastAvailH: NaN,\n lastOffsetX: NaN,\n lastOffsetY: NaN,\n lastAbsX: NaN,\n lastAbsY: NaN,\n layoutValid: false,\n lastDir: 0,\n }\n\n // Dirty flags\n private _isDirty = true\n private _hasNewLayout = false\n\n // Last calculateLayout() inputs (for constraint-aware skip)\n private _lastCalcW: number = NaN\n private _lastCalcH: number = NaN\n private _lastCalcDir: number = 0\n\n // ============================================================================\n // Static Factory\n // ============================================================================\n\n /**\n * Create a new layout node.\n *\n * @returns A new Node instance\n * @example\n * ```typescript\n * const root = Node.create();\n * root.setWidth(100);\n * root.setHeight(200);\n * ```\n */\n static create(): Node {\n return new Node()\n }\n\n // ============================================================================\n // Tree Operations\n // ============================================================================\n\n /**\n * Get the number of child nodes.\n *\n * @returns The number of children\n */\n getChildCount(): number {\n return this._children.length\n }\n\n /**\n * Get a child node by index.\n *\n * @param index - Zero-based child index\n * @returns The child node at the given index, or undefined if index is out of bounds\n */\n getChild(index: number): Node | undefined {\n return this._children[index]\n }\n\n /**\n * Get the parent node.\n *\n * @returns The parent node, or null if this is a root node\n */\n getParent(): Node | null {\n return this._parent\n }\n\n /**\n * Insert a child node at the specified index.\n * If the child already has a parent, it will be removed from that parent first.\n * Marks the node as dirty to trigger layout recalculation.\n *\n * @param child - The child node to insert\n * @param index - The index at which to insert the child\n * @example\n * ```typescript\n * const parent = Node.create();\n * const child1 = Node.create();\n * const child2 = Node.create();\n * parent.insertChild(child1, 0);\n * parent.insertChild(child2, 1);\n * ```\n */\n insertChild(child: Node, index: number): void {\n // Cycle guard: prevent self-insertion or insertion of an ancestor (would create infinite loop)\n if (child === this) {\n throw new Error(\"Cannot insert a node as a child of itself\")\n }\n let ancestor: Node | null = this._parent\n while (ancestor !== null) {\n if (ancestor === child) {\n throw new Error(\"Cannot insert an ancestor as a child (would create a cycle)\")\n }\n ancestor = ancestor._parent\n }\n\n if (child._parent !== null) {\n child._parent.removeChild(child)\n }\n child._parent = this\n // Clamp index to valid range to ensure deterministic behavior\n const clampedIndex = Math.max(0, Math.min(index, this._children.length))\n this._children.splice(clampedIndex, 0, child)\n // Invalidate layoutValid for siblings after the insertion point\n // Their positions may change due to the insertion\n for (let i = clampedIndex + 1; i < this._children.length; i++) {\n this._children[i]!._flex.layoutValid = false\n }\n this.markDirty()\n }\n\n /**\n * Remove a child node from this node.\n * The child's parent reference will be cleared.\n * Marks the node as dirty to trigger layout recalculation.\n * Invalidates layout validity of remaining siblings whose positions may change.\n *\n * @param child - The child node to remove\n */\n removeChild(child: Node): void {\n const index = this._children.indexOf(child)\n if (index !== -1) {\n this._children.splice(index, 1)\n child._parent = null\n // Invalidate layoutValid for remaining siblings after the removal point\n // Their positions may change due to the removal\n for (let i = index; i < this._children.length; i++) {\n this._children[i]!._flex.layoutValid = false\n }\n this.markDirty()\n }\n }\n\n /**\n * Free this node and clean up all references.\n * Removes the node from its parent, clears all children, and removes the measure function.\n * This does not recursively free child nodes.\n */\n free(): void {\n // Remove from parent\n if (this._parent !== null) {\n this._parent.removeChild(this)\n }\n // Clear children\n for (const child of this._children) {\n child._parent = null\n }\n this._children = []\n this._measureFunc = null\n this._baselineFunc = null\n }\n\n /**\n * Free this node and all descendants recursively.\n * Each node is detached from its parent and cleaned up.\n * Uses iterative traversal to avoid stack overflow on deep trees.\n */\n freeRecursive(): void {\n // Collect all descendants first (iterative to avoid stack overflow)\n const nodes: Node[] = []\n traversalStack.length = 0\n traversalStack.push(this)\n while (traversalStack.length > 0) {\n const current = traversalStack.pop() as Node\n nodes.push(current)\n for (const child of current._children) {\n traversalStack.push(child)\n }\n }\n // Free in reverse order (leaves first) to avoid parent.removeChild on already-freed nodes\n for (let i = nodes.length - 1; i >= 0; i--) {\n nodes[i]!.free()\n }\n }\n\n /**\n * Dispose the node (calls free)\n */\n [Symbol.dispose](): void {\n this.free()\n }\n\n // ============================================================================\n // Measure Function\n // ============================================================================\n\n /**\n * Set a measure function for intrinsic sizing.\n * The measure function is called during layout to determine the node's natural size.\n * Typically used for text nodes or other content that has an intrinsic size.\n * Marks the node as dirty to trigger layout recalculation.\n *\n * @param measureFunc - Function that returns width and height given available space and constraints\n * @example\n * ```typescript\n * const textNode = Node.create();\n * textNode.setMeasureFunc((width, widthMode, height, heightMode) => {\n * // Measure text and return dimensions\n * return { width: 50, height: 20 };\n * });\n * ```\n */\n setMeasureFunc(measureFunc: MeasureFunc): void {\n this._measureFunc = measureFunc\n this.markDirty()\n }\n\n /**\n * Remove the measure function from this node.\n * Marks the node as dirty to trigger layout recalculation.\n */\n unsetMeasureFunc(): void {\n this._measureFunc = null\n this.markDirty()\n }\n\n /**\n * Check if this node has a measure function.\n *\n * @returns True if a measure function is set\n */\n hasMeasureFunc(): boolean {\n return this._measureFunc !== null\n }\n\n // ============================================================================\n // Baseline Function\n // ============================================================================\n\n /**\n * Set a baseline function to determine where this node's text baseline is.\n * Used for ALIGN_BASELINE to align text across siblings with different heights.\n *\n * @param baselineFunc - Function that returns baseline offset from top given width and height\n * @example\n * ```typescript\n * textNode.setBaselineFunc((width, height) => {\n * // For a text node, baseline might be at 80% of height\n * return height * 0.8;\n * });\n * ```\n */\n setBaselineFunc(baselineFunc: BaselineFunc): void {\n this._baselineFunc = baselineFunc\n this.markDirty()\n }\n\n /**\n * Remove the baseline function from this node.\n * Marks the node as dirty to trigger layout recalculation.\n */\n unsetBaselineFunc(): void {\n this._baselineFunc = null\n this.markDirty()\n }\n\n /**\n * Check if this node has a baseline function.\n *\n * @returns True if a baseline function is set\n */\n hasBaselineFunc(): boolean {\n return this._baselineFunc !== null\n }\n\n /**\n * Call the measure function with caching.\n * Uses a 4-entry numeric cache for fast lookup without allocations.\n * Cache is cleared when markDirty() is called.\n *\n * @returns Measured dimensions or null if no measure function\n */\n cachedMeasure(w: number, wm: number, h: number, hm: number): { width: number; height: number } | null {\n if (!this._measureFunc) return null\n\n Node.measureCalls++\n\n // Check 4-entry cache (most recent first)\n // Returns stable _measureResult object to avoid allocation on cache hit\n const m0 = this._m0\n if (m0 && m0.w === w && m0.wm === wm && m0.h === h && m0.hm === hm) {\n Node.measureCacheHits++\n this._measureResult.width = m0.rw\n this._measureResult.height = m0.rh\n getTrace()?.measureCacheHit(0, w, h, m0.rw, m0.rh)\n return this._measureResult\n }\n const m1 = this._m1\n if (m1 && m1.w === w && m1.wm === wm && m1.h === h && m1.hm === hm) {\n Node.measureCacheHits++\n this._measureResult.width = m1.rw\n this._measureResult.height = m1.rh\n getTrace()?.measureCacheHit(0, w, h, m1.rw, m1.rh)\n return this._measureResult\n }\n const m2 = this._m2\n if (m2 && m2.w === w && m2.wm === wm && m2.h === h && m2.hm === hm) {\n Node.measureCacheHits++\n this._measureResult.width = m2.rw\n this._measureResult.height = m2.rh\n getTrace()?.measureCacheHit(0, w, h, m2.rw, m2.rh)\n return this._measureResult\n }\n const m3 = this._m3\n if (m3 && m3.w === w && m3.wm === wm && m3.h === h && m3.hm === hm) {\n Node.measureCacheHits++\n this._measureResult.width = m3.rw\n this._measureResult.height = m3.rh\n getTrace()?.measureCacheHit(0, w, h, m3.rw, m3.rh)\n return this._measureResult\n }\n\n // Cache miss\n getTrace()?.measureCacheMiss(0, w, h)\n\n // Call actual measure function\n const result = this._measureFunc(w, wm, h, hm)\n\n // Zero-allocation: rotate entries by copying values, lazily allocate on first use\n // Rotate: m3 <- m2 <- m1 <- m0 <- new values\n if (this._m2) {\n if (!this._m3) this._m3 = { w: 0, wm: 0, h: 0, hm: 0, rw: 0, rh: 0 }\n this._m3.w = this._m2.w\n this._m3.wm = this._m2.wm\n this._m3.h = this._m2.h\n this._m3.hm = this._m2.hm\n this._m3.rw = this._m2.rw\n this._m3.rh = this._m2.rh\n }\n if (this._m1) {\n if (!this._m2) this._m2 = { w: 0, wm: 0, h: 0, hm: 0, rw: 0, rh: 0 }\n this._m2.w = this._m1.w\n this._m2.wm = this._m1.wm\n this._m2.h = this._m1.h\n this._m2.hm = this._m1.hm\n this._m2.rw = this._m1.rw\n this._m2.rh = this._m1.rh\n }\n if (this._m0) {\n if (!this._m1) this._m1 = { w: 0, wm: 0, h: 0, hm: 0, rw: 0, rh: 0 }\n this._m1.w = this._m0.w\n this._m1.wm = this._m0.wm\n this._m1.h = this._m0.h\n this._m1.hm = this._m0.hm\n this._m1.rw = this._m0.rw\n this._m1.rh = this._m0.rh\n }\n if (!this._m0) this._m0 = { w: 0, wm: 0, h: 0, hm: 0, rw: 0, rh: 0 }\n this._m0.w = w\n this._m0.wm = wm\n this._m0.h = h\n this._m0.hm = hm\n this._m0.rw = result.width\n this._m0.rh = result.height\n\n // Return stable result object (same as cache hits)\n this._measureResult.width = result.width\n this._measureResult.height = result.height\n return this._measureResult\n }\n\n // ============================================================================\n // Layout Caching (for intrinsic sizing pass)\n // ============================================================================\n\n /**\n * Check layout cache for a previously computed size with same available dimensions.\n * Returns cached (width, height) or null if not found.\n *\n * NaN dimensions are handled specially via Object.is (NaN === NaN is false, but Object.is(NaN, NaN) is true).\n */\n getCachedLayout(availW: number, availH: number): { width: number; height: number } | null {\n // Never return cached layout for dirty nodes - content may have changed\n if (this._isDirty) {\n return null\n }\n // Returns stable _layoutResult object to avoid allocation on cache hit\n const lc0 = this._lc0\n if (lc0 && Object.is(lc0.availW, availW) && Object.is(lc0.availH, availH)) {\n this._layoutResult.width = lc0.computedW\n this._layoutResult.height = lc0.computedH\n return this._layoutResult\n }\n const lc1 = this._lc1\n if (lc1 && Object.is(lc1.availW, availW) && Object.is(lc1.availH, availH)) {\n this._layoutResult.width = lc1.computedW\n this._layoutResult.height = lc1.computedH\n return this._layoutResult\n }\n return null\n }\n\n /**\n * Cache a computed layout result for the given available dimensions.\n * Zero-allocation: lazily allocates cache entries once, then reuses.\n */\n setCachedLayout(availW: number, availH: number, computedW: number, computedH: number): void {\n // Rotate entries: copy _lc0 values to _lc1, then update _lc0\n if (this._lc0) {\n // Lazily allocate _lc1 on first rotation\n if (!this._lc1) {\n this._lc1 = { availW: NaN, availH: NaN, computedW: 0, computedH: 0 }\n }\n this._lc1.availW = this._lc0.availW\n this._lc1.availH = this._lc0.availH\n this._lc1.computedW = this._lc0.computedW\n this._lc1.computedH = this._lc0.computedH\n }\n // Lazily allocate _lc0 on first use\n if (!this._lc0) {\n this._lc0 = { availW: 0, availH: 0, computedW: 0, computedH: 0 }\n }\n this._lc0.availW = availW\n this._lc0.availH = availH\n this._lc0.computedW = computedW\n this._lc0.computedH = computedH\n }\n\n /**\n * Clear layout cache for this node and all descendants.\n * Called at the start of each calculateLayout pass.\n * Zero-allocation: invalidates entries (availW = NaN) rather than deallocating.\n * Uses iterative traversal to avoid stack overflow on deep trees.\n */\n resetLayoutCache(): void {\n traversalStack.length = 0\n traversalStack.push(this)\n while (traversalStack.length > 0) {\n const node = traversalStack.pop() as Node\n // Invalidate using -1 sentinel (not NaN — NaN is a legitimate \"unconstrained\" query\n // value and Object.is(NaN, NaN) === true would cause false cache hits)\n if (node._lc0) node._lc0.availW = -1\n if (node._lc1) node._lc1.availW = -1\n for (const child of node._children) {\n traversalStack.push(child)\n }\n }\n }\n\n // ============================================================================\n // Dirty Tracking\n // ============================================================================\n\n /**\n * Check if this node needs layout recalculation.\n *\n * @returns True if the node is dirty and needs layout\n */\n isDirty(): boolean {\n return this._isDirty\n }\n\n /**\n * Mark this node and all ancestors as dirty.\n * A dirty node needs layout recalculation.\n * This is automatically called by all style setters and tree operations.\n * Uses iterative approach to avoid stack overflow on deep trees.\n */\n markDirty(): void {\n let current: Node | null = this\n while (current !== null) {\n // Always clear caches - even if already dirty, a child's content change\n // may invalidate cached layout results that used the old child size\n current._m0 = current._m1 = current._m2 = current._m3 = undefined\n current._lc0 = current._lc1 = undefined\n // Skip setting dirty flag if already dirty (but still cleared caches above)\n if (current._isDirty) break\n current._isDirty = true\n // Invalidate layout fingerprint\n current._flex.layoutValid = false\n current = current._parent\n }\n }\n\n /**\n * Check if this node has new layout results since the last check.\n *\n * @returns True if layout was recalculated since the last call to markLayoutSeen\n */\n hasNewLayout(): boolean {\n return this._hasNewLayout\n }\n\n /**\n * Mark that the current layout has been seen/processed.\n * Clears the hasNewLayout flag.\n */\n markLayoutSeen(): void {\n this._hasNewLayout = false\n }\n\n // ============================================================================\n // Layout Calculation\n // ============================================================================\n\n /**\n * Calculate layout for this node and all descendants.\n * This runs the flexbox layout algorithm to compute positions and sizes.\n * Only recalculates if the node is marked as dirty.\n *\n * @param width - Available width for layout\n * @param height - Available height for layout\n * @param _direction - Text direction (LTR or RTL), defaults to LTR\n * @example\n * ```typescript\n * const root = Node.create();\n * root.setFlexDirection(FLEX_DIRECTION_ROW);\n * root.setWidth(100);\n * root.setHeight(50);\n *\n * const child = Node.create();\n * child.setFlexGrow(1);\n * root.insertChild(child, 0);\n *\n * root.calculateLayout(100, 50, DIRECTION_LTR);\n *\n * // Now you can read computed layout\n * console.log(child.getComputedWidth());\n * ```\n */\n calculateLayout(width?: number, height?: number, direction: number = C.DIRECTION_LTR): void {\n // Treat undefined as unconstrained (NaN signals content-based sizing)\n const availableWidth = width ?? NaN\n const availableHeight = height ?? NaN\n\n // Skip if not dirty AND constraints unchanged (use Object.is for NaN equality)\n if (\n !this._isDirty &&\n Object.is(this._lastCalcW, availableWidth) &&\n Object.is(this._lastCalcH, availableHeight) &&\n this._lastCalcDir === direction\n ) {\n log.debug?.(\"layout skip (not dirty, constraints unchanged)\")\n return\n }\n\n // Track constraints for future skip check\n this._lastCalcW = availableWidth\n this._lastCalcH = availableHeight\n this._lastCalcDir = direction\n\n // Only compute debug stats when debug logging is enabled (avoid O(n) traversal in production)\n const start = log.debug ? Date.now() : 0\n const nodeCount = log.debug ? countNodes(this) : 0\n\n // Reset measure statistics for this layout pass\n Node.resetMeasureStats()\n\n // Run the layout algorithm\n computeLayout(this, availableWidth, availableHeight, direction)\n\n // Mark layout computed\n this._isDirty = false\n this._hasNewLayout = true\n markSubtreeLayoutSeen(this)\n\n log.debug?.(\n \"layout: %dx%d, %d nodes in %dms (measure: calls=%d hits=%d)\",\n width,\n height,\n nodeCount,\n Date.now() - start,\n Node.measureCalls,\n Node.measureCacheHits,\n )\n }\n\n // ============================================================================\n // Layout Results\n // ============================================================================\n\n /**\n * Get the computed left position after layout.\n *\n * @returns The left position in points\n */\n getComputedLeft(): number {\n return this._layout.left\n }\n\n /**\n * Get the computed top position after layout.\n *\n * @returns The top position in points\n */\n getComputedTop(): number {\n return this._layout.top\n }\n\n /**\n * Get the computed width after layout.\n *\n * @returns The width in points\n */\n getComputedWidth(): number {\n return this._layout.width\n }\n\n /**\n * Get the computed height after layout.\n *\n * @returns The height in points\n */\n getComputedHeight(): number {\n return this._layout.height\n }\n\n /**\n * Get the computed right edge position after layout (left + width).\n *\n * @returns The right edge position in points\n */\n getComputedRight(): number {\n return this._layout.left + this._layout.width\n }\n\n /**\n * Get the computed bottom edge position after layout (top + height).\n *\n * @returns The bottom edge position in points\n */\n getComputedBottom(): number {\n return this._layout.top + this._layout.height\n }\n\n /**\n * Get the computed padding for a specific edge after layout.\n * Returns the resolved padding value (percentage and logical edges resolved).\n *\n * @param edge - EDGE_LEFT, EDGE_TOP, EDGE_RIGHT, or EDGE_BOTTOM\n * @returns Padding value in points\n */\n getComputedPadding(edge: number): number {\n return getEdgeValue(this._style.padding, edge).value\n }\n\n /**\n * Get the computed margin for a specific edge after layout.\n * Returns the resolved margin value (percentage and logical edges resolved).\n *\n * @param edge - EDGE_LEFT, EDGE_TOP, EDGE_RIGHT, or EDGE_BOTTOM\n * @returns Margin value in points\n */\n getComputedMargin(edge: number): number {\n return getEdgeValue(this._style.margin, edge).value\n }\n\n /**\n * Get the computed border width for a specific edge after layout.\n *\n * @param edge - EDGE_LEFT, EDGE_TOP, EDGE_RIGHT, or EDGE_BOTTOM\n * @returns Border width in points\n */\n getComputedBorder(edge: number): number {\n return getEdgeBorderValue(this._style.border, edge)\n }\n\n // ============================================================================\n // Internal Accessors (for layout algorithm)\n // ============================================================================\n\n get children(): readonly Node[] {\n return this._children\n }\n\n get style(): Style {\n return this._style\n }\n\n get layout(): Layout {\n return this._layout\n }\n\n get measureFunc(): MeasureFunc | null {\n return this._measureFunc\n }\n\n get baselineFunc(): BaselineFunc | null {\n return this._baselineFunc\n }\n\n get flex(): FlexInfo {\n return this._flex\n }\n\n // ============================================================================\n // Width Setters\n // ============================================================================\n\n /**\n * Set the width to a fixed value in points.\n *\n * @param value - Width in points\n */\n setWidth(value: number): void {\n // NaN means \"auto\" in Yoga API\n if (Number.isNaN(value)) {\n this._style.width = { value: 0, unit: C.UNIT_AUTO }\n } else {\n this._style.width = { value, unit: C.UNIT_POINT }\n }\n this.markDirty()\n }\n\n /**\n * Set the width as a percentage of the parent's width.\n *\n * @param value - Width as a percentage (0-100)\n */\n setWidthPercent(value: number): void {\n this._style.width = { value, unit: C.UNIT_PERCENT }\n this.markDirty()\n }\n\n /**\n * Set the width to auto (determined by layout algorithm).\n */\n setWidthAuto(): void {\n this._style.width = { value: 0, unit: C.UNIT_AUTO }\n this.markDirty()\n }\n\n // ============================================================================\n // Height Setters\n // ============================================================================\n\n /**\n * Set the height to a fixed value in points.\n *\n * @param value - Height in points\n */\n setHeight(value: number): void {\n // NaN means \"auto\" in Yoga API\n if (Number.isNaN(value)) {\n this._style.height = { value: 0, unit: C.UNIT_AUTO }\n } else {\n this._style.height = { value, unit: C.UNIT_POINT }\n }\n this.markDirty()\n }\n\n /**\n * Set the height as a percentage of the parent's height.\n *\n * @param value - Height as a percentage (0-100)\n */\n setHeightPercent(value: number): void {\n this._style.height = { value, unit: C.UNIT_PERCENT }\n this.markDirty()\n }\n\n /**\n * Set the height to auto (determined by layout algorithm).\n */\n setHeightAuto(): void {\n this._style.height = { value: 0, unit: C.UNIT_AUTO }\n this.markDirty()\n }\n\n // ============================================================================\n // Min/Max Size Setters\n // ============================================================================\n\n /**\n * Set the minimum width in points.\n *\n * @param value - Minimum width in points\n */\n setMinWidth(value: number): void {\n this._style.minWidth = { value, unit: C.UNIT_POINT }\n this.markDirty()\n }\n\n /**\n * Set the minimum width as a percentage of the parent's width.\n *\n * @param value - Minimum width as a percentage (0-100)\n */\n setMinWidthPercent(value: number): void {\n this._style.minWidth = { value, unit: C.UNIT_PERCENT }\n this.markDirty()\n }\n\n /**\n * Set the minimum height in points.\n *\n * @param value - Minimum height in points\n */\n setMinHeight(value: number): void {\n this._style.minHeight = { value, unit: C.UNIT_POINT }\n this.markDirty()\n }\n\n /**\n * Set the minimum height as a percentage of the parent's height.\n *\n * @param value - Minimum height as a percentage (0-100)\n */\n setMinHeightPercent(value: number): void {\n this._style.minHeight = { value, unit: C.UNIT_PERCENT }\n this.markDirty()\n }\n\n /**\n * Set the maximum width in points.\n *\n * @param value - Maximum width in points\n */\n setMaxWidth(value: number): void {\n this._style.maxWidth = { value, unit: C.UNIT_POINT }\n this.markDirty()\n }\n\n /**\n * Set the maximum width as a percentage of the parent's width.\n *\n * @param value - Maximum width as a percentage (0-100)\n */\n setMaxWidthPercent(value: number): void {\n this._style.maxWidth = { value, unit: C.UNIT_PERCENT }\n this.markDirty()\n }\n\n /**\n * Set the maximum height in points.\n *\n * @param value - Maximum height in points\n */\n setMaxHeight(value: number): void {\n this._style.maxHeight = { value, unit: C.UNIT_POINT }\n this.markDirty()\n }\n\n /**\n * Set the maximum height as a percentage of the parent's height.\n *\n * @param value - Maximum height as a percentage (0-100)\n */\n setMaxHeightPercent(value: number): void {\n this._style.maxHeight = { value, unit: C.UNIT_PERCENT }\n this.markDirty()\n }\n\n /**\n * Set the aspect ratio of the node.\n * When set, the node's width/height relationship is constrained.\n * If width is defined, height = width / aspectRatio.\n * If height is defined, width = height * aspectRatio.\n *\n * @param value - Aspect ratio (width/height). Use NaN to unset.\n */\n setAspectRatio(value: number): void {\n this._style.aspectRatio = value\n this.markDirty()\n }\n\n // ============================================================================\n // Flex Setters\n // ============================================================================\n\n /**\n * Set the flex grow factor.\n * Determines how much the node will grow relative to siblings when there is extra space.\n *\n * @param value - Flex grow factor (typically 0 or 1+)\n * @example\n * ```typescript\n * const child = Node.create();\n * child.setFlexGrow(1); // Will grow to fill available space\n * ```\n */\n setFlexGrow(value: number): void {\n this._style.flexGrow = value\n this.markDirty()\n }\n\n /**\n * Set the flex shrink factor.\n * Determines how much the node will shrink relative to siblings when there is insufficient space.\n *\n * @param value - Flex shrink factor (default is 1)\n */\n setFlexShrink(value: number): void {\n this._style.flexShrink = value\n this.markDirty()\n }\n\n /**\n * Set the flex basis to a fixed value in points.\n * The initial size of the node before flex grow/shrink is applied.\n *\n * @param value - Flex basis in points\n */\n setFlexBasis(value: number): void {\n this._style.flexBasis = { value, unit: C.UNIT_POINT }\n this.markDirty()\n }\n\n /**\n * Set the flex basis as a percentage of the parent's size.\n *\n * @param value - Flex basis as a percentage (0-100)\n */\n setFlexBasisPercent(value: number): void {\n this._style.flexBasis = { value, unit: C.UNIT_PERCENT }\n this.markDirty()\n }\n\n /**\n * Set the flex basis to auto (based on the node's width/height).\n */\n setFlexBasisAuto(): void {\n this._style.flexBasis = { value: 0, unit: C.UNIT_AUTO }\n this.markDirty()\n }\n\n /**\n * Set the flex direction (main axis direction).\n *\n * @param direction - FLEX_DIRECTION_ROW, FLEX_DIRECTION_COLUMN, FLEX_DIRECTION_ROW_REVERSE, or FLEX_DIRECTION_COLUMN_REVERSE\n * @example\n * ```typescript\n * const container = Node.create();\n * container.setFlexDirection(FLEX_DIRECTION_ROW); // Lay out children horizontally\n * ```\n */\n setFlexDirection(direction: number): void {\n this._style.flexDirection = direction\n this.markDirty()\n }\n\n /**\n * Set the flex wrap behavior.\n *\n * @param wrap - WRAP_NO_WRAP, WRAP_WRAP, or WRAP_WRAP_REVERSE\n */\n setFlexWrap(wrap: number): void {\n this._style.flexWrap = wrap\n this.markDirty()\n }\n\n // ============================================================================\n // Alignment Setters\n // ============================================================================\n\n /**\n * Set how children are aligned along the cross axis.\n *\n * @param align - ALIGN_FLEX_START, ALIGN_CENTER, ALIGN_FLEX_END, ALIGN_STRETCH, or ALIGN_BASELINE\n * @example\n * ```typescript\n * const container = Node.create();\n * container.setFlexDirection(FLEX_DIRECTION_ROW);\n * container.setAlignItems(ALIGN_CENTER); // Center children vertically\n * ```\n */\n setAlignItems(align: number): void {\n this._style.alignItems = align\n this.markDirty()\n }\n\n /**\n * Set how this node is aligned along the parent's cross axis.\n * Overrides the parent's alignItems for this specific child.\n *\n * @param align - ALIGN_AUTO, ALIGN_FLEX_START, ALIGN_CENTER, ALIGN_FLEX_END, ALIGN_STRETCH, or ALIGN_BASELINE\n */\n setAlignSelf(align: number): void {\n this._style.alignSelf = align\n this.markDirty()\n }\n\n /**\n * Set how lines are aligned in a multi-line flex container.\n * Only affects containers with wrap enabled and multiple lines.\n *\n * @param align - ALIGN_FLEX_START, ALIGN_CENTER, ALIGN_FLEX_END, ALIGN_STRETCH, ALIGN_SPACE_BETWEEN, or ALIGN_SPACE_AROUND\n */\n setAlignContent(align: number): void {\n this._style.alignContent = align\n this.markDirty()\n }\n\n /**\n * Set how children are distributed along the main axis.\n *\n * @param justify - JUSTIFY_FLEX_START, JUSTIFY_CENTER, JUSTIFY_FLEX_END, JUSTIFY_SPACE_BETWEEN, JUSTIFY_SPACE_AROUND, or JUSTIFY_SPACE_EVENLY\n * @example\n * ```typescript\n * const container = Node.create();\n * container.setJustifyContent(JUSTIFY_SPACE_BETWEEN); // Space children evenly with edges at start/end\n * ```\n */\n setJustifyContent(justify: number): void {\n this._style.justifyContent = justify\n this.markDirty()\n }\n\n // ============================================================================\n // Spacing Setters\n // ============================================================================\n\n /**\n * Set padding for one or more edges.\n *\n * @param edge - EDGE_LEFT, EDGE_TOP, EDGE_RIGHT, EDGE_BOTTOM, EDGE_HORIZONTAL, EDGE_VERTICAL, or EDGE_ALL\n * @param value - Padding in points\n * @example\n * ```typescript\n * node.setPadding(EDGE_ALL, 10); // Set 10pt padding on all edges\n * node.setPadding(EDGE_HORIZONTAL, 5); // Set 5pt padding on left and right\n * ```\n */\n setPadding(edge: number, value: number): void {\n setEdgeValue(this._style.padding, edge, value, C.UNIT_POINT)\n this.markDirty()\n }\n\n /**\n * Set padding as a percentage of the parent's width.\n * Per CSS spec, percentage padding always resolves against the containing block's width.\n *\n * @param edge - EDGE_LEFT, EDGE_TOP, EDGE_RIGHT, EDGE_BOTTOM, EDGE_HORIZONTAL, EDGE_VERTICAL, or EDGE_ALL\n * @param value - Padding as a percentage (0-100)\n */\n setPaddingPercent(edge: number, value: number): void {\n setEdgeValue(this._style.padding, edge, value, C.UNIT_PERCENT)\n this.markDirty()\n }\n\n /**\n * Set margin for one or more edges.\n *\n * @param edge - EDGE_LEFT, EDGE_TOP, EDGE_RIGHT, EDGE_BOTTOM, EDGE_HORIZONTAL, EDGE_VERTICAL, or EDGE_ALL\n * @param value - Margin in points\n * @example\n * ```typescript\n * node.setMargin(EDGE_ALL, 5); // Set 5pt margin on all edges\n * node.setMargin(EDGE_TOP, 10); // Set 10pt margin on top only\n * ```\n */\n setMargin(edge: number, value: number): void {\n setEdgeValue(this._style.margin, edge, value, C.UNIT_POINT)\n this.markDirty()\n }\n\n /**\n * Set margin as a percentage of the parent's size.\n *\n * @param edge - EDGE_LEFT, EDGE_TOP, EDGE_RIGHT, EDGE_BOTTOM, EDGE_HORIZONTAL, EDGE_VERTICAL, or EDGE_ALL\n * @param value - Margin as a percentage (0-100)\n */\n setMarginPercent(edge: number, value: number): void {\n setEdgeValue(this._style.margin, edge, value, C.UNIT_PERCENT)\n this.markDirty()\n }\n\n /**\n * Set margin to auto (for centering items with margin: auto).\n *\n * @param edge - EDGE_LEFT, EDGE_TOP, EDGE_RIGHT, EDGE_BOTTOM, EDGE_HORIZONTAL, EDGE_VERTICAL, or EDGE_ALL\n */\n setMarginAuto(edge: number): void {\n setEdgeValue(this._style.margin, edge, 0, C.UNIT_AUTO)\n this.markDirty()\n }\n\n /**\n * Set border width for one or more edges.\n *\n * @param edge - EDGE_LEFT, EDGE_TOP, EDGE_RIGHT, EDGE_BOTTOM, EDGE_HORIZONTAL, EDGE_VERTICAL, or EDGE_ALL\n * @param value - Border width in points\n */\n setBorder(edge: number, value: number): void {\n setEdgeBorder(this._style.border, edge, value)\n this.markDirty()\n }\n\n /**\n * Set gap between flex items.\n *\n * @param gutter - GUTTER_COLUMN (horizontal gap), GUTTER_ROW (vertical gap), or GUTTER_ALL (both)\n * @param value - Gap size in points\n * @example\n * ```typescript\n * container.setGap(GUTTER_ALL, 8); // Set 8pt gap between all items\n * container.setGap(GUTTER_COLUMN, 10); // Set 10pt horizontal gap only\n * ```\n */\n setGap(gutter: number, value: number): void {\n if (gutter === C.GUTTER_COLUMN) {\n this._style.gap[0] = value\n } else if (gutter === C.GUTTER_ROW) {\n this._style.gap[1] = value\n } else if (gutter === C.GUTTER_ALL) {\n this._style.gap[0] = value\n this._style.gap[1] = value\n }\n this.markDirty()\n }\n\n // ============================================================================\n // Position Setters\n // ============================================================================\n\n /**\n * Set the position type.\n *\n * @param positionType - POSITION_TYPE_STATIC, POSITION_TYPE_RELATIVE, or POSITION_TYPE_ABSOLUTE\n * @example\n * ```typescript\n * node.setPositionType(POSITION_TYPE_ABSOLUTE);\n * node.setPosition(EDGE_LEFT, 10);\n * node.setPosition(EDGE_TOP, 20);\n * ```\n */\n setPositionType(positionType: number): void {\n this._style.positionType = positionType\n this.markDirty()\n }\n\n /**\n * Set position offset for one or more edges.\n * Only applies when position type is ABSOLUTE or RELATIVE.\n *\n * @param edge - EDGE_LEFT, EDGE_TOP, EDGE_RIGHT, EDGE_BOTTOM, EDGE_HORIZONTAL, EDGE_VERTICAL, or EDGE_ALL\n * @param value - Position offset in points\n */\n setPosition(edge: number, value: number): void {\n // NaN means \"auto\" (unset) in Yoga API\n if (Number.isNaN(value)) {\n setEdgeValue(this._style.position, edge, 0, C.UNIT_UNDEFINED)\n } else {\n setEdgeValue(this._style.position, edge, value, C.UNIT_POINT)\n }\n this.markDirty()\n }\n\n /**\n * Set position offset as a percentage.\n *\n * @param edge - EDGE_LEFT, EDGE_TOP, EDGE_RIGHT, EDGE_BOTTOM, EDGE_HORIZONTAL, EDGE_VERTICAL, or EDGE_ALL\n * @param value - Position offset as a percentage of parent's corresponding dimension\n */\n setPositionPercent(edge: number, value: number): void {\n setEdgeValue(this._style.position, edge, value, C.UNIT_PERCENT)\n this.markDirty()\n }\n\n // ============================================================================\n // Other Setters\n // ============================================================================\n\n /**\n * Set the display type.\n *\n * @param display - DISPLAY_FLEX or DISPLAY_NONE\n */\n setDisplay(display: number): void {\n this._style.display = display\n this.markDirty()\n }\n\n /**\n * Set the overflow behavior.\n *\n * @param overflow - OVERFLOW_VISIBLE, OVERFLOW_HIDDEN, or OVERFLOW_SCROLL\n */\n setOverflow(overflow: number): void {\n this._style.overflow = overflow\n this.markDirty()\n }\n\n // ============================================================================\n // Style Getters\n // ============================================================================\n\n /**\n * Get the width style value.\n *\n * @returns Width value with unit (points, percent, or auto)\n */\n getWidth(): Value {\n return this._style.width\n }\n\n /**\n * Get the height style value.\n *\n * @returns Height value with unit (points, percent, or auto)\n */\n getHeight(): Value {\n return this._style.height\n }\n\n /**\n * Get the minimum width style value.\n *\n * @returns Minimum width value with unit\n */\n getMinWidth(): Value {\n return this._style.minWidth\n }\n\n /**\n * Get the minimum height style value.\n *\n * @returns Minimum height value with unit\n */\n getMinHeight(): Value {\n return this._style.minHeight\n }\n\n /**\n * Get the maximum width style value.\n *\n * @returns Maximum width value with unit\n */\n getMaxWidth(): Value {\n return this._style.maxWidth\n }\n\n /**\n * Get the maximum height style value.\n *\n * @returns Maximum height value with unit\n */\n getMaxHeight(): Value {\n return this._style.maxHeight\n }\n\n /**\n * Get the aspect ratio.\n *\n * @returns Aspect ratio value (NaN if not set)\n */\n getAspectRatio(): number {\n return this._style.aspectRatio\n }\n\n /**\n * Get the flex grow factor.\n *\n * @returns Flex grow value\n */\n getFlexGrow(): number {\n return this._style.flexGrow\n }\n\n /**\n * Get the flex shrink factor.\n *\n * @returns Flex shrink value\n */\n getFlexShrink(): number {\n return this._style.flexShrink\n }\n\n /**\n * Get the flex basis style value.\n *\n * @returns Flex basis value with unit\n */\n getFlexBasis(): Value {\n return this._style.flexBasis\n }\n\n /**\n * Get the flex direction.\n *\n * @returns Flex direction constant\n */\n getFlexDirection(): number {\n return this._style.flexDirection\n }\n\n /**\n * Get the flex wrap setting.\n *\n * @returns Flex wrap constant\n */\n getFlexWrap(): number {\n return this._style.flexWrap\n }\n\n /**\n * Get the align items setting.\n *\n * @returns Align items constant\n */\n getAlignItems(): number {\n return this._style.alignItems\n }\n\n /**\n * Get the align self setting.\n *\n * @returns Align self constant\n */\n getAlignSelf(): number {\n return this._style.alignSelf\n }\n\n /**\n * Get the align content setting.\n *\n * @returns Align content constant\n */\n getAlignContent(): number {\n return this._style.alignContent\n }\n\n /**\n * Get the justify content setting.\n *\n * @returns Justify content constant\n */\n getJustifyContent(): number {\n return this._style.justifyContent\n }\n\n /**\n * Get the padding for a specific edge.\n *\n * @param edge - EDGE_LEFT, EDGE_TOP, EDGE_RIGHT, or EDGE_BOTTOM\n * @returns Padding value with unit\n */\n getPadding(edge: number): Value {\n return getEdgeValue(this._style.padding, edge)\n }\n\n /**\n * Get the margin for a specific edge.\n *\n * @param edge - EDGE_LEFT, EDGE_TOP, EDGE_RIGHT, or EDGE_BOTTOM\n * @returns Margin value with unit\n */\n getMargin(edge: number): Value {\n return getEdgeValue(this._style.margin, edge)\n }\n\n /**\n * Get the border width for a specific edge.\n *\n * @param edge - EDGE_LEFT, EDGE_TOP, EDGE_RIGHT, or EDGE_BOTTOM\n * @returns Border width in points\n */\n getBorder(edge: number): number {\n return getEdgeBorderValue(this._style.border, edge)\n }\n\n /**\n * Get the position offset for a specific edge.\n *\n * @param edge - EDGE_LEFT, EDGE_TOP, EDGE_RIGHT, or EDGE_BOTTOM\n * @returns Position value with unit\n */\n getPosition(edge: number): Value {\n return getEdgeValue(this._style.position, edge)\n }\n\n /**\n * Get the position type.\n *\n * @returns Position type constant\n */\n getPositionType(): number {\n return this._style.positionType\n }\n\n /**\n * Get the display type.\n *\n * @returns Display constant\n */\n getDisplay(): number {\n return this._style.display\n }\n\n /**\n * Get the overflow setting.\n *\n * @returns Overflow constant\n */\n getOverflow(): number {\n return this._style.overflow\n }\n\n /**\n * Get the gap for column or row.\n *\n * @param gutter - GUTTER_COLUMN or GUTTER_ROW\n * @returns Gap size in points\n */\n getGap(gutter: number): number {\n if (gutter === C.GUTTER_COLUMN) {\n return this._style.gap[0]\n } else if (gutter === C.GUTTER_ROW) {\n return this._style.gap[1]\n }\n return this._style.gap[0] // Default to column gap\n }\n}\n","/**\n * Monospace text measurement.\n *\n * Terminal text: graphemeCount * charWidth, always 1 line (no wrapping).\n * This is the default for terminal UIs where 1 char = 1 cell.\n */\n\nimport type { FlexilyPlugin } from \"./create-flexily.js\"\nimport type { TextLayoutService, PreparedText, TextLayout, IntrinsicSizes } from \"./text-layout.js\"\n\nconst segmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" })\n\n/**\n * Create a monospace text measurement service.\n *\n * @param charWidth - Width of each character cell (default: 1 for terminal grids)\n * @param charHeight - Height of each character cell (default: 1 for terminal grids)\n */\nexport function createMonospaceMeasurer(charWidth = 1, charHeight = 1): TextLayoutService {\n return {\n prepare(input) {\n const { text } = input\n\n // Count grapheme clusters for proper emoji/CJK support\n let graphemeCount = 0\n for (const _ of segmenter.segment(text)) graphemeCount++\n\n const totalWidth = graphemeCount * charWidth\n\n const prepared: PreparedText = {\n intrinsicSizes(): IntrinsicSizes {\n return {\n minContentWidth: totalWidth, // monospace: entire text is one unbreakable segment\n maxContentWidth: totalWidth,\n }\n },\n\n layout(constraints): TextLayout {\n const width = constraints.maxWidth !== undefined ? Math.min(totalWidth, constraints.maxWidth) : totalWidth\n\n return {\n width,\n height: charHeight,\n lineCount: 1,\n firstBaseline: charHeight,\n lastBaseline: charHeight,\n truncated: width < totalWidth,\n }\n },\n }\n\n return prepared\n },\n }\n}\n\n/**\n * Plugin: add monospace text measurement to the engine.\n *\n * @param charWidth - Width per character cell (default: 1)\n * @param charHeight - Height per character cell (default: 1)\n */\nexport function withMonospace(charWidth = 1, charHeight = 1): FlexilyPlugin {\n return (engine) => {\n engine.textLayout = createMonospaceMeasurer(charWidth, charHeight)\n return engine\n }\n}\n","/**\n * Deterministic test text measurer.\n *\n * Fixed grapheme width table: Latin 0.8, CJK 1.0, emoji 1.8 (relative to fontSize).\n * Deterministic across platforms — use in tests and CI.\n * Supports word wrapping for realistic text layout testing.\n */\n\nimport type { FlexilyPlugin } from \"./create-flexily.js\"\nimport type { TextLayoutService, PreparedText, TextLayout, TextLine, IntrinsicSizes } from \"./text-layout.js\"\n\nconst segmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" })\n\n/** Measure a single grapheme cluster with the deterministic width table. */\nfunction graphemeWidth(grapheme: string, fontSize: number): number {\n const cp = grapheme.codePointAt(0) ?? 0\n\n // Emoji: ZWJ sequences, variation selectors, regional indicators\n if (\n (cp >= 0x1f300 && cp <= 0x1faff) ||\n (cp >= 0x2600 && cp <= 0x27bf) ||\n (cp >= 0xfe00 && cp <= 0xfe0f) ||\n cp === 0x200d ||\n (cp >= 0x1f900 && cp <= 0x1f9ff) ||\n grapheme.length > 2\n ) {\n return fontSize * 1.8\n }\n\n // CJK: Chinese, Japanese, Korean ideographs + fullwidth\n if (\n (cp >= 0x4e00 && cp <= 0x9fff) ||\n (cp >= 0x3000 && cp <= 0x303f) ||\n (cp >= 0x3040 && cp <= 0x309f) ||\n (cp >= 0x30a0 && cp <= 0x30ff) ||\n (cp >= 0xac00 && cp <= 0xd7af) ||\n (cp >= 0xff00 && cp <= 0xffef)\n ) {\n return fontSize * 1.0\n }\n\n // Latin and everything else\n return fontSize * 0.8\n}\n\n/** A word or whitespace segment for line breaking. */\ninterface TextSegment {\n text: string\n width: number\n isWhitespace: boolean\n}\n\nfunction segmentText(text: string, fontSize: number): TextSegment[] {\n const segments: TextSegment[] = []\n let current = \"\"\n let currentWidth = 0\n let isWhitespace = false\n\n for (const { segment } of segmenter.segment(text)) {\n const isSpace = segment === \" \" || segment === \"\\t\"\n\n if (segments.length === 0 && current === \"\") {\n isWhitespace = isSpace\n current = segment\n currentWidth = isSpace ? fontSize * 0.8 : graphemeWidth(segment, fontSize)\n continue\n }\n\n if (isSpace !== isWhitespace) {\n if (current) segments.push({ text: current, width: currentWidth, isWhitespace })\n current = segment\n currentWidth = isSpace ? fontSize * 0.8 : graphemeWidth(segment, fontSize)\n isWhitespace = isSpace\n } else {\n current += segment\n currentWidth += isSpace ? fontSize * 0.8 : graphemeWidth(segment, fontSize)\n }\n }\n\n if (current) segments.push({ text: current, width: currentWidth, isWhitespace })\n return segments\n}\n\nfunction measureString(text: string, fontSize: number): number {\n let width = 0\n for (const { segment } of segmenter.segment(text)) {\n width += graphemeWidth(segment, fontSize)\n }\n return width\n}\n\n/**\n * Create a deterministic text measurement service for testing.\n *\n * Uses fixed grapheme widths: Latin 0.8, CJK 1.0, emoji 1.8 (relative to fontSize).\n */\nexport function createTestMeasurer(): TextLayoutService {\n return {\n prepare(input) {\n const { text, style } = input\n const fontSize = style.fontSize\n const lineHeight = style.lineHeight || fontSize\n\n const segments = segmentText(text, fontSize)\n\n let maxContentWidth = 0\n let minContentWidth = 0\n for (const seg of segments) {\n maxContentWidth += seg.width\n if (!seg.isWhitespace && seg.width > minContentWidth) {\n minContentWidth = seg.width\n }\n }\n\n const prepared: PreparedText = {\n intrinsicSizes(): IntrinsicSizes {\n return { minContentWidth, maxContentWidth }\n },\n\n layout(constraints, options?): TextLayout {\n const maxWidth = constraints.maxWidth ?? Infinity\n const maxLines = constraints.maxLines ?? Infinity\n const wrap = constraints.wrap ?? \"normal\"\n const includeLines = options?.includeLines ?? false\n\n if (wrap === \"none\" || maxWidth >= maxContentWidth) {\n const truncated = maxLines < 1\n const width = constraints.shrinkWrap ? maxContentWidth : Math.min(maxWidth, maxContentWidth)\n return {\n width,\n height: truncated ? 0 : lineHeight,\n lineCount: truncated ? 0 : 1,\n firstBaseline: lineHeight,\n lastBaseline: lineHeight,\n truncated: maxWidth < maxContentWidth,\n lines: includeLines\n ? [{ text, width: maxContentWidth, startIndex: 0, endIndex: text.length }]\n : undefined,\n }\n }\n\n // Word wrapping\n const lines: TextLine[] = []\n let lineWidth = 0\n let lineText = \"\"\n let lineStart = 0\n let charIndex = 0\n\n for (const seg of segments) {\n if (seg.isWhitespace) {\n if (lineText) {\n lineWidth += seg.width\n lineText += seg.text\n }\n charIndex += seg.text.length\n continue\n }\n\n if (lineWidth + seg.width > maxWidth && lineText) {\n const trimmed = lineText.trimEnd()\n lines.push({\n text: trimmed,\n width: measureString(trimmed, fontSize),\n startIndex: lineStart,\n endIndex: charIndex,\n })\n if (lines.length >= maxLines) break\n\n lineText = seg.text\n lineWidth = seg.width\n lineStart = charIndex\n } else {\n lineText += seg.text\n lineWidth += seg.width\n }\n charIndex += seg.text.length\n }\n\n if (lineText && lines.length < maxLines) {\n const trimmed = lineText.trimEnd()\n lines.push({\n text: trimmed,\n width: measureString(trimmed, fontSize),\n startIndex: lineStart,\n endIndex: charIndex,\n })\n }\n\n const lineCount = lines.length\n const height = lineCount * lineHeight\n const widestLine = lines.reduce((max, l) => Math.max(max, l.width), 0)\n const width = constraints.shrinkWrap ? widestLine : Math.min(maxWidth, widestLine)\n\n return {\n width,\n height,\n lineCount,\n firstBaseline: lineHeight,\n lastBaseline: lineCount > 0 ? (lineCount - 1) * lineHeight + lineHeight : lineHeight,\n truncated: lines.length >= maxLines && charIndex < text.length,\n lines: includeLines ? lines : undefined,\n }\n },\n }\n\n return prepared\n },\n }\n}\n\n/**\n * Plugin: add deterministic test text measurement to the engine.\n */\nexport function withTestMeasurer(): FlexilyPlugin {\n return (engine) => {\n engine.textLayout = createTestMeasurer()\n return engine\n }\n}\n","/**\n * Flexily Layout Engine Adapter\n *\n * Wraps Flexily to implement the LayoutEngine interface.\n * Uses the default zero-allocation algorithm from flexily.\n */\n\nimport {\n ALIGN_AUTO,\n ALIGN_BASELINE,\n ALIGN_CENTER,\n ALIGN_FLEX_END,\n ALIGN_FLEX_START,\n ALIGN_SPACE_AROUND,\n ALIGN_SPACE_BETWEEN,\n ALIGN_SPACE_EVENLY,\n ALIGN_STRETCH,\n DIRECTION_LTR,\n DISPLAY_FLEX,\n DISPLAY_NONE,\n EDGE_ALL,\n EDGE_BOTTOM,\n EDGE_HORIZONTAL,\n EDGE_LEFT,\n EDGE_RIGHT,\n EDGE_TOP,\n EDGE_VERTICAL,\n // Constants\n FLEX_DIRECTION_COLUMN,\n FLEX_DIRECTION_COLUMN_REVERSE,\n FLEX_DIRECTION_ROW,\n FLEX_DIRECTION_ROW_REVERSE,\n Node as FlexilyNode,\n GUTTER_ALL,\n GUTTER_COLUMN,\n GUTTER_ROW,\n JUSTIFY_CENTER,\n JUSTIFY_FLEX_END,\n JUSTIFY_FLEX_START,\n JUSTIFY_SPACE_AROUND,\n JUSTIFY_SPACE_BETWEEN,\n JUSTIFY_SPACE_EVENLY,\n MEASURE_MODE_AT_MOST,\n MEASURE_MODE_EXACTLY,\n MEASURE_MODE_UNDEFINED,\n OVERFLOW_HIDDEN,\n OVERFLOW_SCROLL,\n OVERFLOW_VISIBLE,\n POSITION_TYPE_ABSOLUTE,\n POSITION_TYPE_RELATIVE,\n POSITION_TYPE_STATIC,\n WRAP_NO_WRAP,\n WRAP_WRAP,\n WRAP_WRAP_REVERSE,\n} from \"flexily\"\n\nimport type { LayoutNode, MeasureFunc, MeasureMode } from \"@silvery/ag/layout-types\"\nimport type {\n AlignValue,\n DirectionValue,\n DisplayValue,\n EdgeValue,\n FlexDirectionValue,\n GutterValue,\n JustifyValue,\n LayoutConstants,\n LayoutEngine,\n MeasureModeValue,\n OverflowValue,\n PositionTypeValue,\n WrapValue,\n} from \"../layout-engine\"\n\n// ============================================================================\n// Flexily Zero Node Adapter\n// ============================================================================\n\n/**\n * Wraps a Flexily zero-alloc node to implement LayoutNode interface.\n * Since Flexily already has a Yoga-compatible API, this is mostly delegation.\n */\nclass FlexilyZeroNodeAdapter implements LayoutNode {\n private node: FlexilyNode\n\n constructor(node: FlexilyNode) {\n this.node = node\n }\n\n /** Get the underlying Flexily node (for tree operations) */\n getFlexilyNode(): FlexilyNode {\n return this.node\n }\n\n // Tree operations\n insertChild(child: LayoutNode, index: number): void {\n const flexilyChild = (child as FlexilyZeroNodeAdapter).getFlexilyNode()\n this.node.insertChild(flexilyChild, index)\n }\n\n removeChild(child: LayoutNode): void {\n const flexilyChild = (child as FlexilyZeroNodeAdapter).getFlexilyNode()\n this.node.removeChild(flexilyChild)\n }\n\n free(): void {\n this.node.free()\n }\n\n // Measure function\n setMeasureFunc(measureFunc: MeasureFunc): void {\n this.node.setMeasureFunc((width, widthMode, height, heightMode) => {\n const widthModeStr = this.measureModeToString(widthMode)\n const heightModeStr = this.measureModeToString(heightMode)\n return measureFunc(width, widthModeStr, height, heightModeStr)\n })\n }\n\n // Dirty tracking - forces layout recalculation\n markDirty(): void {\n this.node.markDirty()\n }\n isDirty(): boolean {\n return this.node.isDirty()\n }\n\n private measureModeToString(mode: number): MeasureMode {\n if (mode === MEASURE_MODE_EXACTLY) return \"exactly\"\n if (mode === MEASURE_MODE_AT_MOST) return \"at-most\"\n return \"undefined\"\n }\n\n // Dimension setters\n setWidth(value: number): void {\n this.node.setWidth(value)\n }\n setWidthPercent(value: number): void {\n this.node.setWidthPercent(value)\n }\n setWidthAuto(): void {\n this.node.setWidthAuto()\n }\n setWidthFitContent(): void {\n this.node.setWidthFitContent()\n }\n setWidthSnugContent(): void {\n this.node.setWidthSnugContent()\n }\n setHeight(value: number): void {\n this.node.setHeight(value)\n }\n setHeightPercent(value: number): void {\n this.node.setHeightPercent(value)\n }\n setHeightAuto(): void {\n this.node.setHeightAuto()\n }\n setMinWidth(value: number): void {\n this.node.setMinWidth(value)\n }\n setMinWidthPercent(value: number): void {\n this.node.setMinWidthPercent(value)\n }\n setMinHeight(value: number): void {\n this.node.setMinHeight(value)\n }\n setMinHeightPercent(value: number): void {\n this.node.setMinHeightPercent(value)\n }\n setMaxWidth(value: number): void {\n this.node.setMaxWidth(value)\n }\n setMaxWidthPercent(value: number): void {\n this.node.setMaxWidthPercent(value)\n }\n setMaxHeight(value: number): void {\n this.node.setMaxHeight(value)\n }\n setMaxHeightPercent(value: number): void {\n this.node.setMaxHeightPercent(value)\n }\n\n // Flex properties\n setFlexGrow(value: number): void {\n this.node.setFlexGrow(value)\n }\n setFlexShrink(value: number): void {\n this.node.setFlexShrink(value)\n }\n setFlexBasis(value: number): void {\n this.node.setFlexBasis(value)\n }\n setFlexBasisPercent(value: number): void {\n this.node.setFlexBasisPercent(value)\n }\n setFlexBasisAuto(): void {\n this.node.setFlexBasisAuto()\n }\n setFlexDirection(direction: number): void {\n this.node.setFlexDirection(direction)\n }\n setFlexWrap(wrap: number): void {\n this.node.setFlexWrap(wrap)\n }\n\n // Alignment\n setAlignItems(align: number): void {\n this.node.setAlignItems(align)\n }\n setAlignSelf(align: number): void {\n this.node.setAlignSelf(align)\n }\n setAlignContent(align: number): void {\n this.node.setAlignContent(align)\n }\n setJustifyContent(justify: number): void {\n this.node.setJustifyContent(justify)\n }\n\n // Spacing\n setPadding(edge: number, value: number): void {\n this.node.setPadding(edge, value)\n }\n setMargin(edge: number, value: number): void {\n this.node.setMargin(edge, value)\n }\n setBorder(edge: number, value: number): void {\n this.node.setBorder(edge, value)\n }\n setGap(gutter: number, value: number): void {\n this.node.setGap(gutter, value)\n }\n\n // Display & Position\n setDisplay(display: number): void {\n this.node.setDisplay(display)\n }\n setPositionType(positionType: number): void {\n this.node.setPositionType(positionType)\n }\n setPosition(edge: number, value: number): void {\n this.node.setPosition(edge, value)\n }\n setPositionPercent(edge: number, value: number): void {\n this.node.setPositionPercent(edge, value)\n }\n setOverflow(overflow: number): void {\n this.node.setOverflow(overflow)\n }\n\n // Aspect Ratio\n setAspectRatio(value: number): void {\n this.node.setAspectRatio(value)\n }\n\n // Layout calculation\n calculateLayout(width: number, height: number, direction?: number): void {\n this.node.calculateLayout(width, height, direction ?? DIRECTION_LTR)\n }\n\n // Layout results\n getComputedLeft(): number {\n return this.node.getComputedLeft()\n }\n getComputedTop(): number {\n return this.node.getComputedTop()\n }\n getComputedWidth(): number {\n return this.node.getComputedWidth()\n }\n getComputedHeight(): number {\n return this.node.getComputedHeight()\n }\n}\n\n// ============================================================================\n// Flexily Zero Layout Engine\n// ============================================================================\n\n/**\n * Layout engine implementation using Flexily zero-allocation variant.\n * Optimized for high-frequency layout with reduced GC pressure.\n */\nexport class FlexilyZeroLayoutEngine implements LayoutEngine {\n private _constants: LayoutConstants = {\n // Flex Direction (cast from Flexily's plain numbers to branded types)\n FLEX_DIRECTION_COLUMN: FLEX_DIRECTION_COLUMN as FlexDirectionValue,\n FLEX_DIRECTION_COLUMN_REVERSE: FLEX_DIRECTION_COLUMN_REVERSE as FlexDirectionValue,\n FLEX_DIRECTION_ROW: FLEX_DIRECTION_ROW as FlexDirectionValue,\n FLEX_DIRECTION_ROW_REVERSE: FLEX_DIRECTION_ROW_REVERSE as FlexDirectionValue,\n\n // Wrap\n WRAP_NO_WRAP: WRAP_NO_WRAP as WrapValue,\n WRAP_WRAP: WRAP_WRAP as WrapValue,\n WRAP_WRAP_REVERSE: WRAP_WRAP_REVERSE as WrapValue,\n\n // Align\n ALIGN_AUTO: ALIGN_AUTO as AlignValue,\n ALIGN_FLEX_START: ALIGN_FLEX_START as AlignValue,\n ALIGN_CENTER: ALIGN_CENTER as AlignValue,\n ALIGN_FLEX_END: ALIGN_FLEX_END as AlignValue,\n ALIGN_STRETCH: ALIGN_STRETCH as AlignValue,\n ALIGN_BASELINE: ALIGN_BASELINE as AlignValue,\n ALIGN_SPACE_BETWEEN: ALIGN_SPACE_BETWEEN as AlignValue,\n ALIGN_SPACE_AROUND: ALIGN_SPACE_AROUND as AlignValue,\n ALIGN_SPACE_EVENLY: ALIGN_SPACE_EVENLY as AlignValue,\n\n // Justify\n JUSTIFY_FLEX_START: JUSTIFY_FLEX_START as JustifyValue,\n JUSTIFY_CENTER: JUSTIFY_CENTER as JustifyValue,\n JUSTIFY_FLEX_END: JUSTIFY_FLEX_END as JustifyValue,\n JUSTIFY_SPACE_BETWEEN: JUSTIFY_SPACE_BETWEEN as JustifyValue,\n JUSTIFY_SPACE_AROUND: JUSTIFY_SPACE_AROUND as JustifyValue,\n JUSTIFY_SPACE_EVENLY: JUSTIFY_SPACE_EVENLY as JustifyValue,\n\n // Edge\n EDGE_LEFT: EDGE_LEFT as EdgeValue,\n EDGE_TOP: EDGE_TOP as EdgeValue,\n EDGE_RIGHT: EDGE_RIGHT as EdgeValue,\n EDGE_BOTTOM: EDGE_BOTTOM as EdgeValue,\n EDGE_HORIZONTAL: EDGE_HORIZONTAL as EdgeValue,\n EDGE_VERTICAL: EDGE_VERTICAL as EdgeValue,\n EDGE_ALL: EDGE_ALL as EdgeValue,\n\n // Gutter\n GUTTER_COLUMN: GUTTER_COLUMN as GutterValue,\n GUTTER_ROW: GUTTER_ROW as GutterValue,\n GUTTER_ALL: GUTTER_ALL as GutterValue,\n\n // Display\n DISPLAY_FLEX: DISPLAY_FLEX as DisplayValue,\n DISPLAY_NONE: DISPLAY_NONE as DisplayValue,\n\n // Position Type\n POSITION_TYPE_STATIC: POSITION_TYPE_STATIC as PositionTypeValue,\n POSITION_TYPE_RELATIVE: POSITION_TYPE_RELATIVE as PositionTypeValue,\n POSITION_TYPE_ABSOLUTE: POSITION_TYPE_ABSOLUTE as PositionTypeValue,\n\n // Overflow\n OVERFLOW_VISIBLE: OVERFLOW_VISIBLE as OverflowValue,\n OVERFLOW_HIDDEN: OVERFLOW_HIDDEN as OverflowValue,\n OVERFLOW_SCROLL: OVERFLOW_SCROLL as OverflowValue,\n\n // Direction\n DIRECTION_LTR: DIRECTION_LTR as DirectionValue,\n\n // Measure Mode\n MEASURE_MODE_UNDEFINED: MEASURE_MODE_UNDEFINED as MeasureModeValue,\n MEASURE_MODE_EXACTLY: MEASURE_MODE_EXACTLY as MeasureModeValue,\n MEASURE_MODE_AT_MOST: MEASURE_MODE_AT_MOST as MeasureModeValue,\n }\n\n createNode(): LayoutNode {\n return new FlexilyZeroNodeAdapter(FlexilyNode.create())\n }\n\n get constants(): LayoutConstants {\n return this._constants\n }\n\n get name(): string {\n return \"flexily-zero\"\n }\n}\n\n// ============================================================================\n// Initialization Helper\n// ============================================================================\n\n/**\n * Create a Flexily zero-allocation layout engine.\n * Unlike Yoga, Flexily doesn't require async initialization.\n */\nexport function createFlexilyZeroEngine(): FlexilyZeroLayoutEngine {\n return new FlexilyZeroLayoutEngine()\n}\n"],"x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12],"mappings":"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"}
|