@react-x11/components 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -4
- package/dist/charts/node.d.ts +11 -1
- package/dist/charts/node.d.ts.map +1 -1
- package/dist/charts/node.js +44 -14
- package/dist/charts/node.js.map +1 -1
- package/dist/charts/render.d.ts +12 -3
- package/dist/charts/render.d.ts.map +1 -1
- package/dist/charts/render.js +94 -25
- package/dist/charts/render.js.map +1 -1
- package/dist/code/index.d.ts.map +1 -1
- package/dist/code/index.js +27 -24
- package/dist/code/index.js.map +1 -1
- package/dist/code-editor/completion.d.ts.map +1 -1
- package/dist/code-editor/completion.js +3 -2
- package/dist/code-editor/completion.js.map +1 -1
- package/dist/code-editor/index.d.ts.map +1 -1
- package/dist/code-editor/index.js +19 -0
- package/dist/code-editor/index.js.map +1 -1
- package/dist/code-editor/node.d.ts +177 -7
- package/dist/code-editor/node.d.ts.map +1 -1
- package/dist/code-editor/node.js +1329 -164
- package/dist/code-editor/node.js.map +1 -1
- package/dist/code-language/index.d.ts +1 -1
- package/dist/code-language/index.d.ts.map +1 -1
- package/dist/code-language/index.js +1 -1
- package/dist/code-language/index.js.map +1 -1
- package/dist/code-language/languages/glsl.d.ts.map +1 -1
- package/dist/code-language/languages/glsl.js +10 -2
- package/dist/code-language/languages/glsl.js.map +1 -1
- package/dist/code-language/languages/javascript.d.ts.map +1 -1
- package/dist/code-language/languages/javascript.js +18 -3
- package/dist/code-language/languages/javascript.js.map +1 -1
- package/dist/code-language/languages/json.d.ts.map +1 -1
- package/dist/code-language/languages/json.js +10 -2
- package/dist/code-language/languages/json.js.map +1 -1
- package/dist/code-language/languages/shell.d.ts.map +1 -1
- package/dist/code-language/languages/shell.js +10 -2
- package/dist/code-language/languages/shell.js.map +1 -1
- package/dist/code-language/languages/sql.d.ts.map +1 -1
- package/dist/code-language/languages/sql.js +20 -2
- package/dist/code-language/languages/sql.js.map +1 -1
- package/dist/code-language/runs.d.ts +31 -0
- package/dist/code-language/runs.d.ts.map +1 -1
- package/dist/code-language/runs.js +105 -0
- package/dist/code-language/runs.js.map +1 -1
- package/dist/code-language/stream.d.ts +22 -0
- package/dist/code-language/stream.d.ts.map +1 -1
- package/dist/code-language/stream.js +259 -9
- package/dist/code-language/stream.js.map +1 -1
- package/dist/code-language/types.d.ts +5 -4
- package/dist/code-language/types.d.ts.map +1 -1
- package/dist/codeblock/index.d.ts +26 -2
- package/dist/codeblock/index.d.ts.map +1 -1
- package/dist/codeblock/index.js +57 -4
- package/dist/codeblock/index.js.map +1 -1
- package/dist/flow/draw.d.ts +50 -0
- package/dist/flow/draw.d.ts.map +1 -1
- package/dist/flow/draw.js +132 -33
- package/dist/flow/draw.js.map +1 -1
- package/dist/flow/gl/color.d.ts +13 -0
- package/dist/flow/gl/color.d.ts.map +1 -0
- package/dist/flow/gl/color.js +82 -0
- package/dist/flow/gl/color.js.map +1 -0
- package/dist/flow/gl/index.d.ts +60 -0
- package/dist/flow/gl/index.d.ts.map +1 -0
- package/dist/flow/gl/index.js +283 -0
- package/dist/flow/gl/index.js.map +1 -0
- package/dist/flow/gl/pack.d.ts +133 -0
- package/dist/flow/gl/pack.d.ts.map +1 -0
- package/dist/flow/gl/pack.js +408 -0
- package/dist/flow/gl/pack.js.map +1 -0
- package/dist/flow/gl/renderer.d.ts +95 -0
- package/dist/flow/gl/renderer.d.ts.map +1 -0
- package/dist/flow/gl/renderer.js +459 -0
- package/dist/flow/gl/renderer.js.map +1 -0
- package/dist/flow/gl/shaders.d.ts +79 -0
- package/dist/flow/gl/shaders.d.ts.map +1 -0
- package/dist/flow/gl/shaders.js +346 -0
- package/dist/flow/gl/shaders.js.map +1 -0
- package/dist/flow/gl/text.d.ts +318 -0
- package/dist/flow/gl/text.d.ts.map +1 -0
- package/dist/flow/gl/text.js +1103 -0
- package/dist/flow/gl/text.js.map +1 -0
- package/dist/flow/index.d.ts +1 -1
- package/dist/flow/index.d.ts.map +1 -1
- package/dist/flow/index.js +619 -64
- package/dist/flow/index.js.map +1 -1
- package/dist/flow/node.d.ts +621 -72
- package/dist/flow/node.d.ts.map +1 -1
- package/dist/flow/node.js +2253 -1018
- package/dist/flow/node.js.map +1 -1
- package/dist/flow/paint.d.ts +35 -0
- package/dist/flow/paint.d.ts.map +1 -0
- package/dist/flow/paint.js +393 -0
- package/dist/flow/paint.js.map +1 -0
- package/dist/flow/paths.d.ts +14 -0
- package/dist/flow/paths.d.ts.map +1 -1
- package/dist/flow/paths.js +45 -19
- package/dist/flow/paths.js.map +1 -1
- package/dist/flow/scene.d.ts +584 -0
- package/dist/flow/scene.d.ts.map +1 -0
- package/dist/flow/scene.js +1453 -0
- package/dist/flow/scene.js.map +1 -0
- package/dist/flow/types.d.ts +111 -1
- package/dist/flow/types.d.ts.map +1 -1
- package/dist/html/controls.d.ts +28 -0
- package/dist/html/controls.d.ts.map +1 -1
- package/dist/html/controls.js +52 -2
- package/dist/html/controls.js.map +1 -1
- package/dist/html/css/calc.d.ts +14 -0
- package/dist/html/css/calc.d.ts.map +1 -0
- package/dist/html/css/calc.js +344 -0
- package/dist/html/css/calc.js.map +1 -0
- package/dist/html/css/cascade.d.ts +262 -6
- package/dist/html/css/cascade.d.ts.map +1 -1
- package/dist/html/css/cascade.js +1373 -67
- package/dist/html/css/cascade.js.map +1 -1
- package/dist/html/css/color.d.ts +23 -0
- package/dist/html/css/color.d.ts.map +1 -0
- package/dist/html/css/color.js +740 -0
- package/dist/html/css/color.js.map +1 -0
- package/dist/html/css/content.d.ts +92 -0
- package/dist/html/css/content.d.ts.map +1 -0
- package/dist/html/css/content.js +388 -0
- package/dist/html/css/content.js.map +1 -0
- package/dist/html/css/counter-styles.d.ts +76 -0
- package/dist/html/css/counter-styles.d.ts.map +1 -0
- package/dist/html/css/counter-styles.js +893 -0
- package/dist/html/css/counter-styles.js.map +1 -0
- package/dist/html/css/decode.d.ts +12 -0
- package/dist/html/css/decode.d.ts.map +1 -0
- package/dist/html/css/decode.js +116 -0
- package/dist/html/css/decode.js.map +1 -0
- package/dist/html/css/parse.d.ts +110 -10
- package/dist/html/css/parse.d.ts.map +1 -1
- package/dist/html/css/parse.js +1473 -180
- package/dist/html/css/parse.js.map +1 -1
- package/dist/html/css/style.d.ts +501 -15
- package/dist/html/css/style.d.ts.map +1 -1
- package/dist/html/css/style.js +3729 -206
- package/dist/html/css/style.js.map +1 -1
- package/dist/html/css/ua.d.ts.map +1 -1
- package/dist/html/css/ua.js +65 -16
- package/dist/html/css/ua.js.map +1 -1
- package/dist/html/css/values.d.ts +37 -3
- package/dist/html/css/values.d.ts.map +1 -1
- package/dist/html/css/values.js +122 -48
- package/dist/html/css/values.js.map +1 -1
- package/dist/html/css/vars.d.ts +52 -0
- package/dist/html/css/vars.d.ts.map +1 -0
- package/dist/html/css/vars.js +358 -0
- package/dist/html/css/vars.js.map +1 -0
- package/dist/html/dom.d.ts +30 -4
- package/dist/html/dom.d.ts.map +1 -1
- package/dist/html/dom.js +278 -17
- package/dist/html/dom.js.map +1 -1
- package/dist/html/fonts.d.ts +106 -0
- package/dist/html/fonts.d.ts.map +1 -0
- package/dist/html/fonts.js +565 -0
- package/dist/html/fonts.js.map +1 -0
- package/dist/html/gif.d.ts +15 -0
- package/dist/html/gif.d.ts.map +1 -0
- package/dist/html/gif.js +229 -0
- package/dist/html/gif.js.map +1 -0
- package/dist/html/index.d.ts +50 -11
- package/dist/html/index.d.ts.map +1 -1
- package/dist/html/index.js +115 -9
- package/dist/html/index.js.map +1 -1
- package/dist/html/layout/block.d.ts +226 -3
- package/dist/html/layout/block.d.ts.map +1 -1
- package/dist/html/layout/block.js +3077 -219
- package/dist/html/layout/block.js.map +1 -1
- package/dist/html/layout/boxes.d.ts +367 -17
- package/dist/html/layout/boxes.d.ts.map +1 -1
- package/dist/html/layout/boxes.js +1742 -182
- package/dist/html/layout/boxes.js.map +1 -1
- package/dist/html/layout/cache.d.ts +58 -0
- package/dist/html/layout/cache.d.ts.map +1 -0
- package/dist/html/layout/cache.js +224 -0
- package/dist/html/layout/cache.js.map +1 -0
- package/dist/html/layout/collapse.d.ts +45 -0
- package/dist/html/layout/collapse.d.ts.map +1 -0
- package/dist/html/layout/collapse.js +246 -0
- package/dist/html/layout/collapse.js.map +1 -0
- package/dist/html/layout/css-grid.d.ts +7 -0
- package/dist/html/layout/css-grid.d.ts.map +1 -0
- package/dist/html/layout/css-grid.js +900 -0
- package/dist/html/layout/css-grid.js.map +1 -0
- package/dist/html/layout/flex.d.ts.map +1 -1
- package/dist/html/layout/flex.js +1025 -89
- package/dist/html/layout/flex.js.map +1 -1
- package/dist/html/layout/floats.d.ts +45 -6
- package/dist/html/layout/floats.d.ts.map +1 -1
- package/dist/html/layout/floats.js +113 -14
- package/dist/html/layout/floats.js.map +1 -1
- package/dist/html/layout/grid-lines.d.ts +39 -0
- package/dist/html/layout/grid-lines.d.ts.map +1 -0
- package/dist/html/layout/grid-lines.js +119 -0
- package/dist/html/layout/grid-lines.js.map +1 -0
- package/dist/html/layout/grid.d.ts +53 -0
- package/dist/html/layout/grid.d.ts.map +1 -0
- package/dist/html/layout/grid.js +153 -0
- package/dist/html/layout/grid.js.map +1 -0
- package/dist/html/layout/inline.d.ts +154 -1
- package/dist/html/layout/inline.d.ts.map +1 -1
- package/dist/html/layout/inline.js +3598 -175
- package/dist/html/layout/inline.js.map +1 -1
- package/dist/html/layout/shaping.d.ts +6 -0
- package/dist/html/layout/shaping.d.ts.map +1 -0
- package/dist/html/layout/shaping.js +100 -0
- package/dist/html/layout/shaping.js.map +1 -0
- package/dist/html/layout/table.d.ts +3 -0
- package/dist/html/layout/table.d.ts.map +1 -1
- package/dist/html/layout/table.js +681 -175
- package/dist/html/layout/table.js.map +1 -1
- package/dist/html/layout/tracks.d.ts +44 -0
- package/dist/html/layout/tracks.d.ts.map +1 -0
- package/dist/html/layout/tracks.js +349 -0
- package/dist/html/layout/tracks.js.map +1 -0
- package/dist/html/node.d.ts +169 -4
- package/dist/html/node.d.ts.map +1 -1
- package/dist/html/node.js +1429 -137
- package/dist/html/node.js.map +1 -1
- package/dist/html/paint.d.ts +92 -3
- package/dist/html/paint.d.ts.map +1 -1
- package/dist/html/paint.js +3635 -107
- package/dist/html/paint.js.map +1 -1
- package/dist/html/resources.d.ts +60 -14
- package/dist/html/resources.d.ts.map +1 -1
- package/dist/html/resources.js +122 -36
- package/dist/html/resources.js.map +1 -1
- package/dist/html/surfaces.d.ts +23 -0
- package/dist/html/surfaces.d.ts.map +1 -0
- package/dist/html/surfaces.js +68 -0
- package/dist/html/surfaces.js.map +1 -0
- package/dist/html/svg.d.ts +80 -0
- package/dist/html/svg.d.ts.map +1 -0
- package/dist/html/svg.js +442 -0
- package/dist/html/svg.js.map +1 -0
- package/dist/html/url.d.ts +23 -0
- package/dist/html/url.d.ts.map +1 -0
- package/dist/html/url.js +80 -0
- package/dist/html/url.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/internal/codelines.d.ts +42 -0
- package/dist/internal/codelines.d.ts.map +1 -0
- package/dist/internal/codelines.js +170 -0
- package/dist/internal/codelines.js.map +1 -0
- package/dist/internal/collate.d.ts +3 -0
- package/dist/internal/collate.d.ts.map +1 -0
- package/dist/internal/collate.js +11 -0
- package/dist/internal/collate.js.map +1 -0
- package/dist/internal/markdown/ast.d.ts +11 -0
- package/dist/internal/markdown/ast.d.ts.map +1 -1
- package/dist/internal/markdown/parse.d.ts.map +1 -1
- package/dist/internal/markdown/parse.js +109 -8
- package/dist/internal/markdown/parse.js.map +1 -1
- package/dist/internal/prewarm.d.ts +18 -0
- package/dist/internal/prewarm.d.ts.map +1 -0
- package/dist/internal/prewarm.js +42 -0
- package/dist/internal/prewarm.js.map +1 -0
- package/dist/internal/sdf.d.ts +20 -0
- package/dist/internal/sdf.d.ts.map +1 -0
- package/dist/internal/sdf.js +216 -0
- package/dist/internal/sdf.js.map +1 -0
- package/dist/internal/splice.d.ts +12 -0
- package/dist/internal/splice.d.ts.map +1 -0
- package/dist/internal/splice.js +23 -0
- package/dist/internal/splice.js.map +1 -0
- package/dist/internal/window.d.ts +12 -0
- package/dist/internal/window.d.ts.map +1 -1
- package/dist/internal/window.js +23 -6
- package/dist/internal/window.js.map +1 -1
- package/dist/maps/anchors.d.ts +6 -1
- package/dist/maps/anchors.d.ts.map +1 -1
- package/dist/maps/anchors.js +260 -1
- package/dist/maps/anchors.js.map +1 -1
- package/dist/maps/controller.d.ts +57 -0
- package/dist/maps/controller.d.ts.map +1 -1
- package/dist/maps/controller.js +97 -18
- package/dist/maps/controller.js.map +1 -1
- package/dist/maps/gl/buckets.d.ts +5 -1
- package/dist/maps/gl/buckets.d.ts.map +1 -1
- package/dist/maps/gl/buckets.js +5 -2
- package/dist/maps/gl/buckets.js.map +1 -1
- package/dist/maps/gl/build-worker.d.ts +2 -0
- package/dist/maps/gl/build-worker.d.ts.map +1 -1
- package/dist/maps/gl/build-worker.js +1 -1
- package/dist/maps/gl/build-worker.js.map +1 -1
- package/dist/maps/gl/cover.d.ts +23 -4
- package/dist/maps/gl/cover.d.ts.map +1 -1
- package/dist/maps/gl/cover.js +61 -48
- package/dist/maps/gl/cover.js.map +1 -1
- package/dist/maps/gl/placement.d.ts +21 -8
- package/dist/maps/gl/placement.d.ts.map +1 -1
- package/dist/maps/gl/placement.js +133 -58
- package/dist/maps/gl/placement.js.map +1 -1
- package/dist/maps/gl/renderer.d.ts +36 -4
- package/dist/maps/gl/renderer.d.ts.map +1 -1
- package/dist/maps/gl/renderer.js +81 -24
- package/dist/maps/gl/renderer.js.map +1 -1
- package/dist/maps/gl/shaders.d.ts +18 -17
- package/dist/maps/gl/shaders.d.ts.map +1 -1
- package/dist/maps/gl/shaders.js +34 -32
- package/dist/maps/gl/shaders.js.map +1 -1
- package/dist/maps/gl/store.d.ts +10 -0
- package/dist/maps/gl/store.d.ts.map +1 -1
- package/dist/maps/gl/store.js +47 -4
- package/dist/maps/gl/store.js.map +1 -1
- package/dist/maps/gl/text.d.ts +153 -24
- package/dist/maps/gl/text.d.ts.map +1 -1
- package/dist/maps/gl/text.js +379 -63
- package/dist/maps/gl/text.js.map +1 -1
- package/dist/maps/gl/view.d.ts +293 -2
- package/dist/maps/gl/view.d.ts.map +1 -1
- package/dist/maps/gl/view.js +317 -82
- package/dist/maps/gl/view.js.map +1 -1
- package/dist/maps/icons.d.ts +32 -0
- package/dist/maps/icons.d.ts.map +1 -0
- package/dist/maps/icons.js +151 -0
- package/dist/maps/icons.js.map +1 -0
- package/dist/maps/index.d.ts +2 -0
- package/dist/maps/index.d.ts.map +1 -1
- package/dist/maps/index.js +2 -0
- package/dist/maps/index.js.map +1 -1
- package/dist/maps/labels.d.ts +56 -4
- package/dist/maps/labels.d.ts.map +1 -1
- package/dist/maps/labels.js +213 -46
- package/dist/maps/labels.js.map +1 -1
- package/dist/maps/node.d.ts +17 -0
- package/dist/maps/node.d.ts.map +1 -1
- package/dist/maps/node.js +64 -30
- package/dist/maps/node.js.map +1 -1
- package/dist/maps/proj.d.ts +48 -0
- package/dist/maps/proj.d.ts.map +1 -1
- package/dist/maps/proj.js +73 -0
- package/dist/maps/proj.js.map +1 -1
- package/dist/maps/sources.d.ts +5 -3
- package/dist/maps/sources.d.ts.map +1 -1
- package/dist/maps/sources.js +5 -3
- package/dist/maps/sources.js.map +1 -1
- package/dist/maps/style.d.ts +35 -0
- package/dist/maps/style.d.ts.map +1 -1
- package/dist/maps/style.js.map +1 -1
- package/dist/maps/styles.d.ts +12 -0
- package/dist/maps/styles.d.ts.map +1 -1
- package/dist/maps/styles.js +120 -6
- package/dist/maps/styles.js.map +1 -1
- package/dist/maps/tiles.d.ts +31 -11
- package/dist/maps/tiles.d.ts.map +1 -1
- package/dist/maps/tiles.js +61 -27
- package/dist/maps/tiles.js.map +1 -1
- package/dist/maps/types.d.ts +28 -4
- package/dist/maps/types.d.ts.map +1 -1
- package/dist/markdown/index.d.ts.map +1 -1
- package/dist/markdown/index.js +209 -68
- package/dist/markdown/index.js.map +1 -1
- package/dist/markdown/spans.d.ts.map +1 -1
- package/dist/markdown/spans.js +6 -0
- package/dist/markdown/spans.js.map +1 -1
- package/dist/qml/containers.d.ts.map +1 -1
- package/dist/qml/containers.js +6 -1
- package/dist/qml/containers.js.map +1 -1
- package/dist/qml/interaction.d.ts.map +1 -1
- package/dist/qml/interaction.js +38 -5
- package/dist/qml/interaction.js.map +1 -1
- package/dist/qml/layouts.d.ts.map +1 -1
- package/dist/qml/layouts.js +21 -6
- package/dist/qml/layouts.js.map +1 -1
- package/dist/qml/qtquick.d.ts.map +1 -1
- package/dist/qml/qtquick.js +9 -2
- package/dist/qml/qtquick.js.map +1 -1
- package/dist/qml/react.d.ts.map +1 -1
- package/dist/qml/react.js +9 -7
- package/dist/qml/react.js.map +1 -1
- package/dist/reorder/clock.d.ts +7 -0
- package/dist/reorder/clock.d.ts.map +1 -0
- package/dist/reorder/clock.js +26 -0
- package/dist/reorder/clock.js.map +1 -0
- package/dist/reorder/index.d.ts +25 -3
- package/dist/reorder/index.d.ts.map +1 -1
- package/dist/reorder/index.js +64 -19
- package/dist/reorder/index.js.map +1 -1
- package/dist/rich-text-editor/index.d.ts +0 -11
- package/dist/rich-text-editor/index.d.ts.map +1 -1
- package/dist/rich-text-editor/index.js +38 -9
- package/dist/rich-text-editor/index.js.map +1 -1
- package/dist/rich-text-editor/keymap.d.ts.map +1 -1
- package/dist/rich-text-editor/keymap.js +2 -1
- package/dist/rich-text-editor/keymap.js.map +1 -1
- package/dist/rich-text-editor/keys.d.ts +17 -6
- package/dist/rich-text-editor/keys.d.ts.map +1 -1
- package/dist/rich-text-editor/keys.js +135 -26
- package/dist/rich-text-editor/keys.js.map +1 -1
- package/dist/rich-text-editor/markdown.d.ts.map +1 -1
- package/dist/rich-text-editor/markdown.js +30 -1
- package/dist/rich-text-editor/markdown.js.map +1 -1
- package/dist/rich-text-editor/marks.d.ts +9 -0
- package/dist/rich-text-editor/marks.d.ts.map +1 -0
- package/dist/rich-text-editor/marks.js +83 -0
- package/dist/rich-text-editor/marks.js.map +1 -0
- package/dist/rich-text-editor/render.d.ts.map +1 -1
- package/dist/rich-text-editor/render.js +28 -10
- package/dist/rich-text-editor/render.js.map +1 -1
- package/dist/rich-text-editor/replace.d.ts +13 -0
- package/dist/rich-text-editor/replace.d.ts.map +1 -0
- package/dist/rich-text-editor/replace.js +64 -0
- package/dist/rich-text-editor/replace.js.map +1 -0
- package/dist/rich-text-editor/toolbar.d.ts.map +1 -1
- package/dist/rich-text-editor/toolbar.js +1 -1
- package/dist/rich-text-editor/toolbar.js.map +1 -1
- package/dist/rich-text-editor/virtual.d.ts.map +1 -1
- package/dist/rich-text-editor/virtual.js +17 -0
- package/dist/rich-text-editor/virtual.js.map +1 -1
- package/dist/richtext/node.d.ts +46 -2
- package/dist/richtext/node.d.ts.map +1 -1
- package/dist/richtext/node.js +187 -4
- package/dist/richtext/node.js.map +1 -1
- package/dist/richtext/runs.d.ts +13 -8
- package/dist/richtext/runs.d.ts.map +1 -1
- package/dist/richtext/runs.js +18 -8
- package/dist/richtext/runs.js.map +1 -1
- package/dist/table/index.d.ts.map +1 -1
- package/dist/table/index.js +23 -0
- package/dist/table/index.js.map +1 -1
- package/dist/table/rows.d.ts +3 -2
- package/dist/table/rows.d.ts.map +1 -1
- package/dist/table/rows.js +20 -6
- package/dist/table/rows.js.map +1 -1
- package/dist/terminal/index.d.ts.map +1 -1
- package/dist/terminal/index.js +4 -0
- package/dist/terminal/index.js.map +1 -1
- package/dist/terminal/vt/pty.d.ts +13 -2
- package/dist/terminal/vt/pty.d.ts.map +1 -1
- package/dist/terminal/vt/pty.js +18 -3
- package/dist/terminal/vt/pty.js.map +1 -1
- package/dist/terminal-output/index.d.ts.map +1 -1
- package/dist/terminal-output/index.js +103 -23
- package/dist/terminal-output/index.js.map +1 -1
- package/dist/terminal-output/runs.d.ts +4 -1
- package/dist/terminal-output/runs.d.ts.map +1 -1
- package/dist/terminal-output/runs.js +5 -1
- package/dist/terminal-output/runs.js.map +1 -1
- package/dist/three/canvas.d.ts.map +1 -1
- package/dist/three/canvas.js +85 -7
- package/dist/three/canvas.js.map +1 -1
- package/dist/three/events.d.ts +22 -4
- package/dist/three/events.d.ts.map +1 -1
- package/dist/three/events.js +34 -4
- package/dist/three/events.js.map +1 -1
- package/dist/tree/index.d.ts.map +1 -1
- package/dist/tree/index.js +17 -0
- package/dist/tree/index.js.map +1 -1
- package/package.json +42 -33
- package/src/charts/node.ts +62 -26
- package/src/charts/render.ts +120 -30
- package/src/code/index.ts +36 -32
- package/src/code-editor/completion.ts +3 -2
- package/src/code-editor/index.ts +19 -0
- package/src/code-editor/node.ts +1574 -184
- package/src/code-language/index.ts +1 -1
- package/src/code-language/languages/glsl.ts +12 -2
- package/src/code-language/languages/javascript.ts +21 -4
- package/src/code-language/languages/json.ts +12 -2
- package/src/code-language/languages/shell.ts +12 -2
- package/src/code-language/languages/sql.ts +22 -2
- package/src/code-language/runs.ts +111 -1
- package/src/code-language/stream.ts +257 -17
- package/src/code-language/types.ts +5 -4
- package/src/codeblock/index.ts +68 -4
- package/src/flow/draw.ts +167 -41
- package/src/flow/gl/color.ts +85 -0
- package/src/flow/gl/index.ts +342 -0
- package/src/flow/gl/pack.ts +585 -0
- package/src/flow/gl/renderer.ts +679 -0
- package/src/flow/gl/shaders.ts +371 -0
- package/src/flow/gl/text.ts +1295 -0
- package/src/flow/index.ts +794 -67
- package/src/flow/node.ts +2496 -1256
- package/src/flow/paint.ts +511 -0
- package/src/flow/paths.ts +80 -15
- package/src/flow/scene.ts +2199 -0
- package/src/flow/types.ts +113 -1
- package/src/html/controls.ts +73 -2
- package/src/html/css/calc.ts +385 -0
- package/src/html/css/cascade.ts +1481 -62
- package/src/html/css/color.ts +755 -0
- package/src/html/css/content.ts +417 -0
- package/src/html/css/counter-styles.ts +973 -0
- package/src/html/css/decode.ts +130 -0
- package/src/html/css/parse.ts +1514 -160
- package/src/html/css/style.ts +4131 -223
- package/src/html/css/ua.ts +66 -17
- package/src/html/css/values.ts +150 -50
- package/src/html/css/vars.ts +348 -0
- package/src/html/dom.ts +284 -17
- package/src/html/fonts.ts +641 -0
- package/src/html/gif.ts +233 -0
- package/src/html/index.ts +180 -20
- package/src/html/layout/block.ts +3560 -208
- package/src/html/layout/boxes.ts +2141 -190
- package/src/html/layout/cache.ts +289 -0
- package/src/html/layout/collapse.ts +317 -0
- package/src/html/layout/css-grid.ts +1063 -0
- package/src/html/layout/flex.ts +1115 -106
- package/src/html/layout/floats.ts +128 -14
- package/src/html/layout/grid-lines.ts +141 -0
- package/src/html/layout/grid.ts +181 -0
- package/src/html/layout/inline.ts +4187 -192
- package/src/html/layout/shaping.ts +140 -0
- package/src/html/layout/table.ts +696 -186
- package/src/html/layout/tracks.ts +437 -0
- package/src/html/node.ts +1585 -156
- package/src/html/paint.ts +4582 -267
- package/src/html/resources.ts +161 -50
- package/src/html/surfaces.ts +81 -0
- package/src/html/svg.ts +504 -0
- package/src/html/url.ts +86 -0
- package/src/index.ts +2 -0
- package/src/internal/codelines.ts +200 -0
- package/src/internal/collate.ts +12 -0
- package/src/internal/markdown/ast.ts +11 -0
- package/src/internal/markdown/parse.ts +154 -11
- package/src/internal/prewarm.ts +45 -0
- package/src/internal/sdf.ts +227 -0
- package/src/internal/splice.ts +25 -0
- package/src/internal/window.ts +36 -5
- package/src/maps/anchors.ts +307 -1
- package/src/maps/controller.ts +116 -31
- package/src/maps/gl/buckets.ts +5 -1
- package/src/maps/gl/build-worker.ts +13 -2
- package/src/maps/gl/cover.ts +79 -44
- package/src/maps/gl/placement.ts +221 -69
- package/src/maps/gl/renderer.ts +104 -20
- package/src/maps/gl/shaders.ts +35 -32
- package/src/maps/gl/store.ts +66 -17
- package/src/maps/gl/text.ts +444 -71
- package/src/maps/gl/view.ts +361 -96
- package/src/maps/icons.ts +183 -0
- package/src/maps/index.ts +4 -0
- package/src/maps/labels.ts +269 -49
- package/src/maps/node.ts +82 -49
- package/src/maps/proj.ts +87 -0
- package/src/maps/sources.ts +5 -3
- package/src/maps/style.ts +32 -0
- package/src/maps/styles.ts +215 -4
- package/src/maps/tiles.ts +64 -31
- package/src/maps/types.ts +28 -4
- package/src/markdown/index.ts +293 -92
- package/src/markdown/spans.ts +5 -0
- package/src/qml/containers.tsx +6 -1
- package/src/qml/interaction.tsx +42 -5
- package/src/qml/layouts.tsx +21 -6
- package/src/qml/qtquick.tsx +9 -2
- package/src/qml/react.tsx +7 -5
- package/src/reorder/clock.ts +27 -0
- package/src/reorder/index.ts +100 -27
- package/src/rich-text-editor/index.ts +37 -12
- package/src/rich-text-editor/keymap.ts +1 -1
- package/src/rich-text-editor/keys.ts +135 -26
- package/src/rich-text-editor/markdown.ts +36 -1
- package/src/rich-text-editor/marks.ts +101 -0
- package/src/rich-text-editor/render.ts +49 -12
- package/src/rich-text-editor/replace.ts +85 -0
- package/src/rich-text-editor/toolbar.ts +1 -1
- package/src/rich-text-editor/virtual.ts +25 -0
- package/src/richtext/node.ts +235 -14
- package/src/richtext/runs.ts +23 -12
- package/src/table/index.ts +29 -0
- package/src/table/rows.ts +18 -8
- package/src/terminal/index.ts +4 -0
- package/src/terminal/vt/pty.ts +16 -2
- package/src/terminal-output/index.ts +129 -31
- package/src/terminal-output/runs.ts +16 -2
- package/src/three/canvas.ts +102 -8
- package/src/three/events.ts +49 -9
- package/src/tree/index.ts +19 -0
package/src/html/layout/flex.ts
CHANGED
|
@@ -23,12 +23,34 @@
|
|
|
23
23
|
// the leaf shape costs is stretch — a stretched item's box grows but its
|
|
24
24
|
// contents are not re-laid at the stretched height.
|
|
25
25
|
import { Yoga, layoutLoaded } from 'react-x11/yoga';
|
|
26
|
-
import type { Node as YogaNode } from 'react-x11/yoga';
|
|
26
|
+
import type { Config as YogaConfig, Node as YogaNode } from 'react-x11/yoga';
|
|
27
27
|
|
|
28
|
-
import { AUTO, isPct, resolveOrNull } from '../css/values.js';
|
|
29
|
-
import
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
28
|
+
import { AUTO, gapOf, isPct, resolve, resolveOrNull } from '../css/values.js';
|
|
29
|
+
import { scrolls } from '../css/style.js';
|
|
30
|
+
import type { ComputedStyle, ContentSize } from '../css/style.js';
|
|
31
|
+
import { Box, PAINT_ORDER, isBlank } from './boxes.js';
|
|
32
|
+
import {
|
|
33
|
+
FLEXED_HEIGHT,
|
|
34
|
+
MIN_CONTENT_PROBE,
|
|
35
|
+
clampHeight,
|
|
36
|
+
clampWidth,
|
|
37
|
+
contentSizedWidth,
|
|
38
|
+
exactMinContent,
|
|
39
|
+
intrinsicWidth,
|
|
40
|
+
measureIntrinsicWidth,
|
|
41
|
+
moveTo,
|
|
42
|
+
percentBaseInside,
|
|
43
|
+
percentHeightsIn,
|
|
44
|
+
positionOutOfFlow,
|
|
45
|
+
replacedRatio,
|
|
46
|
+
transferredHeight,
|
|
47
|
+
transferredWidth,
|
|
48
|
+
heightFromWidth,
|
|
49
|
+
widthFromHeight,
|
|
50
|
+
resolveEdges,
|
|
51
|
+
} from './block.js';
|
|
52
|
+
import { layoutGrid } from './css-grid.js';
|
|
53
|
+
import { firstBaselineIn } from './inline.js';
|
|
32
54
|
import type { LayoutContext } from './block.js';
|
|
33
55
|
|
|
34
56
|
// `react-x11/yoga` re-exports yoga's own declarations, so the node shape and
|
|
@@ -37,6 +59,22 @@ import type { LayoutContext } from './block.js';
|
|
|
37
59
|
// `react-x11/ntk` (a deliberately loose record).
|
|
38
60
|
const Y = Yoga;
|
|
39
61
|
|
|
62
|
+
/**
|
|
63
|
+
* The config this engine's flex trees are made in: off the pixel grid, as
|
|
64
|
+
* the rest of its layout is, since its paint snaps each box's edges. On
|
|
65
|
+
* the grid, Yoga rounds a measured item's size up and the next item's
|
|
66
|
+
* start to the nearest, and two items that met at a fraction overlapped
|
|
67
|
+
* by a pixel. Its own, not core's, whose grid its own layout keeps.
|
|
68
|
+
*/
|
|
69
|
+
let config: YogaConfig | null = null;
|
|
70
|
+
function flexConfig(): YogaConfig {
|
|
71
|
+
if (config === null) {
|
|
72
|
+
config = Y.Config.create();
|
|
73
|
+
config.setPointScaleFactor(0);
|
|
74
|
+
}
|
|
75
|
+
return config;
|
|
76
|
+
}
|
|
77
|
+
|
|
40
78
|
/**
|
|
41
79
|
* Lay out a flex container's children. Returns the content height.
|
|
42
80
|
*
|
|
@@ -54,52 +92,395 @@ export function layoutFlex(
|
|
|
54
92
|
ctx: LayoutContext,
|
|
55
93
|
contentWidth: number,
|
|
56
94
|
): number {
|
|
95
|
+
// a grid container is one of these to the box tree, and laid out apart
|
|
96
|
+
if (box.style.grid) return layoutGrid(box, ctx, contentWidth);
|
|
57
97
|
if (!layoutLoaded()) return layoutAsBlockFallback(box, ctx, contentWidth);
|
|
98
|
+
// Each flex box in a flex item runs its Yoga pass inside the measure of
|
|
99
|
+
// the one around it, and Yoga's own stack runs out at about a hundred and
|
|
100
|
+
// fifty of them — a `RuntimeError` out of the layout. Past this many, one
|
|
101
|
+
// is laid out as blocks: the markup of a broken page, not of a design.
|
|
102
|
+
const depth = ctx.flexDepth ?? 0;
|
|
103
|
+
if (depth >= FLEX_DEPTH) return layoutAsBlockFallback(box, ctx, contentWidth);
|
|
58
104
|
|
|
59
|
-
const root = Y.Node.create();
|
|
105
|
+
const root = Y.Node.create(flexConfig());
|
|
60
106
|
applyContainer(root, box.style);
|
|
61
|
-
|
|
62
|
-
|
|
107
|
+
// the gaps, a percentage of the content box's size along them where it
|
|
108
|
+
// has one, and else of nothing (CSS Box Alignment 3, 8.3)
|
|
109
|
+
const rowGap = gapOf(box.style.rowGap, percentBaseInside(box));
|
|
110
|
+
const columnGap = gapOf(box.style.columnGap, contentWidth);
|
|
111
|
+
if (rowGap) root.setGap(Y.GUTTER_ROW, rowGap);
|
|
112
|
+
if (columnGap) root.setGap(Y.GUTTER_COLUMN, columnGap);
|
|
113
|
+
// Laid out at no width limit — a flex item's max-content measured, a
|
|
114
|
+
// table column's — the container is as wide as its content, which Yoga
|
|
115
|
+
// works out from an `auto` width. Handed an infinite one, it took it for
|
|
116
|
+
// a width, grew a `flex: 1` item to fill it, placed its text at 1.7e38,
|
|
117
|
+
// and the measure that asked came back vast: a row beside such an item
|
|
118
|
+
// was squeezed to wrap every word.
|
|
119
|
+
const bounded = Number.isFinite(contentWidth);
|
|
120
|
+
if (bounded) root.setWidth(contentWidth);
|
|
121
|
+
// The content box's height, where it is definite: a length or a
|
|
122
|
+
// percentage that resolves, or what `aspect-ratio` makes of the width —
|
|
123
|
+
// less the padding and borders a `border-box` height holds, which put
|
|
124
|
+
// `h-16 py-2 items-center` eight pixels low. Where it is not, the limits
|
|
125
|
+
// on it, so a column `min-h-screen` gives its `flex-1` the rest.
|
|
126
|
+
const definite = percentBaseInside(box);
|
|
127
|
+
const height = Number.isFinite(definite) ? definite : null;
|
|
63
128
|
if (height !== null) root.setHeight(height);
|
|
64
|
-
else
|
|
129
|
+
else {
|
|
130
|
+
root.setHeightAuto();
|
|
131
|
+
const extra = box.verticalExtra;
|
|
132
|
+
const min = clampHeight(box, extra) - extra;
|
|
133
|
+
if (min > 0) root.setMinHeight(min);
|
|
134
|
+
const max = clampHeight(box, Infinity) - extra;
|
|
135
|
+
if (Number.isFinite(max)) root.setMaxHeight(Math.max(0, max));
|
|
136
|
+
}
|
|
65
137
|
|
|
66
|
-
const
|
|
138
|
+
const flowing: Box[] = [];
|
|
139
|
+
let reordered = false;
|
|
67
140
|
for (const child of box.children) {
|
|
68
|
-
if (child.kind === 'text' &&
|
|
141
|
+
if (child.kind === 'text' && isBlank(child.text)) continue;
|
|
69
142
|
if (child.outOfFlow) {
|
|
70
|
-
|
|
143
|
+
positionOutOfFlow(child, box, ctx, true);
|
|
71
144
|
continue;
|
|
72
145
|
}
|
|
73
|
-
|
|
146
|
+
if (child.style.order !== 0) reordered = true;
|
|
147
|
+
flowing.push(child);
|
|
148
|
+
}
|
|
149
|
+
// in `order`, and where two have the same, in the document's (CSS
|
|
150
|
+
// Flexbox 5.4): Yoga places its children in the order they were given,
|
|
151
|
+
// and paint paints them in it
|
|
152
|
+
if (reordered) {
|
|
153
|
+
flowing.sort((a, b) => a.style.order - b.style.order);
|
|
154
|
+
PAINT_ORDER.set(
|
|
155
|
+
box,
|
|
156
|
+
[...box.children].sort((a, b) => orderOf(a) - orderOf(b)),
|
|
157
|
+
);
|
|
158
|
+
} else PAINT_ORDER.delete(box);
|
|
159
|
+
|
|
160
|
+
const items: { box: Box; node: YogaNode; laid: Laid }[] = [];
|
|
161
|
+
for (const child of flowing) {
|
|
162
|
+
const node = Y.Node.create(flexConfig());
|
|
74
163
|
resolveEdges(child, contentWidth);
|
|
75
|
-
|
|
164
|
+
const laid: Laid = { width: NaN, height: NaN, set: NaN, stretch: NaN };
|
|
165
|
+
applyItem(node, child, ctx, contentWidth, laid, height !== null);
|
|
76
166
|
root.insertChild(node, items.length);
|
|
77
|
-
items.push({ box: child, node });
|
|
167
|
+
items.push({ box: child, node, laid });
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const direction =
|
|
171
|
+
box.style.direction === 'rtl' ? Y.DIRECTION_RTL : Y.DIRECTION_LTR;
|
|
172
|
+
const row = box.style.flexDirection.startsWith('row');
|
|
173
|
+
const calculate = (): void =>
|
|
174
|
+
root.calculateLayout(
|
|
175
|
+
bounded ? contentWidth : Number.NaN,
|
|
176
|
+
height ?? Number.NaN,
|
|
177
|
+
direction,
|
|
178
|
+
);
|
|
179
|
+
ctx.flexDepth = depth + 1;
|
|
180
|
+
try {
|
|
181
|
+
calculate();
|
|
182
|
+
// an item Yoga shrank under what its content comes to is kept to it,
|
|
183
|
+
// and the row is laid out again (`autoMinimums`) — which may shrink
|
|
184
|
+
// another under its own, a few times over at most
|
|
185
|
+
for (
|
|
186
|
+
let pass = 0;
|
|
187
|
+
pass < 4 && autoMinimums(items, row, ctx, contentWidth);
|
|
188
|
+
pass += 1
|
|
189
|
+
) {
|
|
190
|
+
calculate();
|
|
191
|
+
}
|
|
192
|
+
} finally {
|
|
193
|
+
ctx.flexDepth = depth;
|
|
78
194
|
}
|
|
79
195
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
box.style.
|
|
196
|
+
// Yoga aligns the lines of a box that wraps, or aligns by baselines, in
|
|
197
|
+
// one pass of its own, which drops a margin (`lineMarginFix`)
|
|
198
|
+
const baselines =
|
|
199
|
+
box.style.alignItems === 'baseline' ||
|
|
200
|
+
items.some(({ box: child }) => child.style.alignSelf === 'baseline');
|
|
201
|
+
let bottom = placeItems(
|
|
202
|
+
box,
|
|
203
|
+
ctx,
|
|
204
|
+
items,
|
|
205
|
+
row,
|
|
206
|
+
height,
|
|
207
|
+
box.style.flexWrap === 'wrap' || baselines,
|
|
84
208
|
);
|
|
209
|
+
// Items aligned by their baselines, which Yoga cannot see, are aligned
|
|
210
|
+
// with their baselines known (`baselineLines`)
|
|
211
|
+
// by the flex layout again, set at their lines' starts with the margins
|
|
212
|
+
// that put their baselines together, which makes each line as tall as
|
|
213
|
+
// that does
|
|
214
|
+
const lines = row && baselines ? baselineLines(box.style, items) : null;
|
|
215
|
+
if (lines) {
|
|
216
|
+
// every one of them, and the box's own `baseline` too, which is what
|
|
217
|
+
// takes Yoga down that pass
|
|
218
|
+
const started = new Set<Box>();
|
|
219
|
+
for (const line of lines) {
|
|
220
|
+
line.forEach(({ box: child, node }, i) => {
|
|
221
|
+
node.setAlignSelf(Y.ALIGN_FLEX_START);
|
|
222
|
+
node.setMargin(Y.EDGE_TOP, line.margins[i]);
|
|
223
|
+
started.add(child);
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
if (box.style.alignItems === 'baseline') {
|
|
227
|
+
root.setAlignItems(Y.ALIGN_FLEX_START);
|
|
228
|
+
}
|
|
229
|
+
ctx.flexDepth = depth + 1;
|
|
230
|
+
try {
|
|
231
|
+
calculate();
|
|
232
|
+
} finally {
|
|
233
|
+
ctx.flexDepth = depth;
|
|
234
|
+
}
|
|
235
|
+
bottom = placeItems(
|
|
236
|
+
box,
|
|
237
|
+
ctx,
|
|
238
|
+
items,
|
|
239
|
+
row,
|
|
240
|
+
height,
|
|
241
|
+
box.style.flexWrap === 'wrap',
|
|
242
|
+
started,
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// A replaced item with a ratio that is stretched across a line of a
|
|
247
|
+
// definite size takes its flex base size from the stretched one through
|
|
248
|
+
// the ratio (CSS Flexbox 9.2 and 9.8), where Yoga took its natural size —
|
|
249
|
+
// which Yoga's own `aspectRatio` would do for its border box, where a
|
|
250
|
+
// replaced element's ratio is its content box's. Laid out again with it.
|
|
251
|
+
// where the line's cross size is definite: one line, in a box of that
|
|
252
|
+
// size of its own (9.8)
|
|
253
|
+
const definiteCross =
|
|
254
|
+
box.style.flexWrap === 'nowrap' && (row ? height !== null : bounded);
|
|
255
|
+
if (definiteCross && keepRatios(box, items, row)) {
|
|
256
|
+
ctx.flexDepth = depth + 1;
|
|
257
|
+
try {
|
|
258
|
+
calculate();
|
|
259
|
+
} finally {
|
|
260
|
+
ctx.flexDepth = depth;
|
|
261
|
+
}
|
|
262
|
+
bottom = placeItems(
|
|
263
|
+
box,
|
|
264
|
+
ctx,
|
|
265
|
+
items,
|
|
266
|
+
row,
|
|
267
|
+
height,
|
|
268
|
+
box.style.flexWrap === 'wrap' || baselines,
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const contentHeight = root.getComputedHeight();
|
|
273
|
+
root.freeRecursive();
|
|
274
|
+
return Math.max(contentHeight, bottom - box.contentY);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/** Give each replaced item with a ratio that its line stretched the flex
|
|
278
|
+
* base size the ratio makes of the stretched size; whether any changed. */
|
|
279
|
+
function keepRatios(
|
|
280
|
+
container: Box,
|
|
281
|
+
items: readonly { box: Box; node: YogaNode }[],
|
|
282
|
+
row: boolean,
|
|
283
|
+
): boolean {
|
|
284
|
+
let changed = false;
|
|
285
|
+
for (const { box, node } of items) {
|
|
286
|
+
if (box.kind !== 'replaced' || !stretches(box, container.style, row)) {
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
const style = box.style;
|
|
290
|
+
if ((row ? style.width : style.height) !== AUTO) continue;
|
|
291
|
+
const ratio = replacedRatio(box);
|
|
292
|
+
if (!(ratio > 0)) continue;
|
|
293
|
+
const basis = row
|
|
294
|
+
? Math.max(0, node.getComputedHeight() - box.verticalExtra) * ratio +
|
|
295
|
+
box.horizontalExtra
|
|
296
|
+
: Math.max(0, node.getComputedWidth() - box.horizontalExtra) / ratio +
|
|
297
|
+
box.verticalExtra;
|
|
298
|
+
const main = row ? node.getComputedWidth() : node.getComputedHeight();
|
|
299
|
+
if (Math.abs(basis - main) < 0.5) continue;
|
|
300
|
+
node.setFlexBasis(basis);
|
|
301
|
+
changed = true;
|
|
302
|
+
}
|
|
303
|
+
return changed;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* A replaced row item's automatic least width, its border box (CSS
|
|
308
|
+
* Flexbox 4.5): its natural width, or through its ratio what a height of
|
|
309
|
+
* its own makes of it, and no more than a width of its own, within its
|
|
310
|
+
* `max-width`. Null where it has neither a natural width nor a ratio to
|
|
311
|
+
* take one through.
|
|
312
|
+
*/
|
|
313
|
+
function replacedMinimum(box: Box, containingWidth: number): number | null {
|
|
314
|
+
const style = box.style;
|
|
315
|
+
const own = box.intrinsic;
|
|
316
|
+
const ratio = replacedRatio(box);
|
|
317
|
+
const hx = style.boxSizing === 'border-box' ? box.horizontalExtra : 0;
|
|
318
|
+
const vx = style.boxSizing === 'border-box' ? box.verticalExtra : 0;
|
|
319
|
+
const base = box.percentHeightBase;
|
|
320
|
+
const height = resolveOrNull(style.height, base);
|
|
321
|
+
let content: number | null =
|
|
322
|
+
height !== null && ratio > 0
|
|
323
|
+
? Math.max(0, height - vx) * ratio
|
|
324
|
+
: own && !(own.missing & 1)
|
|
325
|
+
? own.width
|
|
326
|
+
: null;
|
|
327
|
+
if (content === null) return null;
|
|
328
|
+
// and through its ratio, within its least and greatest heights
|
|
329
|
+
if (ratio > 0) {
|
|
330
|
+
const least =
|
|
331
|
+
style.minHeight === AUTO ? null : resolveOrNull(style.minHeight, base);
|
|
332
|
+
if (least !== null)
|
|
333
|
+
content = Math.max(content, Math.max(0, least - vx) * ratio);
|
|
334
|
+
const most =
|
|
335
|
+
style.maxHeight === 'none' ? null : resolveOrNull(style.maxHeight, base);
|
|
336
|
+
if (most !== null)
|
|
337
|
+
content = Math.min(content, Math.max(0, most - vx) * ratio);
|
|
338
|
+
}
|
|
339
|
+
const width = resolveOrNull(style.width, containingWidth);
|
|
340
|
+
if (width !== null) content = Math.min(content, Math.max(0, width - hx));
|
|
341
|
+
if (style.maxWidth !== 'none') {
|
|
342
|
+
const most = resolveOrNull(style.maxWidth, containingWidth);
|
|
343
|
+
if (most !== null) content = Math.min(content, Math.max(0, most - hx));
|
|
344
|
+
}
|
|
345
|
+
return content + box.horizontalExtra;
|
|
346
|
+
}
|
|
85
347
|
|
|
348
|
+
/** A row item's `flex-basis: content`, its border box: its max-content
|
|
349
|
+
* width, or a replaced element's natural one. */
|
|
350
|
+
function contentBasis(
|
|
351
|
+
box: Box,
|
|
352
|
+
ctx: LayoutContext,
|
|
353
|
+
containingWidth: number,
|
|
354
|
+
): number {
|
|
355
|
+
if (box.kind === 'replaced') {
|
|
356
|
+
const own = box.intrinsic;
|
|
357
|
+
if (own && !(own.missing & 1)) return own.width + box.horizontalExtra;
|
|
358
|
+
}
|
|
359
|
+
// a ratio's is a definite height through it, whatever the width says
|
|
360
|
+
const fromRatio = ratioBasis(box);
|
|
361
|
+
if (fromRatio !== null) return fromRatio;
|
|
362
|
+
const room = Math.max(0, containingWidth - box.marginLeft - box.marginRight);
|
|
363
|
+
return contentSizedWidth(box, ctx, 'max-content', room, containingWidth);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* The border-box width a row item's ratio makes of a definite height: its
|
|
368
|
+
* own, a length or a percentage of a flex box of a definite height, or the
|
|
369
|
+
* one line of such a flex box that stretches it across (CSS Flexbox 9.2,
|
|
370
|
+
* 9.4). Null where it has no ratio or no such height.
|
|
371
|
+
*/
|
|
372
|
+
function ratioBasis(box: Box): number | null {
|
|
373
|
+
const style = box.style;
|
|
374
|
+
const aspect = style.aspectRatio;
|
|
375
|
+
const flex = box.parent;
|
|
376
|
+
if (!aspect || box.kind === 'replaced' || !flex) return null;
|
|
377
|
+
const room = percentBaseInside(flex);
|
|
378
|
+
let height = resolveOrNull(style.height, room);
|
|
379
|
+
let outer: number;
|
|
380
|
+
if (height !== null) {
|
|
381
|
+
outer =
|
|
382
|
+
style.boxSizing === 'border-box'
|
|
383
|
+
? Math.max(height, box.verticalExtra)
|
|
384
|
+
: height + box.verticalExtra;
|
|
385
|
+
} else {
|
|
386
|
+
const align =
|
|
387
|
+
style.alignSelf === AUTO ? flex.style.alignItems : style.alignSelf;
|
|
388
|
+
if (
|
|
389
|
+
align !== 'stretch' ||
|
|
390
|
+
flex.style.flexWrap !== 'nowrap' ||
|
|
391
|
+
!Number.isFinite(room) ||
|
|
392
|
+
style.marginTop === AUTO ||
|
|
393
|
+
style.marginBottom === AUTO
|
|
394
|
+
) {
|
|
395
|
+
return null;
|
|
396
|
+
}
|
|
397
|
+
height = room - box.marginTop - box.marginBottom;
|
|
398
|
+
outer = Math.max(height, box.verticalExtra);
|
|
399
|
+
}
|
|
400
|
+
return widthFromHeight(box, clampHeight(box, outer));
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/** A column item's flex base size where it has a ratio and a width of
|
|
404
|
+
* its own, its border box: the width, within its limits, through the
|
|
405
|
+
* ratio. */
|
|
406
|
+
function ratioHeightBasis(box: Box, containingWidth: number): number | null {
|
|
407
|
+
const style = box.style;
|
|
408
|
+
if (style.width === AUTO || style.widthKeyword || box.kind === 'replaced') {
|
|
409
|
+
return null;
|
|
410
|
+
}
|
|
411
|
+
const set = resolveOrNull(style.width, containingWidth);
|
|
412
|
+
if (set === null) return null;
|
|
413
|
+
const outer =
|
|
414
|
+
style.boxSizing === 'border-box'
|
|
415
|
+
? Math.max(set, box.horizontalExtra)
|
|
416
|
+
: set + box.horizontalExtra;
|
|
417
|
+
return heightFromWidth(box, clampWidth(box, outer, containingWidth));
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/** A child's `order`, which an absolutely positioned one takes as 0 when
|
|
421
|
+
* it is painted among the items. */
|
|
422
|
+
function orderOf(box: Box): number {
|
|
423
|
+
return box.outOfFlow || box.kind === 'text' ? 0 : box.style.order;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/** Lay each item out where the flex layout put it, at the size it gave it,
|
|
427
|
+
* and answer where the lowest ends. `started` are items set at their
|
|
428
|
+
* lines' starts whatever their own alignment says (`baselineLines`). */
|
|
429
|
+
function placeItems(
|
|
430
|
+
box: Box,
|
|
431
|
+
ctx: LayoutContext,
|
|
432
|
+
items: readonly { box: Box; node: YogaNode; laid: Laid }[],
|
|
433
|
+
row: boolean,
|
|
434
|
+
height: number | null,
|
|
435
|
+
/** Whether Yoga aligned the lines in its pass that drops a margin. */
|
|
436
|
+
lined: boolean,
|
|
437
|
+
started?: ReadonlySet<Box>,
|
|
438
|
+
): number {
|
|
86
439
|
let bottom = 0;
|
|
87
|
-
for (const { box: child, node } of items) {
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
440
|
+
for (const { box: child, node, laid } of items) {
|
|
441
|
+
const across = lined
|
|
442
|
+
? lineMarginFix(box.style, child, node, row, started?.has(child))
|
|
443
|
+
: 0;
|
|
444
|
+
const left = box.contentX + node.getComputedLeft() + (row ? 0 : across);
|
|
445
|
+
const top = box.contentY + node.getComputedTop() + (row ? across : 0);
|
|
446
|
+
const width = meant(
|
|
447
|
+
node.getComputedWidth(),
|
|
448
|
+
laid.set,
|
|
449
|
+
laid.stretch,
|
|
450
|
+
laid.width,
|
|
451
|
+
);
|
|
91
452
|
const itemHeight = node.getComputedHeight();
|
|
92
453
|
// The item is laid out again at the width the flex pass settled on: the
|
|
93
454
|
// measure function answered a question, and the answer is not a layout —
|
|
94
455
|
// its line breaks were computed against a width that may have changed
|
|
95
|
-
// when a sibling grew.
|
|
96
|
-
|
|
456
|
+
// when a sibling grew. Unless the last answer was at that width, which
|
|
457
|
+
// is a layout the item still has (Yoga's widths are float32s).
|
|
458
|
+
// Its height is definite where the flex layout made it so (CSS Flexbox
|
|
459
|
+
// 9.8): stretched across a row's line, or flexed in a column of a
|
|
460
|
+
// height of its own. What is in it takes its percentages of that —
|
|
461
|
+
// the `h-full` in a stretched sidebar — where they had nothing to be
|
|
462
|
+
// of, and the item is laid out again for them.
|
|
463
|
+
const definite = row
|
|
464
|
+
? stretches(child, box.style)
|
|
465
|
+
? itemHeight
|
|
466
|
+
: null
|
|
467
|
+
: height !== null
|
|
468
|
+
? itemHeight
|
|
469
|
+
: null;
|
|
470
|
+
layoutItemAt(
|
|
471
|
+
child,
|
|
472
|
+
ctx,
|
|
473
|
+
left,
|
|
474
|
+
top,
|
|
475
|
+
width,
|
|
476
|
+
itemHeight,
|
|
477
|
+
laid,
|
|
478
|
+
definite,
|
|
479
|
+
!row,
|
|
480
|
+
);
|
|
97
481
|
bottom = Math.max(bottom, top + child.height);
|
|
98
482
|
}
|
|
99
|
-
|
|
100
|
-
const contentHeight = root.getComputedHeight();
|
|
101
|
-
root.freeRecursive();
|
|
102
|
-
return Math.max(contentHeight, bottom - box.contentY);
|
|
483
|
+
return bottom;
|
|
103
484
|
}
|
|
104
485
|
|
|
105
486
|
function layoutItemAt(
|
|
@@ -109,34 +490,66 @@ function layoutItemAt(
|
|
|
109
490
|
y: number,
|
|
110
491
|
width: number,
|
|
111
492
|
height: number,
|
|
493
|
+
laid: Laid,
|
|
494
|
+
/** Its border box's height where the flex layout made it definite. */
|
|
495
|
+
definite: number | null,
|
|
496
|
+
/** Whether its height is the one the flex layout gave it, in a column,
|
|
497
|
+
* whatever its own says: flexed, it is shrunk as well as grown. */
|
|
498
|
+
column = false,
|
|
112
499
|
): void {
|
|
113
|
-
|
|
500
|
+
// a replaced item is the size the flex layout made it — flexed,
|
|
501
|
+
// stretched — which its natural size was only the start of
|
|
502
|
+
if (box.kind === 'text' || box.kind === 'break' || box.kind === 'replaced') {
|
|
114
503
|
box.x = x;
|
|
115
504
|
box.y = y;
|
|
116
505
|
box.width = width;
|
|
117
506
|
box.height = height;
|
|
118
507
|
return;
|
|
119
508
|
}
|
|
509
|
+
const inner =
|
|
510
|
+
definite === null || !percentHeightsIn(box)
|
|
511
|
+
? null
|
|
512
|
+
: Math.max(0, definite - box.verticalExtra);
|
|
513
|
+
if (inner !== null && !Object.is(inner, percentBaseInside(box))) {
|
|
514
|
+
FLEXED_HEIGHT.set(box, inner);
|
|
515
|
+
try {
|
|
516
|
+
ctx.layoutSubtree(box, width);
|
|
517
|
+
} finally {
|
|
518
|
+
FLEXED_HEIGHT.delete(box);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
120
521
|
// `measureBox` lays the box out at (0, 0); re-running it at the final width
|
|
121
522
|
// and then moving it is one pass, not two, because the second call is the
|
|
122
|
-
// one whose result is kept
|
|
123
|
-
|
|
523
|
+
// one whose result is kept — or no pass, where the last measure was at
|
|
524
|
+
// this width. An item Yoga never measured has none, NaN, and is laid out.
|
|
525
|
+
else if (Math.abs(laid.width - width) <= 0.01) box.height = laid.height;
|
|
526
|
+
else ctx.layoutSubtree(box, width);
|
|
124
527
|
// A stretched item is taller than its content, and the box has to say so
|
|
125
|
-
// or its background stops short of the row
|
|
126
|
-
|
|
528
|
+
// or its background stops short of the row — and it is no taller than its
|
|
529
|
+
// line where its content is, or than what its ratio makes of its width:
|
|
530
|
+
// its height is the line's (CSS Flexbox 9.4, step 11).
|
|
531
|
+
if (height > box.height || column || definite !== null) box.height = height;
|
|
127
532
|
moveTo(box, x, y);
|
|
128
533
|
}
|
|
129
534
|
|
|
535
|
+
// What a new Yoga node already is is not said again. A call into the
|
|
536
|
+
// engine costs more than the arithmetic it asks for, and a Tailwind page is
|
|
537
|
+
// a flex box in every list item: saying every default made the calls into
|
|
538
|
+
// Yoga two fifths of laying one out. A node's defaults are column, no wrap,
|
|
539
|
+
// start, stretch, start (for its lines), no growing, no shrinking, `auto`
|
|
540
|
+
// basis and size, and nothing on any edge.
|
|
541
|
+
|
|
130
542
|
function applyContainer(node: YogaNode, style: ComputedStyle): void {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
if (
|
|
139
|
-
|
|
543
|
+
const direction = FLEX_DIRECTION[style.flexDirection] ?? Y.FLEX_DIRECTION_ROW;
|
|
544
|
+
if (direction !== Y.FLEX_DIRECTION_COLUMN) node.setFlexDirection(direction);
|
|
545
|
+
const wrap = WRAP[style.flexWrap] ?? Y.WRAP_NO_WRAP;
|
|
546
|
+
if (wrap !== Y.WRAP_NO_WRAP) node.setFlexWrap(wrap);
|
|
547
|
+
const justify = JUSTIFY[mainJustify(style)] ?? Y.JUSTIFY_FLEX_START;
|
|
548
|
+
if (justify !== Y.JUSTIFY_FLEX_START) node.setJustifyContent(justify);
|
|
549
|
+
const items = ALIGN[style.alignItems] ?? Y.ALIGN_STRETCH;
|
|
550
|
+
if (items !== Y.ALIGN_STRETCH) node.setAlignItems(items);
|
|
551
|
+
const lines = ALIGN[style.alignContent] ?? Y.ALIGN_STRETCH;
|
|
552
|
+
if (lines !== Y.ALIGN_FLEX_START) node.setAlignContent(lines);
|
|
140
553
|
}
|
|
141
554
|
|
|
142
555
|
function applyItem(
|
|
@@ -144,107 +557,677 @@ function applyItem(
|
|
|
144
557
|
box: Box,
|
|
145
558
|
ctx: LayoutContext,
|
|
146
559
|
containingWidth: number,
|
|
560
|
+
laid: Laid,
|
|
561
|
+
/** Whether the flex box has a height of its own. */
|
|
562
|
+
tall: boolean,
|
|
147
563
|
): void {
|
|
148
564
|
const style = box.style;
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
565
|
+
laid.stretch = containingWidth - box.marginLeft - box.marginRight;
|
|
566
|
+
// an `auto` margin takes the free space on its side, which is how
|
|
567
|
+
// `margin-left: auto` puts an item at the end of its row (CSS Flexbox
|
|
568
|
+
// 8.1); Yoga does that itself
|
|
569
|
+
const margin = (edge: number, len: unknown, px: number) => {
|
|
570
|
+
if (len === AUTO) node.setMarginAuto(edge);
|
|
571
|
+
else if (px) node.setMargin(edge, px);
|
|
572
|
+
};
|
|
573
|
+
margin(Y.EDGE_TOP, style.marginTop, box.marginTop);
|
|
574
|
+
margin(Y.EDGE_RIGHT, style.marginRight, box.marginRight);
|
|
575
|
+
margin(Y.EDGE_BOTTOM, style.marginBottom, box.marginBottom);
|
|
576
|
+
margin(Y.EDGE_LEFT, style.marginLeft, box.marginLeft);
|
|
577
|
+
if (style.flexGrow) node.setFlexGrow(style.flexGrow);
|
|
578
|
+
if (style.flexShrink) node.setFlexShrink(style.flexShrink);
|
|
155
579
|
if (style.alignSelf !== AUTO)
|
|
156
580
|
node.setAlignSelf(ALIGN[style.alignSelf] ?? Y.ALIGN_AUTO);
|
|
157
581
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
NaN,
|
|
168
|
-
node.setHeight.bind(node),
|
|
169
|
-
node.setHeightPercent.bind(node),
|
|
170
|
-
node.setHeightAuto.bind(node),
|
|
171
|
-
);
|
|
582
|
+
// Yoga's sizes are border boxes, as `box-sizing: border-box` has them;
|
|
583
|
+
// a `content-box` length is the content's, and the item's padding and
|
|
584
|
+
// border go on top of it
|
|
585
|
+
const across = style.boxSizing === 'border-box' ? 0 : box.horizontalExtra;
|
|
586
|
+
const down = style.boxSizing === 'border-box' ? 0 : box.verticalExtra;
|
|
587
|
+
if (style.width !== AUTO) {
|
|
588
|
+
laid.set = setLength(node, true, style.width, containingWidth, across);
|
|
589
|
+
}
|
|
590
|
+
if (style.height !== AUTO) setLength(node, false, style.height, NaN, down);
|
|
172
591
|
const minWidth = resolveOrNull(style.minWidth, containingWidth);
|
|
173
|
-
if (minWidth !== null) node.setMinWidth(minWidth);
|
|
592
|
+
if (minWidth !== null) node.setMinWidth(minWidth + across);
|
|
174
593
|
if (style.maxWidth !== 'none') {
|
|
175
594
|
const maxWidth = resolveOrNull(style.maxWidth, containingWidth);
|
|
176
|
-
if (maxWidth !== null) node.setMaxWidth(maxWidth);
|
|
595
|
+
if (maxWidth !== null) node.setMaxWidth(maxWidth + across);
|
|
596
|
+
}
|
|
597
|
+
if (style.widthKeyword || style.minWidthKeyword || style.maxWidthKeyword) {
|
|
598
|
+
// an intrinsic size is the item's content's, measured here and handed
|
|
599
|
+
// over as a length: `w-fit` in a column is not stretched across it,
|
|
600
|
+
// and `min-w-max` in a row does not shrink below its content
|
|
601
|
+
const room = Math.max(
|
|
602
|
+
0,
|
|
603
|
+
containingWidth - box.marginLeft - box.marginRight,
|
|
604
|
+
);
|
|
605
|
+
const size = (keyword: ContentSize): number =>
|
|
606
|
+
contentSizedWidth(box, ctx, keyword, room, containingWidth);
|
|
607
|
+
if (style.widthKeyword) {
|
|
608
|
+
laid.set = size(style.widthKeyword);
|
|
609
|
+
node.setWidth(laid.set);
|
|
610
|
+
}
|
|
611
|
+
if (style.minWidthKeyword) node.setMinWidth(size(style.minWidthKeyword));
|
|
612
|
+
if (style.maxWidthKeyword) node.setMaxWidth(size(style.maxWidthKeyword));
|
|
177
613
|
}
|
|
178
614
|
const minHeight = resolveOrNull(style.minHeight, NaN);
|
|
179
|
-
if (minHeight !== null) node.setMinHeight(minHeight);
|
|
615
|
+
if (minHeight !== null) node.setMinHeight(minHeight + down);
|
|
180
616
|
if (style.maxHeight !== 'none') {
|
|
181
617
|
const maxHeight = resolveOrNull(style.maxHeight, NaN);
|
|
182
|
-
if (maxHeight !== null) node.setMaxHeight(maxHeight);
|
|
618
|
+
if (maxHeight !== null) node.setMaxHeight(maxHeight + down);
|
|
183
619
|
}
|
|
184
620
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
else
|
|
188
|
-
|
|
189
|
-
|
|
621
|
+
const row = box.parent?.style.flexDirection.startsWith('row') ?? true;
|
|
622
|
+
// Yoga takes a length for a basis only where the flex box's main size is
|
|
623
|
+
// definite, and else the item's own size along it: down a column of no
|
|
624
|
+
// height of its own it read `flex: 0 0 3rem` as the item's height, or
|
|
625
|
+
// its content's. There the basis is handed over as that height, which is
|
|
626
|
+
// what the item's own is to a basis anyway — no more than its start
|
|
627
|
+
const setBasis = (px: number): void => {
|
|
628
|
+
if (row || tall) node.setFlexBasis(px);
|
|
629
|
+
else node.setHeight(px);
|
|
630
|
+
};
|
|
631
|
+
// down a column, an item with a ratio and a width is as tall as that
|
|
632
|
+
// makes it, for a basis of its content or of its own `auto` height (CSS
|
|
633
|
+
// Flexbox 9.2.3, B) — where Yoga measured it, and its block layout held
|
|
634
|
+
// it to its content (CSS Sizing 4, 5.2), which only its automatic
|
|
635
|
+
// minimum does here (`autoMinimums`)
|
|
636
|
+
const columnBasis =
|
|
637
|
+
!row &&
|
|
638
|
+
(style.flexBasis === 'content' ||
|
|
639
|
+
(style.flexBasis === AUTO && style.height === AUTO))
|
|
640
|
+
? ratioHeightBasis(box, containingWidth)
|
|
641
|
+
: null;
|
|
642
|
+
if (style.flexBasis === 'content' && row) {
|
|
643
|
+
// the content's size along a row, whatever the item's own width says
|
|
644
|
+
// (CSS Flexbox 7.2.3), which Yoga reads as `auto` and takes the width
|
|
645
|
+
// for; along a column, Yoga's measure is the content's
|
|
646
|
+
node.setFlexBasis(contentBasis(box, ctx, containingWidth));
|
|
647
|
+
} else if (columnBasis !== null) {
|
|
648
|
+
// but a height of its own hides it from Yoga, and an item with a ratio
|
|
649
|
+
// and a width is as tall as that makes it
|
|
650
|
+
setBasis(columnBasis);
|
|
651
|
+
} else if (style.flexBasis === 'content' || style.flexBasis === AUTO) {
|
|
652
|
+
// Yoga's own
|
|
653
|
+
} else if (isPct(style.flexBasis)) {
|
|
654
|
+
// a percentage of the main size, which is known across a row
|
|
655
|
+
const basis = style.flexBasis;
|
|
656
|
+
if (!basis.px && !basis.of) node.setFlexBasisPercent(basis.pct);
|
|
657
|
+
else if (row && Number.isFinite(containingWidth)) {
|
|
658
|
+
node.setFlexBasis(resolve(basis, containingWidth));
|
|
659
|
+
} else if (basis.of) node.setFlexBasisAuto();
|
|
660
|
+
else node.setFlexBasisPercent(basis.pct);
|
|
661
|
+
} else setBasis(style.flexBasis + (row ? across : down));
|
|
190
662
|
|
|
191
663
|
// The item's padding and border belong to Yoga so it can size the item,
|
|
192
664
|
// and to this engine so it can paint it. Both read the same numbers.
|
|
193
|
-
node.setPadding(Y.EDGE_TOP, box.padTop);
|
|
194
|
-
node.setPadding(Y.EDGE_RIGHT, box.padRight);
|
|
195
|
-
node.setPadding(Y.EDGE_BOTTOM, box.padBottom);
|
|
196
|
-
node.setPadding(Y.EDGE_LEFT, box.padLeft);
|
|
197
|
-
node.setBorder(Y.EDGE_TOP, box.borderTop);
|
|
198
|
-
node.setBorder(Y.EDGE_RIGHT, box.borderRight);
|
|
199
|
-
node.setBorder(Y.EDGE_BOTTOM, box.borderBottom);
|
|
200
|
-
node.setBorder(Y.EDGE_LEFT, box.borderLeft);
|
|
665
|
+
if (box.padTop) node.setPadding(Y.EDGE_TOP, box.padTop);
|
|
666
|
+
if (box.padRight) node.setPadding(Y.EDGE_RIGHT, box.padRight);
|
|
667
|
+
if (box.padBottom) node.setPadding(Y.EDGE_BOTTOM, box.padBottom);
|
|
668
|
+
if (box.padLeft) node.setPadding(Y.EDGE_LEFT, box.padLeft);
|
|
669
|
+
if (box.borderTop) node.setBorder(Y.EDGE_TOP, box.borderTop);
|
|
670
|
+
if (box.borderRight) node.setBorder(Y.EDGE_RIGHT, box.borderRight);
|
|
671
|
+
if (box.borderBottom) node.setBorder(Y.EDGE_BOTTOM, box.borderBottom);
|
|
672
|
+
if (box.borderLeft) node.setBorder(Y.EDGE_LEFT, box.borderLeft);
|
|
201
673
|
|
|
202
674
|
// Yoga asks; this engine answers. That is the whole of the bridge, and it
|
|
203
675
|
// is what lets a paragraph be a flex item without flex knowing what a
|
|
204
676
|
// paragraph is.
|
|
677
|
+
// Its max-content width is the same at every width Yoga asks at, and at
|
|
678
|
+
// every layout the box has, so it is taken once in the box's life, as a
|
|
679
|
+
// table cell's is: taken per layout of the container, a flex box in a
|
|
680
|
+
// flex box in a flex box laid its innermost out three times a level,
|
|
681
|
+
// and twelve levels took two seconds.
|
|
682
|
+
const alongRow = box.parent?.style.flexDirection.startsWith('row') ?? true;
|
|
683
|
+
const content = (): number => {
|
|
684
|
+
// a replaced element's is the width it has with no limit — its
|
|
685
|
+
// natural one, or what its ratio makes of a height of its own — which
|
|
686
|
+
// its image, loading, may change, so it is not kept; taken as its
|
|
687
|
+
// content's, it was none, and Yoga measured an image as nothing wide
|
|
688
|
+
if (box.kind === 'replaced') {
|
|
689
|
+
ctx.layoutSubtree(box, Infinity);
|
|
690
|
+
return Math.max(0, box.width - box.horizontalExtra);
|
|
691
|
+
}
|
|
692
|
+
// an item with a ratio and a definite height is that height through
|
|
693
|
+
// its ratio wide: its flex base size along a row (CSS Flexbox 9.2.3)
|
|
694
|
+
const fromRatio =
|
|
695
|
+
alongRow && style.width === AUTO && !style.widthKeyword
|
|
696
|
+
? ratioBasis(box)
|
|
697
|
+
: null;
|
|
698
|
+
if (fromRatio !== null) return Math.max(0, fromRatio - box.horizontalExtra);
|
|
699
|
+
let width = MAX_CONTENT.get(box);
|
|
700
|
+
if (width === undefined) {
|
|
701
|
+
width = measureIntrinsicWidth(box, ctx, Infinity) - box.horizontalExtra;
|
|
702
|
+
MAX_CONTENT.set(box, width);
|
|
703
|
+
}
|
|
704
|
+
// within what its least and greatest heights make of widths through
|
|
705
|
+
// its ratio: its size before it is flexed, and not after
|
|
706
|
+
const extra = box.horizontalExtra;
|
|
707
|
+
return Math.max(0, transferredWidth(box, width + extra) - extra);
|
|
708
|
+
};
|
|
709
|
+
// An item with a ratio is as wide, across a column, as the height it
|
|
710
|
+
// was given makes it through the ratio, where its width is its own to
|
|
711
|
+
// find (CSS Flexbox 9.4, its hypothetical cross size from its used main
|
|
712
|
+
// size); and a replaced one is as tall, along a row, as the width it was
|
|
713
|
+
// given makes it, where its height is — which a replaced element's
|
|
714
|
+
// layout, sized by its own style, does not know.
|
|
715
|
+
const ratio = box.kind === 'replaced' ? replacedRatio(box) : 0;
|
|
716
|
+
const widthThrough =
|
|
717
|
+
!alongRow && style.width === AUTO && !style.widthKeyword
|
|
718
|
+
? (height: number): number | null =>
|
|
719
|
+
box.kind === 'replaced'
|
|
720
|
+
? ratio > 0
|
|
721
|
+
? height * ratio
|
|
722
|
+
: null
|
|
723
|
+
: (() => {
|
|
724
|
+
const width = widthFromHeight(box, height + box.verticalExtra);
|
|
725
|
+
return width === null
|
|
726
|
+
? null
|
|
727
|
+
: Math.max(0, width - box.horizontalExtra);
|
|
728
|
+
})()
|
|
729
|
+
: null;
|
|
730
|
+
// and an answer Yoga asks for twice is the layout the item already has
|
|
731
|
+
const answers = new Map<number, { width: number; height: number }>();
|
|
205
732
|
node.setMeasureFunc((w, wm, h, hm) => {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
733
|
+
// the width Yoga gave, as this engine meant it (`meant`)
|
|
734
|
+
const extra = box.horizontalExtra;
|
|
735
|
+
const width = meant(w, laid.set - extra, laid.stretch - extra);
|
|
736
|
+
const given = hm === Y.MEASURE_MODE_EXACTLY && Number.isFinite(h);
|
|
737
|
+
const exact = wm === Y.MEASURE_MODE_EXACTLY && Number.isFinite(width);
|
|
738
|
+
const through = widthThrough && given && !exact ? widthThrough(h) : null;
|
|
739
|
+
// along a row, a replaced element is its own width wherever there is
|
|
740
|
+
// room for less — its flex base size is not fitted to the room (9.2)
|
|
741
|
+
// — and across a column it is fitted, as any item is
|
|
742
|
+
const inner =
|
|
743
|
+
through !== null
|
|
744
|
+
? through
|
|
745
|
+
: box.kind === 'replaced' && alongRow && !exact
|
|
746
|
+
? content()
|
|
747
|
+
: innerWidth(width, wm, content);
|
|
748
|
+
if (
|
|
749
|
+
box.kind === 'replaced' &&
|
|
750
|
+
exact &&
|
|
751
|
+
ratio > 0 &&
|
|
752
|
+
style.height === AUTO
|
|
753
|
+
) {
|
|
754
|
+
return { width: inner, height: inner / ratio };
|
|
755
|
+
}
|
|
756
|
+
let answer = answers.get(inner);
|
|
757
|
+
if (answer === undefined) {
|
|
758
|
+
answer = measureBox(box, ctx, inner);
|
|
759
|
+
answers.set(inner, answer);
|
|
760
|
+
laid.width = box.width;
|
|
761
|
+
laid.height = box.height;
|
|
762
|
+
}
|
|
763
|
+
return answer;
|
|
211
764
|
});
|
|
212
765
|
}
|
|
213
766
|
|
|
767
|
+
/** How wide an item's content is as the box is laid out: its max-content
|
|
768
|
+
* width, measured the once (`applyItem`). Keyed by the box, whose lifetime
|
|
769
|
+
* is the cache's: any change to what is in it rebuilds it. */
|
|
770
|
+
const MAX_CONTENT = new WeakMap<Box, number>();
|
|
771
|
+
|
|
772
|
+
/** The width and height of the layout an item was last given, its border
|
|
773
|
+
* box's: what the final pass keeps where the width is the same. */
|
|
774
|
+
interface Laid {
|
|
775
|
+
width: number;
|
|
776
|
+
height: number;
|
|
777
|
+
/** The border-box width this engine set on the item's node — a length,
|
|
778
|
+
* or the content's for `fit-content` and its kin — or NaN. */
|
|
779
|
+
set: number;
|
|
780
|
+
/** Its border-box width stretched across its container: the container's
|
|
781
|
+
* content width, less its margins. */
|
|
782
|
+
stretch: number;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
/**
|
|
786
|
+
* Whether two widths are the same to a float32's precision. Yoga keeps
|
|
787
|
+
* every length as a float32, a few of its own operations deep, and hands
|
|
788
|
+
* back a width this engine meant rounded — down as often as up.
|
|
789
|
+
*/
|
|
790
|
+
function nearly(a: number, b: number): boolean {
|
|
791
|
+
return Math.abs(a - b) <= Math.max(Math.abs(a), Math.abs(b)) * 2 ** -20;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* Yoga's width for an item, as this engine meant it: the first of
|
|
796
|
+
* `intended` it is the float32 of, or its own where it is none of them. A
|
|
797
|
+
* box exactly as wide as its text — `width: fit-content` in a column, an
|
|
798
|
+
* item as wide as its content in a row, a flex box sized to what it holds —
|
|
799
|
+
* came back a hair narrower than the text, and laid out there its last word
|
|
800
|
+
* wrapped: meetup.com's "About us" and "Related topics" were two lines.
|
|
801
|
+
*/
|
|
802
|
+
function meant(width: number, ...intended: number[]): number {
|
|
803
|
+
for (const w of intended) {
|
|
804
|
+
if (Number.isFinite(w) && nearly(width, w)) return w;
|
|
805
|
+
}
|
|
806
|
+
return width;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
/** Set a length on the node; the points it set, or NaN where it set a
|
|
810
|
+
* percentage, which Yoga resolves, or nothing. */
|
|
214
811
|
function setLength(
|
|
812
|
+
node: YogaNode,
|
|
813
|
+
across: boolean,
|
|
215
814
|
len: ComputedStyle['width'],
|
|
216
815
|
base: number,
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
816
|
+
/** Padding and border a `content-box` length goes without. */
|
|
817
|
+
extra: number,
|
|
818
|
+
): number {
|
|
819
|
+
const px = (v: number) => {
|
|
820
|
+
if (across) node.setWidth(v);
|
|
821
|
+
else node.setHeight(v);
|
|
822
|
+
return v;
|
|
823
|
+
};
|
|
824
|
+
const percent = (v: number) => {
|
|
825
|
+
if (across) node.setWidthPercent(v);
|
|
826
|
+
else node.setHeightPercent(v);
|
|
827
|
+
return NaN;
|
|
828
|
+
};
|
|
829
|
+
if (len === AUTO) return NaN;
|
|
225
830
|
if (isPct(len)) {
|
|
226
|
-
|
|
227
|
-
|
|
831
|
+
// Yoga takes a percentage or points, not both: `calc(100% - 20px)`
|
|
832
|
+
// resolves here where its base is known, and so does a percentage with
|
|
833
|
+
// padding to add, and a percentage is kept alone where it is not
|
|
834
|
+
if (!len.px && !len.of && !extra) return percent(len.pct);
|
|
835
|
+
if (Number.isFinite(base)) return px(resolve(len, base) + extra);
|
|
836
|
+
if (len.of) return NaN;
|
|
837
|
+
return percent(len.pct);
|
|
228
838
|
}
|
|
229
|
-
|
|
230
|
-
setPx(len);
|
|
839
|
+
return px(len + extra);
|
|
231
840
|
}
|
|
232
841
|
|
|
233
842
|
/**
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
* draws
|
|
843
|
+
* The size of an item's content, the measure function's answer. Yoga holds
|
|
844
|
+
* the item's padding and border and adds them itself, so this answers
|
|
845
|
+
* inside them: a border box here was an item its padding's height taller
|
|
846
|
+
* than a browser draws it. Asked for a width it may take up to, or none,
|
|
847
|
+
* an item is as wide as its content, its max-content width (CSS Flexbox
|
|
848
|
+
* 9.2, `flex-basis: auto`), rather than as wide as the row; asked for one
|
|
849
|
+
* exactly, it is that wide. Its height is its content's at that width.
|
|
238
850
|
*/
|
|
239
851
|
function measureBox(
|
|
240
852
|
box: Box,
|
|
241
853
|
ctx: LayoutContext,
|
|
242
|
-
|
|
854
|
+
inner: number,
|
|
243
855
|
): { width: number; height: number } {
|
|
244
|
-
ctx.layoutSubtree(box,
|
|
245
|
-
return {
|
|
856
|
+
ctx.layoutSubtree(box, inner + box.horizontalExtra);
|
|
857
|
+
return {
|
|
858
|
+
width: inner,
|
|
859
|
+
height: Math.max(0, box.height - box.verticalExtra),
|
|
860
|
+
};
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
/** The width an item's content is measured at: the width Yoga gives it
|
|
864
|
+
* exactly, or its max-content width, no wider than any it may take up to
|
|
865
|
+
* (CSS Flexbox 9.2). */
|
|
866
|
+
function innerWidth(
|
|
867
|
+
width: number,
|
|
868
|
+
mode: number,
|
|
869
|
+
maxContent: () => number,
|
|
870
|
+
): number {
|
|
871
|
+
if (mode === Y.MEASURE_MODE_EXACTLY && Number.isFinite(width)) {
|
|
872
|
+
return Math.max(0, width);
|
|
873
|
+
}
|
|
874
|
+
const content = maxContent();
|
|
875
|
+
if (mode !== Y.MEASURE_MODE_AT_MOST || !Number.isFinite(width)) {
|
|
876
|
+
return content;
|
|
877
|
+
}
|
|
878
|
+
// a room exactly as wide as the content, as Yoga holds it, is room for it
|
|
879
|
+
return content <= width || nearly(content, width)
|
|
880
|
+
? content
|
|
881
|
+
: Math.max(0, width);
|
|
246
882
|
}
|
|
247
883
|
|
|
884
|
+
/**
|
|
885
|
+
* An item's automatic minimum (CSS Flexbox 4.5): with `min-width: auto` in
|
|
886
|
+
* a row, or `min-height: auto` in a column, an item its content sizes is no
|
|
887
|
+
* smaller along the row than its content comes to — its min-content width,
|
|
888
|
+
* or its content's height at its width.
|
|
889
|
+
* Yoga has no such minimum, and shrank an item under a long word or a
|
|
890
|
+
* column's content, which ran out over the next one; `min-w-0` is what
|
|
891
|
+
* lets an item shrink past it, and so `auto` is kept apart from 0.
|
|
892
|
+
*
|
|
893
|
+
* Asked of an item only where its content overflows it at the size Yoga
|
|
894
|
+
* gave it, laid out there as the final pass would lay it out and keeps
|
|
895
|
+
* (`Laid`), so a row with room pays for nothing. True where some item
|
|
896
|
+
* was given a minimum and the row has to be laid out again.
|
|
897
|
+
*/
|
|
898
|
+
function autoMinimums(
|
|
899
|
+
items: { box: Box; node: YogaNode; laid: Laid }[],
|
|
900
|
+
row: boolean,
|
|
901
|
+
ctx: LayoutContext,
|
|
902
|
+
containingWidth: number,
|
|
903
|
+
): boolean {
|
|
904
|
+
let changed = false;
|
|
905
|
+
for (const { box, node, laid } of items) {
|
|
906
|
+
if (box.kind === 'text' || box.kind === 'break') continue;
|
|
907
|
+
const style = box.style;
|
|
908
|
+
// a box that scrolls or clips has none, but for one that asks for its
|
|
909
|
+
// content's height
|
|
910
|
+
const asked = !row && style.minHeightKeyword !== null;
|
|
911
|
+
if (!asked && scrolls(style)) {
|
|
912
|
+
continue;
|
|
913
|
+
}
|
|
914
|
+
const width = meant(
|
|
915
|
+
node.getComputedWidth(),
|
|
916
|
+
laid.set,
|
|
917
|
+
laid.stretch,
|
|
918
|
+
laid.width,
|
|
919
|
+
);
|
|
920
|
+
// a replaced item's content along a row is its natural width
|
|
921
|
+
if (row && box.kind === 'replaced') {
|
|
922
|
+
if (style.minWidth !== AUTO || style.minWidthKeyword) continue;
|
|
923
|
+
const least = replacedMinimum(box, containingWidth);
|
|
924
|
+
if (least === null || width >= least - 0.01) continue;
|
|
925
|
+
node.setMinWidth(least);
|
|
926
|
+
changed = true;
|
|
927
|
+
continue;
|
|
928
|
+
}
|
|
929
|
+
// An item with a ratio and a definite height is along a row as wide
|
|
930
|
+
// as that height makes it, or as its content at its narrowest where
|
|
931
|
+
// that is wider (4.5's content size suggestion, its min-content size
|
|
932
|
+
// through the ratio, and CSS Sizing 4, 5.2) — and no wider for it
|
|
933
|
+
// than a width of its own
|
|
934
|
+
if (
|
|
935
|
+
row &&
|
|
936
|
+
box.kind !== 'replaced' &&
|
|
937
|
+
style.minWidth === AUTO &&
|
|
938
|
+
!style.minWidthKeyword
|
|
939
|
+
) {
|
|
940
|
+
const through = ratioBasis(box);
|
|
941
|
+
if (through !== null) {
|
|
942
|
+
let least = Math.max(through, minContentOf(box, ctx, laid));
|
|
943
|
+
const own = resolveOrNull(style.width, containingWidth);
|
|
944
|
+
const extra =
|
|
945
|
+
style.boxSizing === 'border-box' ? 0 : box.horizontalExtra;
|
|
946
|
+
if (own !== null) least = Math.min(least, own + extra);
|
|
947
|
+
if (style.maxWidth !== 'none') {
|
|
948
|
+
const most = resolveOrNull(style.maxWidth, containingWidth);
|
|
949
|
+
if (most !== null) least = Math.min(least, most + extra);
|
|
950
|
+
}
|
|
951
|
+
if (width >= least - 0.01) continue;
|
|
952
|
+
node.setMinWidth(least);
|
|
953
|
+
changed = true;
|
|
954
|
+
continue;
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
if (
|
|
958
|
+
row
|
|
959
|
+
? style.minWidth !== AUTO || style.minWidthKeyword || style.widthKeyword
|
|
960
|
+
: style.minHeight !== AUTO && !asked
|
|
961
|
+
) {
|
|
962
|
+
continue;
|
|
963
|
+
}
|
|
964
|
+
// One with a width of its own is no narrower along a row than the
|
|
965
|
+
// lesser of that width and its content at its narrowest (4.5's
|
|
966
|
+
// specified and content size suggestions): a `width: 250px` sidebar
|
|
967
|
+
// with `flex-basis: 0` is 250 wide beside the item that takes the
|
|
968
|
+
// rest, and one holding a longer word is still no wider than 250
|
|
969
|
+
if (row && style.width !== AUTO) {
|
|
970
|
+
const own = resolveOrNull(style.width, containingWidth);
|
|
971
|
+
if (own === null) continue;
|
|
972
|
+
const extra = style.boxSizing === 'border-box' ? 0 : box.horizontalExtra;
|
|
973
|
+
let least = own + extra;
|
|
974
|
+
if (style.maxWidth !== 'none') {
|
|
975
|
+
const most = resolveOrNull(style.maxWidth, containingWidth);
|
|
976
|
+
if (most !== null) least = Math.min(least, most + extra);
|
|
977
|
+
}
|
|
978
|
+
if (width >= least - 0.01) continue;
|
|
979
|
+
least = Math.min(least, minContentOf(box, ctx, laid));
|
|
980
|
+
if (node.getComputedWidth() >= least - 0.01) continue;
|
|
981
|
+
node.setMinWidth(least);
|
|
982
|
+
changed = true;
|
|
983
|
+
continue;
|
|
984
|
+
}
|
|
985
|
+
// no narrower than its content at its widest, where Yoga measured that
|
|
986
|
+
// — and than what a ratio makes of its least height, which a content
|
|
987
|
+
// no wider may still be held to
|
|
988
|
+
const widest = row ? MAX_CONTENT.get(box) : undefined;
|
|
989
|
+
if (
|
|
990
|
+
widest !== undefined &&
|
|
991
|
+
transferredWidth(box, widest + box.horizontalExtra) <= width + 0.5
|
|
992
|
+
) {
|
|
993
|
+
continue;
|
|
994
|
+
}
|
|
995
|
+
if (!(Math.abs(laid.width - width) <= 0.01)) {
|
|
996
|
+
ctx.layoutSubtree(box, width);
|
|
997
|
+
laid.width = box.width;
|
|
998
|
+
laid.height = box.height;
|
|
999
|
+
}
|
|
1000
|
+
let least: number;
|
|
1001
|
+
if (row) {
|
|
1002
|
+
// or than what it drew at the width it has: nothing overflows it
|
|
1003
|
+
const drawn = intrinsicWidth(box) + box.horizontalExtra;
|
|
1004
|
+
if (transferredWidth(box, drawn) <= width + 0.5) continue;
|
|
1005
|
+
// within what a ratio makes of its least and greatest heights (4.5's
|
|
1006
|
+
// content size suggestion)
|
|
1007
|
+
least = transferredWidth(box, minContentOf(box, ctx, laid));
|
|
1008
|
+
const extra = style.boxSizing === 'border-box' ? 0 : box.horizontalExtra;
|
|
1009
|
+
if (style.maxWidth !== 'none') {
|
|
1010
|
+
const most = resolveOrNull(style.maxWidth, containingWidth);
|
|
1011
|
+
if (most !== null) least = Math.min(least, most + extra);
|
|
1012
|
+
}
|
|
1013
|
+
if (node.getComputedWidth() >= least - 0.01) continue;
|
|
1014
|
+
node.setMinWidth(least);
|
|
1015
|
+
} else {
|
|
1016
|
+
// its height, or where it has one of its own and its content comes to
|
|
1017
|
+
// less, its content's: the lesser of the two (4.5)
|
|
1018
|
+
let content: number;
|
|
1019
|
+
if (box.kind === 'replaced') content = laid.height;
|
|
1020
|
+
else if (style.height !== AUTO && percentHeightsIn(box)) {
|
|
1021
|
+
// what its content comes to where it has no height to take
|
|
1022
|
+
// percentages of, as an intrinsic size is measured: laid out so
|
|
1023
|
+
// apart, and the final pass lays it out again
|
|
1024
|
+
FLEXED_HEIGHT.set(box, NaN);
|
|
1025
|
+
try {
|
|
1026
|
+
ctx.layoutSubtree(box, width);
|
|
1027
|
+
} finally {
|
|
1028
|
+
FLEXED_HEIGHT.delete(box);
|
|
1029
|
+
}
|
|
1030
|
+
content = contentBottom(box) + box.verticalExtra;
|
|
1031
|
+
laid.width = NaN;
|
|
1032
|
+
} else content = contentBottom(box) + box.verticalExtra;
|
|
1033
|
+
// and a ratio's content is at least its width through the ratio,
|
|
1034
|
+
// height of its own or not (CSS Sizing 4, 5.1)
|
|
1035
|
+
const aspect = style.aspectRatio;
|
|
1036
|
+
if (aspect && box.kind !== 'replaced') {
|
|
1037
|
+
content = Math.max(
|
|
1038
|
+
content,
|
|
1039
|
+
style.boxSizing === 'border-box'
|
|
1040
|
+
? box.width / aspect.ratio
|
|
1041
|
+
: box.contentWidth / aspect.ratio + box.verticalExtra,
|
|
1042
|
+
);
|
|
1043
|
+
}
|
|
1044
|
+
// within what the ratio makes of its least and greatest widths
|
|
1045
|
+
if (box.kind !== 'replaced') {
|
|
1046
|
+
content = transferredHeight(box, content, containingWidth);
|
|
1047
|
+
}
|
|
1048
|
+
least = Math.min(laid.height, content);
|
|
1049
|
+
const extra = style.boxSizing === 'border-box' ? 0 : box.verticalExtra;
|
|
1050
|
+
if (style.maxHeight !== 'none') {
|
|
1051
|
+
const most = resolveOrNull(style.maxHeight, NaN);
|
|
1052
|
+
if (most !== null) least = Math.min(least, most + extra);
|
|
1053
|
+
}
|
|
1054
|
+
if (node.getComputedHeight() >= least - 0.01) continue;
|
|
1055
|
+
node.setMinHeight(least);
|
|
1056
|
+
}
|
|
1057
|
+
changed = true;
|
|
1058
|
+
}
|
|
1059
|
+
return changed;
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
/** An item's min-content width, its border box's, taken the once: its
|
|
1063
|
+
* content's, whatever width it has of its own (`keywordWidth`'s too). */
|
|
1064
|
+
function minContentOf(box: Box, ctx: LayoutContext, laid: Laid): number {
|
|
1065
|
+
if (box.intrinsicMinContent < 0) {
|
|
1066
|
+
const exact = ctx.fonts ? exactMinContent(box, ctx.fonts) : null;
|
|
1067
|
+
box.intrinsicMinContent =
|
|
1068
|
+
exact ?? measureIntrinsicWidth(box, ctx, MIN_CONTENT_PROBE, true);
|
|
1069
|
+
// a probe lays the box out where the kept layout was
|
|
1070
|
+
if (exact === null) laid.width = NaN;
|
|
1071
|
+
}
|
|
1072
|
+
return box.intrinsicMinContent;
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
/** How far down a laid-out box's content reaches inside its content box:
|
|
1076
|
+
* its lines and its children, floats included, with their margins. */
|
|
1077
|
+
function contentBottom(box: Box): number {
|
|
1078
|
+
const top = box.contentY;
|
|
1079
|
+
let bottom = 0;
|
|
1080
|
+
for (const line of box.lines ?? []) {
|
|
1081
|
+
bottom = Math.max(bottom, line.y + line.height - top);
|
|
1082
|
+
}
|
|
1083
|
+
for (const child of box.children) {
|
|
1084
|
+
if (child.outOfFlow || child.kind === 'text' || child.kind === 'break') {
|
|
1085
|
+
continue;
|
|
1086
|
+
}
|
|
1087
|
+
if (child.kind === 'inline') continue;
|
|
1088
|
+
bottom = Math.max(
|
|
1089
|
+
bottom,
|
|
1090
|
+
child.y + child.height + child.marginBottom - top,
|
|
1091
|
+
);
|
|
1092
|
+
}
|
|
1093
|
+
return bottom;
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
/**
|
|
1097
|
+
* A row's items aligned by their baselines (CSS Flexbox 8.3, 9.4 step 8),
|
|
1098
|
+
* which Yoga cannot see: an item is a leaf there, and a leaf's baseline is
|
|
1099
|
+
* its bottom edge, so it lined them up by their bottoms. With the items laid
|
|
1100
|
+
* out, each line's, and for each the top margin that sets it at the line's
|
|
1101
|
+
* start with its first baseline where the lowest-reaching one's is — or
|
|
1102
|
+
* null where no line has two to align.
|
|
1103
|
+
*/
|
|
1104
|
+
function baselineLines<T extends { box: Box }>(
|
|
1105
|
+
style: ComputedStyle,
|
|
1106
|
+
items: readonly T[],
|
|
1107
|
+
): (T[] & { margins: number[] })[] | null {
|
|
1108
|
+
// a line that grows from its end is aligned from there, and left to Yoga
|
|
1109
|
+
if (style.flexWrap === 'wrap-reverse') return null;
|
|
1110
|
+
const wraps = style.flexWrap !== 'nowrap';
|
|
1111
|
+
// along a line the items go the way the main axis does, and the next
|
|
1112
|
+
// line starts where one does not
|
|
1113
|
+
const back =
|
|
1114
|
+
(style.flexDirection === 'row-reverse') !== (style.direction === 'rtl');
|
|
1115
|
+
const out: (T[] & { margins: number[] })[] = [];
|
|
1116
|
+
let line: T[] = [];
|
|
1117
|
+
let last = NaN;
|
|
1118
|
+
let several = false;
|
|
1119
|
+
const close = (): void => {
|
|
1120
|
+
if (!line.length) return;
|
|
1121
|
+
if (line.length > 1) several = true;
|
|
1122
|
+
let reach = -Infinity;
|
|
1123
|
+
const ascents = line.map(({ box }) => {
|
|
1124
|
+
const ascent = box.marginTop + itemBaseline(box);
|
|
1125
|
+
reach = Math.max(reach, ascent);
|
|
1126
|
+
return ascent;
|
|
1127
|
+
});
|
|
1128
|
+
const margins = line.map(
|
|
1129
|
+
({ box }, i) => box.marginTop + reach - ascents[i],
|
|
1130
|
+
);
|
|
1131
|
+
out.push(Object.assign(line, { margins }));
|
|
1132
|
+
};
|
|
1133
|
+
for (const item of items) {
|
|
1134
|
+
const box = item.box;
|
|
1135
|
+
if (wraps && line.length && (back ? box.x >= last : box.x <= last)) {
|
|
1136
|
+
close();
|
|
1137
|
+
line = [];
|
|
1138
|
+
}
|
|
1139
|
+
last = box.x;
|
|
1140
|
+
const own = box.style;
|
|
1141
|
+
const aligned = own.alignSelf === AUTO ? style.alignItems : own.alignSelf;
|
|
1142
|
+
// an `auto` margin across the line takes it over alignment
|
|
1143
|
+
if (
|
|
1144
|
+
aligned === 'baseline' &&
|
|
1145
|
+
own.marginTop !== AUTO &&
|
|
1146
|
+
own.marginBottom !== AUTO
|
|
1147
|
+
) {
|
|
1148
|
+
line.push(item);
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
close();
|
|
1152
|
+
// one alone on its line is at its start already
|
|
1153
|
+
return several ? out : null;
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
/**
|
|
1157
|
+
* How far an item is from where it belongs across its line, where Yoga
|
|
1158
|
+
* (3.2.1) aligned the lines in the pass it takes for a box that wraps or
|
|
1159
|
+
* aligns by baselines: it sets an item aligned to its line's start there
|
|
1160
|
+
* as though it had no margin at that side, and one centred as though it had
|
|
1161
|
+
* none at either — `items-start` in a wrapping row put every card's top
|
|
1162
|
+
* margin under it. By the margin at the start of the line's cross axis, and
|
|
1163
|
+
* by half what it exceeds the one at the end by, as Yoga holds them: for an
|
|
1164
|
+
* item set at its line's start (`started`), its baseline's. A column's,
|
|
1165
|
+
* whose cross axis runs right to left, and a box that wraps in reverse are
|
|
1166
|
+
* left as Yoga has them.
|
|
1167
|
+
*/
|
|
1168
|
+
function lineMarginFix(
|
|
1169
|
+
container: ComputedStyle,
|
|
1170
|
+
item: Box,
|
|
1171
|
+
node: YogaNode,
|
|
1172
|
+
row: boolean,
|
|
1173
|
+
started = false,
|
|
1174
|
+
): number {
|
|
1175
|
+
if (container.flexWrap === 'wrap-reverse') return 0;
|
|
1176
|
+
if (!row && container.direction === 'rtl') return 0;
|
|
1177
|
+
const style = item.style;
|
|
1178
|
+
// a margin that is `auto` takes the item over its alignment
|
|
1179
|
+
const lead = row ? style.marginTop : style.marginLeft;
|
|
1180
|
+
const trail = row ? style.marginBottom : style.marginRight;
|
|
1181
|
+
if (lead === AUTO || trail === AUTO) return 0;
|
|
1182
|
+
const align = started
|
|
1183
|
+
? 'flex-start'
|
|
1184
|
+
: style.alignSelf === AUTO
|
|
1185
|
+
? container.alignItems
|
|
1186
|
+
: style.alignSelf;
|
|
1187
|
+
if (align !== 'flex-start' && align !== 'center') return 0;
|
|
1188
|
+
const leading = node.getComputedMargin(row ? Y.EDGE_TOP : Y.EDGE_LEFT);
|
|
1189
|
+
if (align === 'flex-start') return leading;
|
|
1190
|
+
const trailing = node.getComputedMargin(row ? Y.EDGE_BOTTOM : Y.EDGE_RIGHT);
|
|
1191
|
+
return (leading - trailing) / 2;
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
/** An item's first baseline, down from its border edge: its content's
|
|
1195
|
+
* first line's, or where it has none, or is replaced, one synthesized
|
|
1196
|
+
* from its border box — its bottom edge. */
|
|
1197
|
+
function itemBaseline(item: Box): number {
|
|
1198
|
+
if (item.kind !== 'replaced') {
|
|
1199
|
+
const found = firstBaselineIn(item);
|
|
1200
|
+
if (found !== null) return Math.min(found - item.y, item.height);
|
|
1201
|
+
}
|
|
1202
|
+
return item.height;
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
/** Whether an item is stretched across its line: `stretch`, its own or its
|
|
1206
|
+
* container's, with no height of its own and no `auto` margin across. */
|
|
1207
|
+
function stretches(
|
|
1208
|
+
box: Box,
|
|
1209
|
+
container: ComputedStyle,
|
|
1210
|
+
/** Whether the line is a row's, across which the item's height is
|
|
1211
|
+
* stretched; a column's stretches its width. */
|
|
1212
|
+
row = true,
|
|
1213
|
+
): boolean {
|
|
1214
|
+
const style = box.style;
|
|
1215
|
+
const align =
|
|
1216
|
+
style.alignSelf === AUTO ? container.alignItems : style.alignSelf;
|
|
1217
|
+
if (align !== 'stretch') return false;
|
|
1218
|
+
return row
|
|
1219
|
+
? style.height === AUTO &&
|
|
1220
|
+
style.marginTop !== AUTO &&
|
|
1221
|
+
style.marginBottom !== AUTO
|
|
1222
|
+
: style.width === AUTO &&
|
|
1223
|
+
style.marginLeft !== AUTO &&
|
|
1224
|
+
style.marginRight !== AUTO;
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
/** How deep flex boxes are laid out by Yoga, one inside another's measure
|
|
1228
|
+
* (`layoutFlex`). */
|
|
1229
|
+
const FLEX_DEPTH = 64;
|
|
1230
|
+
|
|
248
1231
|
/** No Yoga assembly: stack the items instead of dropping them. */
|
|
249
1232
|
function layoutAsBlockFallback(
|
|
250
1233
|
box: Box,
|
|
@@ -253,9 +1236,9 @@ function layoutAsBlockFallback(
|
|
|
253
1236
|
): number {
|
|
254
1237
|
let y = box.contentY;
|
|
255
1238
|
for (const child of box.children) {
|
|
256
|
-
if (child.kind === 'text' &&
|
|
1239
|
+
if (child.kind === 'text' && isBlank(child.text)) continue;
|
|
257
1240
|
if (child.outOfFlow) {
|
|
258
|
-
|
|
1241
|
+
positionOutOfFlow(child, box, ctx, true);
|
|
259
1242
|
continue;
|
|
260
1243
|
}
|
|
261
1244
|
resolveEdges(child, contentWidth);
|
|
@@ -277,6 +1260,32 @@ const WRAP: Record<string, number> = {
|
|
|
277
1260
|
wrap: Y?.WRAP_WRAP,
|
|
278
1261
|
'wrap-reverse': Y?.WRAP_WRAP_REVERSE,
|
|
279
1262
|
};
|
|
1263
|
+
/**
|
|
1264
|
+
* A `justify-content` as the main axis takes it (CSS Box Alignment 3,
|
|
1265
|
+
* 6.1): `start` and `end` are the writing mode's, the main axis's own ends
|
|
1266
|
+
* turned round in a reversed direction; `left` and `right` are the page's
|
|
1267
|
+
* along a row, and `start` along a column, which has neither.
|
|
1268
|
+
*/
|
|
1269
|
+
function mainJustify(style: ComputedStyle): string {
|
|
1270
|
+
const justify = style.justifyContent;
|
|
1271
|
+
if (
|
|
1272
|
+
justify !== 'start' &&
|
|
1273
|
+
justify !== 'end' &&
|
|
1274
|
+
justify !== 'left' &&
|
|
1275
|
+
justify !== 'right'
|
|
1276
|
+
) {
|
|
1277
|
+
return justify;
|
|
1278
|
+
}
|
|
1279
|
+
const reverse = style.flexDirection.endsWith('-reverse');
|
|
1280
|
+
const row = style.flexDirection.startsWith('row');
|
|
1281
|
+
let start: boolean;
|
|
1282
|
+
if (justify === 'start') start = true;
|
|
1283
|
+
else if (justify === 'end') start = false;
|
|
1284
|
+
else if (!row) start = true;
|
|
1285
|
+
else start = (justify === 'left') === (style.direction !== 'rtl');
|
|
1286
|
+
return start !== reverse ? 'flex-start' : 'flex-end';
|
|
1287
|
+
}
|
|
1288
|
+
|
|
280
1289
|
const JUSTIFY: Record<string, number> = {
|
|
281
1290
|
'flex-start': Y?.JUSTIFY_FLEX_START,
|
|
282
1291
|
'flex-end': Y?.JUSTIFY_FLEX_END,
|