@number10/jsx-core 5.0.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/LICENSE +667 -0
- package/README.md +38 -0
- package/dist/animation/animated-signal.cjs +19 -0
- package/dist/animation/animated-signal.cjs.map +1 -0
- package/dist/animation/animated-signal.d.ts +35 -0
- package/dist/animation/animated-signal.d.ts.map +1 -0
- package/dist/animation/animated-signal.js +19 -0
- package/dist/animation/animated-signal.js.map +1 -0
- package/dist/animation/create-spring.cjs +80 -0
- package/dist/animation/create-spring.cjs.map +1 -0
- package/dist/animation/create-spring.d.ts +56 -0
- package/dist/animation/create-spring.d.ts.map +1 -0
- package/dist/animation/create-spring.js +80 -0
- package/dist/animation/create-spring.js.map +1 -0
- package/dist/animation/easing.cjs +76 -0
- package/dist/animation/easing.cjs.map +1 -0
- package/dist/animation/easing.d.ts +45 -0
- package/dist/animation/easing.d.ts.map +1 -0
- package/dist/animation/easing.js +76 -0
- package/dist/animation/easing.js.map +1 -0
- package/dist/animation/effect-definitions.cjs +441 -0
- package/dist/animation/effect-definitions.cjs.map +1 -0
- package/dist/animation/effect-definitions.d.ts +60 -0
- package/dist/animation/effect-definitions.d.ts.map +1 -0
- package/dist/animation/effect-definitions.js +441 -0
- package/dist/animation/effect-definitions.js.map +1 -0
- package/dist/animation/effect-engine.cjs +189 -0
- package/dist/animation/effect-engine.cjs.map +1 -0
- package/dist/animation/effect-engine.d.ts +70 -0
- package/dist/animation/effect-engine.d.ts.map +1 -0
- package/dist/animation/effect-engine.js +189 -0
- package/dist/animation/effect-engine.js.map +1 -0
- package/dist/animation/index.d.ts +24 -0
- package/dist/animation/index.d.ts.map +1 -0
- package/dist/animation/spring-physics.cjs +94 -0
- package/dist/animation/spring-physics.cjs.map +1 -0
- package/dist/animation/spring-physics.d.ts +145 -0
- package/dist/animation/spring-physics.d.ts.map +1 -0
- package/dist/animation/spring-physics.js +94 -0
- package/dist/animation/spring-physics.js.map +1 -0
- package/dist/animation/tween.cjs +67 -0
- package/dist/animation/tween.cjs.map +1 -0
- package/dist/animation/tween.d.ts +60 -0
- package/dist/animation/tween.d.ts.map +1 -0
- package/dist/animation/tween.js +67 -0
- package/dist/animation/tween.js.map +1 -0
- package/dist/animation/types.d.ts +31 -0
- package/dist/animation/types.d.ts.map +1 -0
- package/dist/animation/useSpring.cjs +152 -0
- package/dist/animation/useSpring.cjs.map +1 -0
- package/dist/animation/useSpring.d.ts +55 -0
- package/dist/animation/useSpring.d.ts.map +1 -0
- package/dist/animation/useSpring.js +149 -0
- package/dist/animation/useSpring.js.map +1 -0
- package/dist/animation/useTween.cjs +208 -0
- package/dist/animation/useTween.cjs.map +1 -0
- package/dist/animation/useTween.d.ts +116 -0
- package/dist/animation/useTween.d.ts.map +1 -0
- package/dist/animation/useTween.js +208 -0
- package/dist/animation/useTween.js.map +1 -0
- package/dist/border-geometry.cjs +447 -0
- package/dist/border-geometry.cjs.map +1 -0
- package/dist/border-geometry.d.ts +114 -0
- package/dist/border-geometry.d.ts.map +1 -0
- package/dist/border-geometry.js +447 -0
- package/dist/border-geometry.js.map +1 -0
- package/dist/colors/color-presets.cjs +236 -0
- package/dist/colors/color-presets.cjs.map +1 -0
- package/dist/colors/color-presets.d.ts +89 -0
- package/dist/colors/color-presets.d.ts.map +1 -0
- package/dist/colors/color-presets.js +236 -0
- package/dist/colors/color-presets.js.map +1 -0
- package/dist/colors/color-theme-helpers.cjs +32 -0
- package/dist/colors/color-theme-helpers.cjs.map +1 -0
- package/dist/colors/color-theme-helpers.d.ts +65 -0
- package/dist/colors/color-theme-helpers.d.ts.map +1 -0
- package/dist/colors/color-theme-helpers.js +32 -0
- package/dist/colors/color-theme-helpers.js.map +1 -0
- package/dist/colors/color-types.cjs +38 -0
- package/dist/colors/color-types.cjs.map +1 -0
- package/dist/colors/color-types.d.ts +112 -0
- package/dist/colors/color-types.d.ts.map +1 -0
- package/dist/colors/color-types.js +38 -0
- package/dist/colors/color-types.js.map +1 -0
- package/dist/colors/color-utils.cjs +197 -0
- package/dist/colors/color-utils.cjs.map +1 -0
- package/dist/colors/color-utils.d.ts +216 -0
- package/dist/colors/color-utils.d.ts.map +1 -0
- package/dist/colors/color-utils.js +197 -0
- package/dist/colors/color-utils.js.map +1 -0
- package/dist/colors/contrast-contracts.cjs +265 -0
- package/dist/colors/contrast-contracts.cjs.map +1 -0
- package/dist/colors/contrast-contracts.d.ts +289 -0
- package/dist/colors/contrast-contracts.d.ts.map +1 -0
- package/dist/colors/contrast-contracts.js +265 -0
- package/dist/colors/contrast-contracts.js.map +1 -0
- package/dist/colors/index.cjs +55 -0
- package/dist/colors/index.cjs.map +1 -0
- package/dist/colors/index.d.ts +16 -0
- package/dist/colors/index.d.ts.map +1 -0
- package/dist/colors/index.js +55 -0
- package/dist/colors/index.js.map +1 -0
- package/dist/core-props.cjs +66 -0
- package/dist/core-props.cjs.map +1 -0
- package/dist/core-props.d.ts +395 -0
- package/dist/core-props.d.ts.map +1 -0
- package/dist/core-props.js +66 -0
- package/dist/core-props.js.map +1 -0
- package/dist/design-tokens/design-token-presets.cjs +91 -0
- package/dist/design-tokens/design-token-presets.cjs.map +1 -0
- package/dist/design-tokens/design-token-presets.d.ts +34 -0
- package/dist/design-tokens/design-token-presets.d.ts.map +1 -0
- package/dist/design-tokens/design-token-presets.js +91 -0
- package/dist/design-tokens/design-token-presets.js.map +1 -0
- package/dist/design-tokens/design-token-types.d.ts +97 -0
- package/dist/design-tokens/design-token-types.d.ts.map +1 -0
- package/dist/design-tokens/index.cjs +10 -0
- package/dist/design-tokens/index.cjs.map +1 -0
- package/dist/design-tokens/index.d.ts +9 -0
- package/dist/design-tokens/index.d.ts.map +1 -0
- package/dist/design-tokens/index.js +10 -0
- package/dist/design-tokens/index.js.map +1 -0
- package/dist/dev-config.cjs +296 -0
- package/dist/dev-config.cjs.map +1 -0
- package/dist/dev-config.d.ts +238 -0
- package/dist/dev-config.d.ts.map +1 -0
- package/dist/dev-config.js +296 -0
- package/dist/dev-config.js.map +1 -0
- package/dist/effects.cjs +69 -0
- package/dist/effects.cjs.map +1 -0
- package/dist/effects.d.ts +152 -0
- package/dist/effects.d.ts.map +1 -0
- package/dist/effects.js +69 -0
- package/dist/effects.js.map +1 -0
- package/dist/global-registry.cjs +25 -0
- package/dist/global-registry.cjs.map +1 -0
- package/dist/global-registry.d.ts +19 -0
- package/dist/global-registry.d.ts.map +1 -0
- package/dist/global-registry.js +25 -0
- package/dist/global-registry.js.map +1 -0
- package/dist/hooks.cjs +378 -0
- package/dist/hooks.cjs.map +1 -0
- package/dist/hooks.d.ts +322 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +378 -0
- package/dist/hooks.js.map +1 -0
- package/dist/host-adapter.d.ts +414 -0
- package/dist/host-adapter.d.ts.map +1 -0
- package/dist/index.cjs +229 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +226 -0
- package/dist/index.js.map +1 -0
- package/dist/jsx-dev-runtime.cjs +10 -0
- package/dist/jsx-dev-runtime.cjs.map +1 -0
- package/dist/jsx-dev-runtime.d.ts +5 -0
- package/dist/jsx-dev-runtime.d.ts.map +1 -0
- package/dist/jsx-dev-runtime.js +11 -0
- package/dist/jsx-dev-runtime.js.map +1 -0
- package/dist/jsx-runtime.cjs +44 -0
- package/dist/jsx-runtime.cjs.map +1 -0
- package/dist/jsx-runtime.d.ts +24 -0
- package/dist/jsx-runtime.d.ts.map +1 -0
- package/dist/jsx-runtime.js +44 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/jsx-types.d.ts +25 -0
- package/dist/jsx-types.d.ts.map +1 -0
- package/dist/layout/appliers/container-applier.cjs +20 -0
- package/dist/layout/appliers/container-applier.cjs.map +1 -0
- package/dist/layout/appliers/container-applier.d.ts +9 -0
- package/dist/layout/appliers/container-applier.d.ts.map +1 -0
- package/dist/layout/appliers/container-applier.js +20 -0
- package/dist/layout/appliers/container-applier.js.map +1 -0
- package/dist/layout/appliers/position-applier.cjs +31 -0
- package/dist/layout/appliers/position-applier.cjs.map +1 -0
- package/dist/layout/appliers/position-applier.d.ts +8 -0
- package/dist/layout/appliers/position-applier.d.ts.map +1 -0
- package/dist/layout/appliers/position-applier.js +31 -0
- package/dist/layout/appliers/position-applier.js.map +1 -0
- package/dist/layout/layout-engine-test-utils.d.ts +26 -0
- package/dist/layout/layout-engine-test-utils.d.ts.map +1 -0
- package/dist/layout/layout-engine.cjs +628 -0
- package/dist/layout/layout-engine.cjs.map +1 -0
- package/dist/layout/layout-engine.d.ts +140 -0
- package/dist/layout/layout-engine.d.ts.map +1 -0
- package/dist/layout/layout-engine.js +628 -0
- package/dist/layout/layout-engine.js.map +1 -0
- package/dist/layout/strategies/base-strategy.cjs +31 -0
- package/dist/layout/strategies/base-strategy.cjs.map +1 -0
- package/dist/layout/strategies/base-strategy.d.ts +59 -0
- package/dist/layout/strategies/base-strategy.d.ts.map +1 -0
- package/dist/layout/strategies/base-strategy.js +31 -0
- package/dist/layout/strategies/base-strategy.js.map +1 -0
- package/dist/layout/strategies/column-layout.cjs +145 -0
- package/dist/layout/strategies/column-layout.cjs.map +1 -0
- package/dist/layout/strategies/column-layout.d.ts +38 -0
- package/dist/layout/strategies/column-layout.d.ts.map +1 -0
- package/dist/layout/strategies/column-layout.js +145 -0
- package/dist/layout/strategies/column-layout.js.map +1 -0
- package/dist/layout/strategies/row-layout.cjs +145 -0
- package/dist/layout/strategies/row-layout.cjs.map +1 -0
- package/dist/layout/strategies/row-layout.d.ts +38 -0
- package/dist/layout/strategies/row-layout.d.ts.map +1 -0
- package/dist/layout/strategies/row-layout.js +145 -0
- package/dist/layout/strategies/row-layout.js.map +1 -0
- package/dist/layout/strategies/stack-layout.cjs +94 -0
- package/dist/layout/strategies/stack-layout.cjs.map +1 -0
- package/dist/layout/strategies/stack-layout.d.ts +30 -0
- package/dist/layout/strategies/stack-layout.d.ts.map +1 -0
- package/dist/layout/strategies/stack-layout.js +94 -0
- package/dist/layout/strategies/stack-layout.js.map +1 -0
- package/dist/layout/types.d.ts +134 -0
- package/dist/layout/types.d.ts.map +1 -0
- package/dist/layout/utils/child-utils.cjs +129 -0
- package/dist/layout/utils/child-utils.cjs.map +1 -0
- package/dist/layout/utils/child-utils.d.ts +54 -0
- package/dist/layout/utils/child-utils.d.ts.map +1 -0
- package/dist/layout/utils/child-utils.js +129 -0
- package/dist/layout/utils/child-utils.js.map +1 -0
- package/dist/layout/utils/dimension-calculator.cjs +109 -0
- package/dist/layout/utils/dimension-calculator.cjs.map +1 -0
- package/dist/layout/utils/dimension-calculator.d.ts +59 -0
- package/dist/layout/utils/dimension-calculator.d.ts.map +1 -0
- package/dist/layout/utils/dimension-calculator.js +109 -0
- package/dist/layout/utils/dimension-calculator.js.map +1 -0
- package/dist/layout/utils/flex-distributor.cjs +173 -0
- package/dist/layout/utils/flex-distributor.cjs.map +1 -0
- package/dist/layout/utils/flex-distributor.d.ts +18 -0
- package/dist/layout/utils/flex-distributor.d.ts.map +1 -0
- package/dist/layout/utils/flex-distributor.js +173 -0
- package/dist/layout/utils/flex-distributor.js.map +1 -0
- package/dist/layout/utils/size-resolver.cjs +280 -0
- package/dist/layout/utils/size-resolver.cjs.map +1 -0
- package/dist/layout/utils/size-resolver.d.ts +84 -0
- package/dist/layout/utils/size-resolver.d.ts.map +1 -0
- package/dist/layout/utils/size-resolver.js +280 -0
- package/dist/layout/utils/size-resolver.js.map +1 -0
- package/dist/layout/utils/spacing-calculator.cjs +50 -0
- package/dist/layout/utils/spacing-calculator.cjs.map +1 -0
- package/dist/layout/utils/spacing-calculator.d.ts +27 -0
- package/dist/layout/utils/spacing-calculator.d.ts.map +1 -0
- package/dist/layout/utils/spacing-calculator.js +50 -0
- package/dist/layout/utils/spacing-calculator.js.map +1 -0
- package/dist/memo.cjs +18 -0
- package/dist/memo.cjs.map +1 -0
- package/dist/memo.d.ts +29 -0
- package/dist/memo.d.ts.map +1 -0
- package/dist/memo.js +18 -0
- package/dist/memo.js.map +1 -0
- package/dist/nineslice-contract.cjs +60 -0
- package/dist/nineslice-contract.cjs.map +1 -0
- package/dist/nineslice-contract.d.ts +107 -0
- package/dist/nineslice-contract.d.ts.map +1 -0
- package/dist/nineslice-contract.js +60 -0
- package/dist/nineslice-contract.js.map +1 -0
- package/dist/placeholder.cjs +12 -0
- package/dist/placeholder.cjs.map +1 -0
- package/dist/placeholder.d.ts +44 -0
- package/dist/placeholder.d.ts.map +1 -0
- package/dist/placeholder.js +12 -0
- package/dist/placeholder.js.map +1 -0
- package/dist/portal.cjs +89 -0
- package/dist/portal.cjs.map +1 -0
- package/dist/portal.d.ts +62 -0
- package/dist/portal.d.ts.map +1 -0
- package/dist/portal.js +89 -0
- package/dist/portal.js.map +1 -0
- package/dist/primitive-contracts.cjs +12 -0
- package/dist/primitive-contracts.cjs.map +1 -0
- package/dist/primitive-contracts.d.ts +186 -0
- package/dist/primitive-contracts.d.ts.map +1 -0
- package/dist/primitive-contracts.js +12 -0
- package/dist/primitive-contracts.js.map +1 -0
- package/dist/theme.cjs +332 -0
- package/dist/theme.cjs.map +1 -0
- package/dist/theme.d.ts +204 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +332 -0
- package/dist/theme.js.map +1 -0
- package/dist/types.d.ts +86 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/vdom/create-runtime.cjs +79 -0
- package/dist/vdom/create-runtime.cjs.map +1 -0
- package/dist/vdom/create-runtime.d.ts +7 -0
- package/dist/vdom/create-runtime.d.ts.map +1 -0
- package/dist/vdom/create-runtime.js +79 -0
- package/dist/vdom/create-runtime.js.map +1 -0
- package/dist/vdom/index.cjs +8 -0
- package/dist/vdom/index.cjs.map +1 -0
- package/dist/vdom/index.d.ts +4 -0
- package/dist/vdom/index.d.ts.map +1 -0
- package/dist/vdom/index.js +8 -0
- package/dist/vdom/index.js.map +1 -0
- package/dist/vdom/mount.cjs +161 -0
- package/dist/vdom/mount.cjs.map +1 -0
- package/dist/vdom/mount.d.ts +6 -0
- package/dist/vdom/mount.d.ts.map +1 -0
- package/dist/vdom/mount.js +161 -0
- package/dist/vdom/mount.js.map +1 -0
- package/dist/vdom/patch.cjs +163 -0
- package/dist/vdom/patch.cjs.map +1 -0
- package/dist/vdom/patch.d.ts +3 -0
- package/dist/vdom/patch.d.ts.map +1 -0
- package/dist/vdom/patch.js +163 -0
- package/dist/vdom/patch.js.map +1 -0
- package/dist/vdom/registry.cjs +85 -0
- package/dist/vdom/registry.cjs.map +1 -0
- package/dist/vdom/registry.d.ts +28 -0
- package/dist/vdom/registry.d.ts.map +1 -0
- package/dist/vdom/registry.js +85 -0
- package/dist/vdom/registry.js.map +1 -0
- package/dist/vdom/runtime-helpers.cjs +23 -0
- package/dist/vdom/runtime-helpers.cjs.map +1 -0
- package/dist/vdom/runtime-helpers.d.ts +8 -0
- package/dist/vdom/runtime-helpers.d.ts.map +1 -0
- package/dist/vdom/runtime-helpers.js +23 -0
- package/dist/vdom/runtime-helpers.js.map +1 -0
- package/dist/vdom/surface.cjs +107 -0
- package/dist/vdom/surface.cjs.map +1 -0
- package/dist/vdom/surface.d.ts +9 -0
- package/dist/vdom/surface.d.ts.map +1 -0
- package/dist/vdom/surface.js +107 -0
- package/dist/vdom/surface.js.map +1 -0
- package/dist/vdom/types.d.ts +104 -0
- package/dist/vdom/types.d.ts.map +1 -0
- package/dist/vdom/utils.cjs +146 -0
- package/dist/vdom/utils.cjs.map +1 -0
- package/dist/vdom/utils.d.ts +24 -0
- package/dist/vdom/utils.d.ts.map +1 -0
- package/dist/vdom/utils.js +146 -0
- package/dist/vdom/utils.js.map +1 -0
- package/dist/vdom.d.ts +4 -0
- package/dist/vdom.d.ts.map +1 -0
- package/dist/vector-draw-context.d.ts +63 -0
- package/dist/vector-draw-context.d.ts.map +1 -0
- package/package.json +161 -0
- package/vdom/index.cjs +1 -0
- package/vdom/index.d.ts +1 -0
- package/vdom/index.js +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"column-layout.js","sources":["../../../src/layout/strategies/column-layout.ts"],"sourcesContent":["/**\n * Column layout strategy (vertical stacking)\n * Like SwiftUI's VStack\n */\nimport type { LayoutChild, LayoutContext, LayoutLine, Position } from '../types'\nimport type { ContentMetrics } from '../utils/dimension-calculator'\nimport { parseSize, resolveSize } from '../utils/size-resolver'\nimport { calculateAlignItems } from '../utils/spacing-calculator'\nimport { BaseLayoutStrategy } from './base-strategy'\n\n/**\n * Column layout strategy - stacks children vertically\n */\nexport class ColumnLayoutStrategy extends BaseLayoutStrategy {\n /**\n * Calculate content dimensions for column layout\n * For flex children, uses a minimum default size to avoid chicken-egg sizing issues\n * @param children - Array of layout children\n * @param context - Layout context\n * @returns Content metrics\n */\n calculateMetrics(children: LayoutChild[], _context: LayoutContext): ContentMetrics {\n const FLEX_CHILD_MIN_SIZE = 100 // Minimum size for flex children in content calculation\n let maxWidth = 0\n let totalMainSize = 0\n\n for (const child of children) {\n const total = this.getTotalChildSize(child)\n maxWidth = Math.max(maxWidth, total.width)\n\n // Check if this child participates in flexbox (flex, flexShrink, or flexBasis)\n const props = child.child.__layoutProps\n const isFlexItem =\n (props?.flex !== undefined && props.flex > 0) ||\n props?.flexShrink !== undefined ||\n props?.flexBasis !== undefined\n // If flex child already has a resolved size (> 10), use it; otherwise use minimum\n const childHeight = isFlexItem && child.size.height <= 10 ? FLEX_CHILD_MIN_SIZE : total.height\n\n totalMainSize += childHeight\n }\n\n return {\n maxWidth,\n maxHeight: 0, // Not used for column\n totalMainSize,\n }\n }\n\n /**\n * Position a child in column layout\n * @param child - Layout child\n * @param _index - Child index (unused for column layout)\n * @param context - Layout context\n * @param currentMain - Current Y position\n * @returns Position and next main axis value\n */\n positionChild(\n child: LayoutChild,\n _index: number,\n context: LayoutContext,\n currentMain: number\n ): { position: Position; nextMain: number } {\n const margin = this.getMarginValues(child)\n const isHeadless = child.child.__layoutProps?.headless\n\n let x: number\n let y: number\n let nextMain: number\n\n if (isHeadless) {\n // Headless: calculate position directly using alignItems/justifyContent on full parent size\n const parentWidth = context.parentSize?.width ?? context.contentArea.width\n const parentHeight = context.parentSize?.height ?? context.contentArea.height\n\n // justifyContent on main axis (vertical) - manual calculation\n const justify = context.containerProps.justifyContent ?? 'start'\n let mainAxisOffset = 0\n if (justify === 'center') {\n mainAxisOffset = (parentHeight - child.size.height) / 2\n } else if (justify === 'end') {\n mainAxisOffset = parentHeight - child.size.height\n }\n // start and space-* variants use 0 for single item\n y = mainAxisOffset\n\n // alignItems on cross axis (horizontal)\n const crossAxisOffset = calculateAlignItems(\n context.containerProps.alignItems,\n parentWidth,\n child.size.width,\n 0,\n 0\n )\n x = crossAxisOffset\n\n // Don't advance currentMain for headless (they don't participate in flow)\n nextMain = currentMain\n } else {\n // Normal: use container padding and contentArea\n currentMain += margin.top\n y = context.padding.top + currentMain\n\n const alignOffset = calculateAlignItems(\n context.containerProps.alignItems,\n context.contentArea.width,\n child.size.width,\n margin.left,\n margin.right\n )\n x = context.padding.left + alignOffset\n\n nextMain = currentMain + child.size.height + margin.bottom\n }\n\n return {\n position: { x, y },\n nextMain,\n }\n }\n\n /**\n * Wrap children into lines based on available height\n * Used when flexWrap is 'wrap' or 'wrap-reverse'\n * @param children - Layout children to wrap\n * @param availableHeight - Available height for each line\n * @param gap - Gap between children\n * @returns Array of layout lines\n */\n wrapChildren(children: LayoutChild[], availableHeight: number, gap: number): LayoutLine[] {\n const lines: LayoutLine[] = []\n let currentLine: LayoutChild[] = []\n let currentLineHeight = 0\n let currentLineWidth = 0\n\n for (const child of children) {\n // Skip headless children in wrapping calculation\n if (child.child.__layoutProps?.headless) {\n continue\n }\n\n const margin = this.getMarginValues(child)\n const props = child.child.__layoutProps\n\n // For flex items with no size, use flexBasis or minHeight as hint for wrapping\n let effectiveHeight = child.size.height\n if (effectiveHeight <= 0 && props) {\n if (props.flexBasis !== undefined && typeof props.flexBasis === 'number') {\n effectiveHeight = props.flexBasis\n } else if (props.minHeight !== undefined) {\n // Resolve minHeight SizeValue to number\n const parsed = parseSize(props.minHeight)\n effectiveHeight = resolveSize(parsed, availableHeight, 100, undefined)\n } else if (props.flex && props.flex > 0) {\n // Use a reasonable default for flex items with no size hint\n effectiveHeight = 100\n }\n }\n\n const childHeight = effectiveHeight + margin.top + margin.bottom\n const childWidth = child.size.width + margin.left + margin.right\n\n const gapSpace = currentLine.length > 0 ? gap : 0\n const requiredSpace = currentLineHeight + childHeight + gapSpace\n\n // Check if we need to wrap to a new line (column)\n if (requiredSpace > availableHeight && currentLine.length > 0) {\n // Save current line\n lines.push({\n children: currentLine,\n mainAxisSize: currentLineHeight,\n crossAxisSize: currentLineWidth,\n })\n\n // Start new line\n currentLine = [child]\n currentLineHeight = childHeight\n currentLineWidth = childWidth\n } else {\n // Add to current line\n currentLine.push(child)\n currentLineHeight = requiredSpace\n currentLineWidth = Math.max(currentLineWidth, childWidth)\n }\n }\n\n // Add remaining line\n if (currentLine.length > 0) {\n lines.push({\n children: currentLine,\n mainAxisSize: currentLineHeight,\n crossAxisSize: currentLineWidth,\n })\n }\n\n return lines\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const sizeResolver = require("../utils/size-resolver.cjs");
|
|
4
|
+
const spacingCalculator = require("../utils/spacing-calculator.cjs");
|
|
5
|
+
const baseStrategy = require("./base-strategy.cjs");
|
|
6
|
+
class RowLayoutStrategy extends baseStrategy.BaseLayoutStrategy {
|
|
7
|
+
/**
|
|
8
|
+
* Calculate content dimensions for row layout
|
|
9
|
+
* For flex children, uses a minimum default size to avoid chicken-egg sizing issues
|
|
10
|
+
* @param children - Array of layout children
|
|
11
|
+
* @param context - Layout context
|
|
12
|
+
* @returns Content metrics
|
|
13
|
+
*/
|
|
14
|
+
calculateMetrics(children, _context) {
|
|
15
|
+
const FLEX_CHILD_MIN_SIZE = 100;
|
|
16
|
+
let maxHeight = 0;
|
|
17
|
+
let totalMainSize = 0;
|
|
18
|
+
for (const child of children) {
|
|
19
|
+
const total = this.getTotalChildSize(child);
|
|
20
|
+
maxHeight = Math.max(maxHeight, total.height);
|
|
21
|
+
const props = child.child.__layoutProps;
|
|
22
|
+
const isFlexItem = props?.flex !== void 0 && props.flex > 0 || props?.flexShrink !== void 0 || props?.flexBasis !== void 0;
|
|
23
|
+
const childWidth = isFlexItem && child.size.width <= 10 ? FLEX_CHILD_MIN_SIZE : total.width;
|
|
24
|
+
totalMainSize += childWidth;
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
maxWidth: 0,
|
|
28
|
+
// Not used for row
|
|
29
|
+
maxHeight,
|
|
30
|
+
totalMainSize
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Position a child in row layout
|
|
35
|
+
* @param child - Layout child
|
|
36
|
+
* @param _index - Child index (unused for row layout)
|
|
37
|
+
* @param context - Layout context
|
|
38
|
+
* @param currentMain - Current X position
|
|
39
|
+
* @returns Position and next main axis value
|
|
40
|
+
*/
|
|
41
|
+
positionChild(child, _index, context, currentMain) {
|
|
42
|
+
const margin = this.getMarginValues(child);
|
|
43
|
+
const isHeadless = child.child.__layoutProps?.headless;
|
|
44
|
+
let x;
|
|
45
|
+
let y;
|
|
46
|
+
let nextMain;
|
|
47
|
+
if (isHeadless) {
|
|
48
|
+
const parentWidth = context.parentSize?.width ?? context.contentArea.width;
|
|
49
|
+
const parentHeight = context.parentSize?.height ?? context.contentArea.height;
|
|
50
|
+
const justify = context.containerProps.justifyContent ?? "start";
|
|
51
|
+
let mainAxisOffset = 0;
|
|
52
|
+
if (justify === "center") {
|
|
53
|
+
mainAxisOffset = (parentWidth - child.size.width) / 2;
|
|
54
|
+
} else if (justify === "end") {
|
|
55
|
+
mainAxisOffset = parentWidth - child.size.width;
|
|
56
|
+
}
|
|
57
|
+
x = mainAxisOffset;
|
|
58
|
+
const crossAxisOffset = spacingCalculator.calculateAlignItems(
|
|
59
|
+
context.containerProps.alignItems,
|
|
60
|
+
parentHeight,
|
|
61
|
+
child.size.height,
|
|
62
|
+
0,
|
|
63
|
+
0
|
|
64
|
+
);
|
|
65
|
+
y = crossAxisOffset;
|
|
66
|
+
nextMain = currentMain;
|
|
67
|
+
} else {
|
|
68
|
+
currentMain += margin.left;
|
|
69
|
+
x = context.padding.left + currentMain;
|
|
70
|
+
const alignOffset = spacingCalculator.calculateAlignItems(
|
|
71
|
+
context.containerProps.alignItems,
|
|
72
|
+
context.contentArea.height,
|
|
73
|
+
child.size.height,
|
|
74
|
+
margin.top,
|
|
75
|
+
margin.bottom
|
|
76
|
+
);
|
|
77
|
+
y = context.padding.top + alignOffset;
|
|
78
|
+
nextMain = currentMain + child.size.width + margin.right;
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
position: { x, y },
|
|
82
|
+
nextMain
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Wrap children into lines based on available width
|
|
87
|
+
* Used when flexWrap is 'wrap' or 'wrap-reverse'
|
|
88
|
+
* @param children - Layout children to wrap
|
|
89
|
+
* @param availableWidth - Available width for each line
|
|
90
|
+
* @param gap - Gap between children
|
|
91
|
+
* @returns Array of layout lines
|
|
92
|
+
*/
|
|
93
|
+
wrapChildren(children, availableWidth, gap) {
|
|
94
|
+
const lines = [];
|
|
95
|
+
let currentLine = [];
|
|
96
|
+
let currentLineWidth = 0;
|
|
97
|
+
let currentLineHeight = 0;
|
|
98
|
+
for (const child of children) {
|
|
99
|
+
if (child.child.__layoutProps?.headless) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
const margin = this.getMarginValues(child);
|
|
103
|
+
const props = child.child.__layoutProps;
|
|
104
|
+
let effectiveWidth = child.size.width;
|
|
105
|
+
if (effectiveWidth <= 0 && props) {
|
|
106
|
+
if (props.flexBasis !== void 0 && typeof props.flexBasis === "number") {
|
|
107
|
+
effectiveWidth = props.flexBasis;
|
|
108
|
+
} else if (props.minWidth !== void 0) {
|
|
109
|
+
const parsed = sizeResolver.parseSize(props.minWidth);
|
|
110
|
+
effectiveWidth = sizeResolver.resolveSize(parsed, availableWidth, 100, void 0);
|
|
111
|
+
} else if (props.flex && props.flex > 0) {
|
|
112
|
+
effectiveWidth = 100;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
const childWidth = effectiveWidth + margin.left + margin.right;
|
|
116
|
+
const childHeight = child.size.height + margin.top + margin.bottom;
|
|
117
|
+
const gapSpace = currentLine.length > 0 ? gap : 0;
|
|
118
|
+
const requiredSpace = currentLineWidth + childWidth + gapSpace;
|
|
119
|
+
if (requiredSpace > availableWidth && currentLine.length > 0) {
|
|
120
|
+
lines.push({
|
|
121
|
+
children: currentLine,
|
|
122
|
+
mainAxisSize: currentLineWidth,
|
|
123
|
+
crossAxisSize: currentLineHeight
|
|
124
|
+
});
|
|
125
|
+
currentLine = [child];
|
|
126
|
+
currentLineWidth = childWidth;
|
|
127
|
+
currentLineHeight = childHeight;
|
|
128
|
+
} else {
|
|
129
|
+
currentLine.push(child);
|
|
130
|
+
currentLineWidth = requiredSpace;
|
|
131
|
+
currentLineHeight = Math.max(currentLineHeight, childHeight);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (currentLine.length > 0) {
|
|
135
|
+
lines.push({
|
|
136
|
+
children: currentLine,
|
|
137
|
+
mainAxisSize: currentLineWidth,
|
|
138
|
+
crossAxisSize: currentLineHeight
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
return lines;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
exports.RowLayoutStrategy = RowLayoutStrategy;
|
|
145
|
+
//# sourceMappingURL=row-layout.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row-layout.cjs","sources":["../../../src/layout/strategies/row-layout.ts"],"sourcesContent":["/**\n * Row layout strategy (horizontal stacking)\n * Like SwiftUI's HStack\n */\nimport type { LayoutChild, LayoutContext, LayoutLine, Position } from '../types'\nimport type { ContentMetrics } from '../utils/dimension-calculator'\nimport { parseSize, resolveSize } from '../utils/size-resolver'\nimport { calculateAlignItems } from '../utils/spacing-calculator'\nimport { BaseLayoutStrategy } from './base-strategy'\n\n/**\n * Row layout strategy - stacks children horizontally\n */\nexport class RowLayoutStrategy extends BaseLayoutStrategy {\n /**\n * Calculate content dimensions for row layout\n * For flex children, uses a minimum default size to avoid chicken-egg sizing issues\n * @param children - Array of layout children\n * @param context - Layout context\n * @returns Content metrics\n */\n calculateMetrics(children: LayoutChild[], _context: LayoutContext): ContentMetrics {\n const FLEX_CHILD_MIN_SIZE = 100 // Minimum size for flex children in content calculation\n let maxHeight = 0\n let totalMainSize = 0\n\n for (const child of children) {\n const total = this.getTotalChildSize(child)\n maxHeight = Math.max(maxHeight, total.height)\n\n // Check if this child participates in flexbox (flex, flexShrink, or flexBasis)\n const props = child.child.__layoutProps\n const isFlexItem =\n (props?.flex !== undefined && props.flex > 0) ||\n props?.flexShrink !== undefined ||\n props?.flexBasis !== undefined\n // If flex child already has a resolved size (> 10), use it; otherwise use minimum\n const childWidth = isFlexItem && child.size.width <= 10 ? FLEX_CHILD_MIN_SIZE : total.width\n\n totalMainSize += childWidth\n }\n\n return {\n maxWidth: 0, // Not used for row\n maxHeight,\n totalMainSize,\n }\n }\n\n /**\n * Position a child in row layout\n * @param child - Layout child\n * @param _index - Child index (unused for row layout)\n * @param context - Layout context\n * @param currentMain - Current X position\n * @returns Position and next main axis value\n */\n positionChild(\n child: LayoutChild,\n _index: number,\n context: LayoutContext,\n currentMain: number\n ): { position: Position; nextMain: number } {\n const margin = this.getMarginValues(child)\n const isHeadless = child.child.__layoutProps?.headless\n\n let x: number\n let y: number\n let nextMain: number\n\n if (isHeadless) {\n // Headless: calculate position directly using alignItems/justifyContent on full parent size\n const parentWidth = context.parentSize?.width ?? context.contentArea.width\n const parentHeight = context.parentSize?.height ?? context.contentArea.height\n\n // justifyContent on main axis (horizontal)\n const justify = context.containerProps.justifyContent ?? 'start'\n let mainAxisOffset = 0\n if (justify === 'center') {\n mainAxisOffset = (parentWidth - child.size.width) / 2\n } else if (justify === 'end') {\n mainAxisOffset = parentWidth - child.size.width\n }\n x = mainAxisOffset\n\n // alignItems on cross axis (vertical)\n const crossAxisOffset = calculateAlignItems(\n context.containerProps.alignItems,\n parentHeight,\n child.size.height,\n 0,\n 0\n )\n y = crossAxisOffset\n\n // Don't advance currentMain for headless\n nextMain = currentMain\n } else {\n // Normal: use container padding and contentArea\n currentMain += margin.left\n x = context.padding.left + currentMain\n\n const alignOffset = calculateAlignItems(\n context.containerProps.alignItems,\n context.contentArea.height,\n child.size.height,\n margin.top,\n margin.bottom\n )\n y = context.padding.top + alignOffset\n\n nextMain = currentMain + child.size.width + margin.right\n }\n\n return {\n position: { x, y },\n nextMain,\n }\n }\n\n /**\n * Wrap children into lines based on available width\n * Used when flexWrap is 'wrap' or 'wrap-reverse'\n * @param children - Layout children to wrap\n * @param availableWidth - Available width for each line\n * @param gap - Gap between children\n * @returns Array of layout lines\n */\n wrapChildren(children: LayoutChild[], availableWidth: number, gap: number): LayoutLine[] {\n const lines: LayoutLine[] = []\n let currentLine: LayoutChild[] = []\n let currentLineWidth = 0\n let currentLineHeight = 0\n\n for (const child of children) {\n // Skip headless children in wrapping calculation\n if (child.child.__layoutProps?.headless) {\n continue\n }\n\n const margin = this.getMarginValues(child)\n const props = child.child.__layoutProps\n\n // For flex items with no size, use flexBasis or minWidth as hint for wrapping\n let effectiveWidth = child.size.width\n if (effectiveWidth <= 0 && props) {\n if (props.flexBasis !== undefined && typeof props.flexBasis === 'number') {\n effectiveWidth = props.flexBasis\n } else if (props.minWidth !== undefined) {\n // Resolve minWidth SizeValue to number\n const parsed = parseSize(props.minWidth)\n effectiveWidth = resolveSize(parsed, availableWidth, 100, undefined)\n } else if (props.flex && props.flex > 0) {\n // Use a reasonable default for flex items with no size hint\n effectiveWidth = 100\n }\n }\n\n const childWidth = effectiveWidth + margin.left + margin.right\n const childHeight = child.size.height + margin.top + margin.bottom\n\n const gapSpace = currentLine.length > 0 ? gap : 0\n const requiredSpace = currentLineWidth + childWidth + gapSpace\n\n // Check if we need to wrap to a new line\n if (requiredSpace > availableWidth && currentLine.length > 0) {\n // Save current line\n lines.push({\n children: currentLine,\n mainAxisSize: currentLineWidth,\n crossAxisSize: currentLineHeight,\n })\n\n // Start new line\n currentLine = [child]\n currentLineWidth = childWidth\n currentLineHeight = childHeight\n } else {\n // Add to current line\n currentLine.push(child)\n currentLineWidth = requiredSpace\n currentLineHeight = Math.max(currentLineHeight, childHeight)\n }\n }\n\n // Add remaining line\n if (currentLine.length > 0) {\n lines.push({\n children: currentLine,\n mainAxisSize: currentLineWidth,\n crossAxisSize: currentLineHeight,\n })\n }\n\n return lines\n }\n}\n"],"names":["BaseLayoutStrategy","calculateAlignItems","parseSize","resolveSize"],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { LayoutChild, LayoutContext, LayoutLine, Position } from '../types';
|
|
2
|
+
import { ContentMetrics } from '../utils/dimension-calculator';
|
|
3
|
+
import { BaseLayoutStrategy } from './base-strategy';
|
|
4
|
+
/**
|
|
5
|
+
* Row layout strategy - stacks children horizontally
|
|
6
|
+
*/
|
|
7
|
+
export declare class RowLayoutStrategy extends BaseLayoutStrategy {
|
|
8
|
+
/**
|
|
9
|
+
* Calculate content dimensions for row layout
|
|
10
|
+
* For flex children, uses a minimum default size to avoid chicken-egg sizing issues
|
|
11
|
+
* @param children - Array of layout children
|
|
12
|
+
* @param context - Layout context
|
|
13
|
+
* @returns Content metrics
|
|
14
|
+
*/
|
|
15
|
+
calculateMetrics(children: LayoutChild[], _context: LayoutContext): ContentMetrics;
|
|
16
|
+
/**
|
|
17
|
+
* Position a child in row layout
|
|
18
|
+
* @param child - Layout child
|
|
19
|
+
* @param _index - Child index (unused for row layout)
|
|
20
|
+
* @param context - Layout context
|
|
21
|
+
* @param currentMain - Current X position
|
|
22
|
+
* @returns Position and next main axis value
|
|
23
|
+
*/
|
|
24
|
+
positionChild(child: LayoutChild, _index: number, context: LayoutContext, currentMain: number): {
|
|
25
|
+
position: Position;
|
|
26
|
+
nextMain: number;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Wrap children into lines based on available width
|
|
30
|
+
* Used when flexWrap is 'wrap' or 'wrap-reverse'
|
|
31
|
+
* @param children - Layout children to wrap
|
|
32
|
+
* @param availableWidth - Available width for each line
|
|
33
|
+
* @param gap - Gap between children
|
|
34
|
+
* @returns Array of layout lines
|
|
35
|
+
*/
|
|
36
|
+
wrapChildren(children: LayoutChild[], availableWidth: number, gap: number): LayoutLine[];
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=row-layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row-layout.d.ts","sourceRoot":"","sources":["../../../src/layout/strategies/row-layout.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAChF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAGnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAEpD;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,kBAAkB;IACvD;;;;;;OAMG;IACH,gBAAgB,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,QAAQ,EAAE,aAAa,GAAG,cAAc;IA4BlF;;;;;;;OAOG;IACH,aAAa,CACX,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,aAAa,EACtB,WAAW,EAAE,MAAM,GAClB;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE;IA0D3C;;;;;;;OAOG;IACH,YAAY,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,EAAE;CAoEzF"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { parseSize, resolveSize } from "../utils/size-resolver.js";
|
|
2
|
+
import { calculateAlignItems } from "../utils/spacing-calculator.js";
|
|
3
|
+
import { BaseLayoutStrategy } from "./base-strategy.js";
|
|
4
|
+
class RowLayoutStrategy extends BaseLayoutStrategy {
|
|
5
|
+
/**
|
|
6
|
+
* Calculate content dimensions for row layout
|
|
7
|
+
* For flex children, uses a minimum default size to avoid chicken-egg sizing issues
|
|
8
|
+
* @param children - Array of layout children
|
|
9
|
+
* @param context - Layout context
|
|
10
|
+
* @returns Content metrics
|
|
11
|
+
*/
|
|
12
|
+
calculateMetrics(children, _context) {
|
|
13
|
+
const FLEX_CHILD_MIN_SIZE = 100;
|
|
14
|
+
let maxHeight = 0;
|
|
15
|
+
let totalMainSize = 0;
|
|
16
|
+
for (const child of children) {
|
|
17
|
+
const total = this.getTotalChildSize(child);
|
|
18
|
+
maxHeight = Math.max(maxHeight, total.height);
|
|
19
|
+
const props = child.child.__layoutProps;
|
|
20
|
+
const isFlexItem = props?.flex !== void 0 && props.flex > 0 || props?.flexShrink !== void 0 || props?.flexBasis !== void 0;
|
|
21
|
+
const childWidth = isFlexItem && child.size.width <= 10 ? FLEX_CHILD_MIN_SIZE : total.width;
|
|
22
|
+
totalMainSize += childWidth;
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
maxWidth: 0,
|
|
26
|
+
// Not used for row
|
|
27
|
+
maxHeight,
|
|
28
|
+
totalMainSize
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Position a child in row layout
|
|
33
|
+
* @param child - Layout child
|
|
34
|
+
* @param _index - Child index (unused for row layout)
|
|
35
|
+
* @param context - Layout context
|
|
36
|
+
* @param currentMain - Current X position
|
|
37
|
+
* @returns Position and next main axis value
|
|
38
|
+
*/
|
|
39
|
+
positionChild(child, _index, context, currentMain) {
|
|
40
|
+
const margin = this.getMarginValues(child);
|
|
41
|
+
const isHeadless = child.child.__layoutProps?.headless;
|
|
42
|
+
let x;
|
|
43
|
+
let y;
|
|
44
|
+
let nextMain;
|
|
45
|
+
if (isHeadless) {
|
|
46
|
+
const parentWidth = context.parentSize?.width ?? context.contentArea.width;
|
|
47
|
+
const parentHeight = context.parentSize?.height ?? context.contentArea.height;
|
|
48
|
+
const justify = context.containerProps.justifyContent ?? "start";
|
|
49
|
+
let mainAxisOffset = 0;
|
|
50
|
+
if (justify === "center") {
|
|
51
|
+
mainAxisOffset = (parentWidth - child.size.width) / 2;
|
|
52
|
+
} else if (justify === "end") {
|
|
53
|
+
mainAxisOffset = parentWidth - child.size.width;
|
|
54
|
+
}
|
|
55
|
+
x = mainAxisOffset;
|
|
56
|
+
const crossAxisOffset = calculateAlignItems(
|
|
57
|
+
context.containerProps.alignItems,
|
|
58
|
+
parentHeight,
|
|
59
|
+
child.size.height,
|
|
60
|
+
0,
|
|
61
|
+
0
|
|
62
|
+
);
|
|
63
|
+
y = crossAxisOffset;
|
|
64
|
+
nextMain = currentMain;
|
|
65
|
+
} else {
|
|
66
|
+
currentMain += margin.left;
|
|
67
|
+
x = context.padding.left + currentMain;
|
|
68
|
+
const alignOffset = calculateAlignItems(
|
|
69
|
+
context.containerProps.alignItems,
|
|
70
|
+
context.contentArea.height,
|
|
71
|
+
child.size.height,
|
|
72
|
+
margin.top,
|
|
73
|
+
margin.bottom
|
|
74
|
+
);
|
|
75
|
+
y = context.padding.top + alignOffset;
|
|
76
|
+
nextMain = currentMain + child.size.width + margin.right;
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
position: { x, y },
|
|
80
|
+
nextMain
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Wrap children into lines based on available width
|
|
85
|
+
* Used when flexWrap is 'wrap' or 'wrap-reverse'
|
|
86
|
+
* @param children - Layout children to wrap
|
|
87
|
+
* @param availableWidth - Available width for each line
|
|
88
|
+
* @param gap - Gap between children
|
|
89
|
+
* @returns Array of layout lines
|
|
90
|
+
*/
|
|
91
|
+
wrapChildren(children, availableWidth, gap) {
|
|
92
|
+
const lines = [];
|
|
93
|
+
let currentLine = [];
|
|
94
|
+
let currentLineWidth = 0;
|
|
95
|
+
let currentLineHeight = 0;
|
|
96
|
+
for (const child of children) {
|
|
97
|
+
if (child.child.__layoutProps?.headless) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const margin = this.getMarginValues(child);
|
|
101
|
+
const props = child.child.__layoutProps;
|
|
102
|
+
let effectiveWidth = child.size.width;
|
|
103
|
+
if (effectiveWidth <= 0 && props) {
|
|
104
|
+
if (props.flexBasis !== void 0 && typeof props.flexBasis === "number") {
|
|
105
|
+
effectiveWidth = props.flexBasis;
|
|
106
|
+
} else if (props.minWidth !== void 0) {
|
|
107
|
+
const parsed = parseSize(props.minWidth);
|
|
108
|
+
effectiveWidth = resolveSize(parsed, availableWidth, 100, void 0);
|
|
109
|
+
} else if (props.flex && props.flex > 0) {
|
|
110
|
+
effectiveWidth = 100;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const childWidth = effectiveWidth + margin.left + margin.right;
|
|
114
|
+
const childHeight = child.size.height + margin.top + margin.bottom;
|
|
115
|
+
const gapSpace = currentLine.length > 0 ? gap : 0;
|
|
116
|
+
const requiredSpace = currentLineWidth + childWidth + gapSpace;
|
|
117
|
+
if (requiredSpace > availableWidth && currentLine.length > 0) {
|
|
118
|
+
lines.push({
|
|
119
|
+
children: currentLine,
|
|
120
|
+
mainAxisSize: currentLineWidth,
|
|
121
|
+
crossAxisSize: currentLineHeight
|
|
122
|
+
});
|
|
123
|
+
currentLine = [child];
|
|
124
|
+
currentLineWidth = childWidth;
|
|
125
|
+
currentLineHeight = childHeight;
|
|
126
|
+
} else {
|
|
127
|
+
currentLine.push(child);
|
|
128
|
+
currentLineWidth = requiredSpace;
|
|
129
|
+
currentLineHeight = Math.max(currentLineHeight, childHeight);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (currentLine.length > 0) {
|
|
133
|
+
lines.push({
|
|
134
|
+
children: currentLine,
|
|
135
|
+
mainAxisSize: currentLineWidth,
|
|
136
|
+
crossAxisSize: currentLineHeight
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
return lines;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
export {
|
|
143
|
+
RowLayoutStrategy
|
|
144
|
+
};
|
|
145
|
+
//# sourceMappingURL=row-layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row-layout.js","sources":["../../../src/layout/strategies/row-layout.ts"],"sourcesContent":["/**\n * Row layout strategy (horizontal stacking)\n * Like SwiftUI's HStack\n */\nimport type { LayoutChild, LayoutContext, LayoutLine, Position } from '../types'\nimport type { ContentMetrics } from '../utils/dimension-calculator'\nimport { parseSize, resolveSize } from '../utils/size-resolver'\nimport { calculateAlignItems } from '../utils/spacing-calculator'\nimport { BaseLayoutStrategy } from './base-strategy'\n\n/**\n * Row layout strategy - stacks children horizontally\n */\nexport class RowLayoutStrategy extends BaseLayoutStrategy {\n /**\n * Calculate content dimensions for row layout\n * For flex children, uses a minimum default size to avoid chicken-egg sizing issues\n * @param children - Array of layout children\n * @param context - Layout context\n * @returns Content metrics\n */\n calculateMetrics(children: LayoutChild[], _context: LayoutContext): ContentMetrics {\n const FLEX_CHILD_MIN_SIZE = 100 // Minimum size for flex children in content calculation\n let maxHeight = 0\n let totalMainSize = 0\n\n for (const child of children) {\n const total = this.getTotalChildSize(child)\n maxHeight = Math.max(maxHeight, total.height)\n\n // Check if this child participates in flexbox (flex, flexShrink, or flexBasis)\n const props = child.child.__layoutProps\n const isFlexItem =\n (props?.flex !== undefined && props.flex > 0) ||\n props?.flexShrink !== undefined ||\n props?.flexBasis !== undefined\n // If flex child already has a resolved size (> 10), use it; otherwise use minimum\n const childWidth = isFlexItem && child.size.width <= 10 ? FLEX_CHILD_MIN_SIZE : total.width\n\n totalMainSize += childWidth\n }\n\n return {\n maxWidth: 0, // Not used for row\n maxHeight,\n totalMainSize,\n }\n }\n\n /**\n * Position a child in row layout\n * @param child - Layout child\n * @param _index - Child index (unused for row layout)\n * @param context - Layout context\n * @param currentMain - Current X position\n * @returns Position and next main axis value\n */\n positionChild(\n child: LayoutChild,\n _index: number,\n context: LayoutContext,\n currentMain: number\n ): { position: Position; nextMain: number } {\n const margin = this.getMarginValues(child)\n const isHeadless = child.child.__layoutProps?.headless\n\n let x: number\n let y: number\n let nextMain: number\n\n if (isHeadless) {\n // Headless: calculate position directly using alignItems/justifyContent on full parent size\n const parentWidth = context.parentSize?.width ?? context.contentArea.width\n const parentHeight = context.parentSize?.height ?? context.contentArea.height\n\n // justifyContent on main axis (horizontal)\n const justify = context.containerProps.justifyContent ?? 'start'\n let mainAxisOffset = 0\n if (justify === 'center') {\n mainAxisOffset = (parentWidth - child.size.width) / 2\n } else if (justify === 'end') {\n mainAxisOffset = parentWidth - child.size.width\n }\n x = mainAxisOffset\n\n // alignItems on cross axis (vertical)\n const crossAxisOffset = calculateAlignItems(\n context.containerProps.alignItems,\n parentHeight,\n child.size.height,\n 0,\n 0\n )\n y = crossAxisOffset\n\n // Don't advance currentMain for headless\n nextMain = currentMain\n } else {\n // Normal: use container padding and contentArea\n currentMain += margin.left\n x = context.padding.left + currentMain\n\n const alignOffset = calculateAlignItems(\n context.containerProps.alignItems,\n context.contentArea.height,\n child.size.height,\n margin.top,\n margin.bottom\n )\n y = context.padding.top + alignOffset\n\n nextMain = currentMain + child.size.width + margin.right\n }\n\n return {\n position: { x, y },\n nextMain,\n }\n }\n\n /**\n * Wrap children into lines based on available width\n * Used when flexWrap is 'wrap' or 'wrap-reverse'\n * @param children - Layout children to wrap\n * @param availableWidth - Available width for each line\n * @param gap - Gap between children\n * @returns Array of layout lines\n */\n wrapChildren(children: LayoutChild[], availableWidth: number, gap: number): LayoutLine[] {\n const lines: LayoutLine[] = []\n let currentLine: LayoutChild[] = []\n let currentLineWidth = 0\n let currentLineHeight = 0\n\n for (const child of children) {\n // Skip headless children in wrapping calculation\n if (child.child.__layoutProps?.headless) {\n continue\n }\n\n const margin = this.getMarginValues(child)\n const props = child.child.__layoutProps\n\n // For flex items with no size, use flexBasis or minWidth as hint for wrapping\n let effectiveWidth = child.size.width\n if (effectiveWidth <= 0 && props) {\n if (props.flexBasis !== undefined && typeof props.flexBasis === 'number') {\n effectiveWidth = props.flexBasis\n } else if (props.minWidth !== undefined) {\n // Resolve minWidth SizeValue to number\n const parsed = parseSize(props.minWidth)\n effectiveWidth = resolveSize(parsed, availableWidth, 100, undefined)\n } else if (props.flex && props.flex > 0) {\n // Use a reasonable default for flex items with no size hint\n effectiveWidth = 100\n }\n }\n\n const childWidth = effectiveWidth + margin.left + margin.right\n const childHeight = child.size.height + margin.top + margin.bottom\n\n const gapSpace = currentLine.length > 0 ? gap : 0\n const requiredSpace = currentLineWidth + childWidth + gapSpace\n\n // Check if we need to wrap to a new line\n if (requiredSpace > availableWidth && currentLine.length > 0) {\n // Save current line\n lines.push({\n children: currentLine,\n mainAxisSize: currentLineWidth,\n crossAxisSize: currentLineHeight,\n })\n\n // Start new line\n currentLine = [child]\n currentLineWidth = childWidth\n currentLineHeight = childHeight\n } else {\n // Add to current line\n currentLine.push(child)\n currentLineWidth = requiredSpace\n currentLineHeight = Math.max(currentLineHeight, childHeight)\n }\n }\n\n // Add remaining line\n if (currentLine.length > 0) {\n lines.push({\n children: currentLine,\n mainAxisSize: currentLineWidth,\n crossAxisSize: currentLineHeight,\n })\n }\n\n return lines\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const animatedSignal = require("../../animation/animated-signal.cjs");
|
|
4
|
+
const baseStrategy = require("./base-strategy.cjs");
|
|
5
|
+
function toLayoutNumber(value) {
|
|
6
|
+
if (value === void 0) return void 0;
|
|
7
|
+
return animatedSignal.isAnimatedSignal(value) ? value.value : value;
|
|
8
|
+
}
|
|
9
|
+
class StackLayoutStrategy extends baseStrategy.BaseLayoutStrategy {
|
|
10
|
+
/**
|
|
11
|
+
* Calculate content dimensions for stack layout
|
|
12
|
+
* For stack, we track max dimensions as children overlay
|
|
13
|
+
* @param children - Array of layout children
|
|
14
|
+
* @param context - Layout context
|
|
15
|
+
* @returns Content metrics
|
|
16
|
+
*/
|
|
17
|
+
calculateMetrics(children, _context) {
|
|
18
|
+
let maxWidth = 0;
|
|
19
|
+
let maxHeight = 0;
|
|
20
|
+
for (const child of children) {
|
|
21
|
+
const total = this.getTotalChildSize(child);
|
|
22
|
+
maxWidth = Math.max(maxWidth, total.width);
|
|
23
|
+
maxHeight = Math.max(maxHeight, total.height);
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
maxWidth,
|
|
27
|
+
maxHeight,
|
|
28
|
+
totalMainSize: 0
|
|
29
|
+
// Not applicable for stack
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Position a child in stack layout
|
|
34
|
+
* All children positioned at same location, aligned via alignItems
|
|
35
|
+
* @param child - Layout child
|
|
36
|
+
* @param _index - Child index (unused for stack layout)
|
|
37
|
+
* @param context - Layout context
|
|
38
|
+
* @param currentMain - Current position (unused for stack)
|
|
39
|
+
* @returns Position and unchanged currentMain
|
|
40
|
+
*/
|
|
41
|
+
positionChild(child, _index, context, currentMain) {
|
|
42
|
+
const margin = this.getMarginValues(child);
|
|
43
|
+
const { alignItems } = context.containerProps;
|
|
44
|
+
const isHeadless = child.child.__layoutProps?.headless;
|
|
45
|
+
let x;
|
|
46
|
+
let y;
|
|
47
|
+
if (isHeadless) {
|
|
48
|
+
return {
|
|
49
|
+
position: {
|
|
50
|
+
x: toLayoutNumber(child.child.__layoutProps?.x) ?? 0,
|
|
51
|
+
y: toLayoutNumber(child.child.__layoutProps?.y) ?? 0
|
|
52
|
+
},
|
|
53
|
+
nextMain: currentMain
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
switch (alignItems) {
|
|
57
|
+
case "start":
|
|
58
|
+
x = context.padding.left + margin.left;
|
|
59
|
+
y = context.padding.top + margin.top;
|
|
60
|
+
break;
|
|
61
|
+
case "center":
|
|
62
|
+
x = context.padding.left + (context.contentArea.width - child.size.width) / 2;
|
|
63
|
+
y = context.padding.top + (context.contentArea.height - child.size.height) / 2;
|
|
64
|
+
break;
|
|
65
|
+
case "end":
|
|
66
|
+
x = context.padding.left + context.contentArea.width - child.size.width - margin.right;
|
|
67
|
+
y = context.padding.top + context.contentArea.height - child.size.height - margin.bottom;
|
|
68
|
+
break;
|
|
69
|
+
case "stretch":
|
|
70
|
+
x = context.padding.left + margin.left;
|
|
71
|
+
y = context.padding.top + margin.top;
|
|
72
|
+
break;
|
|
73
|
+
default:
|
|
74
|
+
x = context.padding.left + margin.left;
|
|
75
|
+
y = context.padding.top + margin.top;
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
const childX = toLayoutNumber(child.child.__layoutProps?.x);
|
|
79
|
+
const childY = toLayoutNumber(child.child.__layoutProps?.y);
|
|
80
|
+
if (childX !== void 0) {
|
|
81
|
+
x += childX;
|
|
82
|
+
}
|
|
83
|
+
if (childY !== void 0) {
|
|
84
|
+
y += childY;
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
position: { x, y },
|
|
88
|
+
nextMain: currentMain
|
|
89
|
+
// Stack doesn't advance main axis
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
exports.StackLayoutStrategy = StackLayoutStrategy;
|
|
94
|
+
//# sourceMappingURL=stack-layout.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stack-layout.cjs","sources":["../../../src/layout/strategies/stack-layout.ts"],"sourcesContent":["/**\n * Stack layout strategy (overlay positioning)\n * Like SwiftUI's ZStack - all children positioned at same location\n */\nimport { isAnimatedSignal } from '../../animation/animated-signal'\nimport type { LayoutChild, LayoutContext, Position } from '../types'\nimport type { ContentMetrics } from '../utils/dimension-calculator'\nimport { BaseLayoutStrategy } from './base-strategy'\n\n/**\n * Unwrap a layout prop value — resolves AnimatedSignal to its .value,\n * passes through plain numbers, returns undefined for undefined.\n */\nfunction toLayoutNumber(value: unknown): number | undefined {\n if (value === undefined) return undefined\n return isAnimatedSignal(value) ? value.value : (value as number)\n}\n\n/**\n * Stack layout strategy - overlays all children at the same position\n */\nexport class StackLayoutStrategy extends BaseLayoutStrategy {\n /**\n * Calculate content dimensions for stack layout\n * For stack, we track max dimensions as children overlay\n * @param children - Array of layout children\n * @param context - Layout context\n * @returns Content metrics\n */\n calculateMetrics(children: LayoutChild[], _context: LayoutContext): ContentMetrics {\n let maxWidth = 0\n let maxHeight = 0\n\n for (const child of children) {\n const total = this.getTotalChildSize(child)\n maxWidth = Math.max(maxWidth, total.width)\n maxHeight = Math.max(maxHeight, total.height)\n }\n\n return {\n maxWidth,\n maxHeight,\n totalMainSize: 0, // Not applicable for stack\n }\n }\n\n /**\n * Position a child in stack layout\n * All children positioned at same location, aligned via alignItems\n * @param child - Layout child\n * @param _index - Child index (unused for stack layout)\n * @param context - Layout context\n * @param currentMain - Current position (unused for stack)\n * @returns Position and unchanged currentMain\n */\n positionChild(\n child: LayoutChild,\n _index: number,\n context: LayoutContext,\n currentMain: number\n ): { position: Position; nextMain: number } {\n const margin = this.getMarginValues(child)\n const { alignItems } = context.containerProps\n const isHeadless = child.child.__layoutProps?.headless\n\n let x: number\n let y: number\n\n if (isHeadless) {\n return {\n position: {\n x: toLayoutNumber(child.child.__layoutProps?.x) ?? 0,\n y: toLayoutNumber(child.child.__layoutProps?.y) ?? 0,\n },\n nextMain: currentMain,\n }\n }\n\n // Position based on alignItems (applies to both axes for stack)\n switch (alignItems) {\n case 'start':\n x = context.padding.left + margin.left\n y = context.padding.top + margin.top\n break\n case 'center':\n x = context.padding.left + (context.contentArea.width - child.size.width) / 2\n y = context.padding.top + (context.contentArea.height - child.size.height) / 2\n break\n case 'end':\n x = context.padding.left + context.contentArea.width - child.size.width - margin.right\n y = context.padding.top + context.contentArea.height - child.size.height - margin.bottom\n break\n case 'stretch':\n // TODO: Implement stretch - for now behave like start\n x = context.padding.left + margin.left\n y = context.padding.top + margin.top\n break\n default:\n x = context.padding.left + margin.left\n y = context.padding.top + margin.top\n break\n }\n\n // Apply explicit x/y offsets if provided\n const childX = toLayoutNumber(child.child.__layoutProps?.x)\n const childY = toLayoutNumber(child.child.__layoutProps?.y)\n\n if (childX !== undefined) {\n x += childX\n }\n if (childY !== undefined) {\n y += childY\n }\n\n return {\n position: { x, y },\n nextMain: currentMain, // Stack doesn't advance main axis\n }\n }\n}\n"],"names":["isAnimatedSignal","BaseLayoutStrategy"],"mappings":";;;;AAaA,SAAS,eAAe,OAAoC;AAC1D,MAAI,UAAU,OAAW,QAAO;AAChC,SAAOA,eAAAA,iBAAiB,KAAK,IAAI,MAAM,QAAS;AAClD;AAKO,MAAM,4BAA4BC,aAAAA,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ1D,iBAAiB,UAAyB,UAAyC;AACjF,QAAI,WAAW;AACf,QAAI,YAAY;AAEhB,eAAW,SAAS,UAAU;AAC5B,YAAM,QAAQ,KAAK,kBAAkB,KAAK;AAC1C,iBAAW,KAAK,IAAI,UAAU,MAAM,KAAK;AACzC,kBAAY,KAAK,IAAI,WAAW,MAAM,MAAM;AAAA,IAC9C;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,eAAe;AAAA;AAAA,IAAA;AAAA,EAEnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,cACE,OACA,QACA,SACA,aAC0C;AAC1C,UAAM,SAAS,KAAK,gBAAgB,KAAK;AACzC,UAAM,EAAE,eAAe,QAAQ;AAC/B,UAAM,aAAa,MAAM,MAAM,eAAe;AAE9C,QAAI;AACJ,QAAI;AAEJ,QAAI,YAAY;AACd,aAAO;AAAA,QACL,UAAU;AAAA,UACR,GAAG,eAAe,MAAM,MAAM,eAAe,CAAC,KAAK;AAAA,UACnD,GAAG,eAAe,MAAM,MAAM,eAAe,CAAC,KAAK;AAAA,QAAA;AAAA,QAErD,UAAU;AAAA,MAAA;AAAA,IAEd;AAGA,YAAQ,YAAA;AAAA,MACN,KAAK;AACH,YAAI,QAAQ,QAAQ,OAAO,OAAO;AAClC,YAAI,QAAQ,QAAQ,MAAM,OAAO;AACjC;AAAA,MACF,KAAK;AACH,YAAI,QAAQ,QAAQ,QAAQ,QAAQ,YAAY,QAAQ,MAAM,KAAK,SAAS;AAC5E,YAAI,QAAQ,QAAQ,OAAO,QAAQ,YAAY,SAAS,MAAM,KAAK,UAAU;AAC7E;AAAA,MACF,KAAK;AACH,YAAI,QAAQ,QAAQ,OAAO,QAAQ,YAAY,QAAQ,MAAM,KAAK,QAAQ,OAAO;AACjF,YAAI,QAAQ,QAAQ,MAAM,QAAQ,YAAY,SAAS,MAAM,KAAK,SAAS,OAAO;AAClF;AAAA,MACF,KAAK;AAEH,YAAI,QAAQ,QAAQ,OAAO,OAAO;AAClC,YAAI,QAAQ,QAAQ,MAAM,OAAO;AACjC;AAAA,MACF;AACE,YAAI,QAAQ,QAAQ,OAAO,OAAO;AAClC,YAAI,QAAQ,QAAQ,MAAM,OAAO;AACjC;AAAA,IAAA;AAIJ,UAAM,SAAS,eAAe,MAAM,MAAM,eAAe,CAAC;AAC1D,UAAM,SAAS,eAAe,MAAM,MAAM,eAAe,CAAC;AAE1D,QAAI,WAAW,QAAW;AACxB,WAAK;AAAA,IACP;AACA,QAAI,WAAW,QAAW;AACxB,WAAK;AAAA,IACP;AAEA,WAAO;AAAA,MACL,UAAU,EAAE,GAAG,EAAA;AAAA,MACf,UAAU;AAAA;AAAA,IAAA;AAAA,EAEd;AACF;;"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { LayoutChild, LayoutContext, Position } from '../types';
|
|
2
|
+
import { ContentMetrics } from '../utils/dimension-calculator';
|
|
3
|
+
import { BaseLayoutStrategy } from './base-strategy';
|
|
4
|
+
/**
|
|
5
|
+
* Stack layout strategy - overlays all children at the same position
|
|
6
|
+
*/
|
|
7
|
+
export declare class StackLayoutStrategy extends BaseLayoutStrategy {
|
|
8
|
+
/**
|
|
9
|
+
* Calculate content dimensions for stack layout
|
|
10
|
+
* For stack, we track max dimensions as children overlay
|
|
11
|
+
* @param children - Array of layout children
|
|
12
|
+
* @param context - Layout context
|
|
13
|
+
* @returns Content metrics
|
|
14
|
+
*/
|
|
15
|
+
calculateMetrics(children: LayoutChild[], _context: LayoutContext): ContentMetrics;
|
|
16
|
+
/**
|
|
17
|
+
* Position a child in stack layout
|
|
18
|
+
* All children positioned at same location, aligned via alignItems
|
|
19
|
+
* @param child - Layout child
|
|
20
|
+
* @param _index - Child index (unused for stack layout)
|
|
21
|
+
* @param context - Layout context
|
|
22
|
+
* @param currentMain - Current position (unused for stack)
|
|
23
|
+
* @returns Position and unchanged currentMain
|
|
24
|
+
*/
|
|
25
|
+
positionChild(child: LayoutChild, _index: number, context: LayoutContext, currentMain: number): {
|
|
26
|
+
position: Position;
|
|
27
|
+
nextMain: number;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=stack-layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stack-layout.d.ts","sourceRoot":"","sources":["../../../src/layout/strategies/stack-layout.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAWpD;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,kBAAkB;IACzD;;;;;;OAMG;IACH,gBAAgB,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,QAAQ,EAAE,aAAa,GAAG,cAAc;IAiBlF;;;;;;;;OAQG;IACH,aAAa,CACX,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,aAAa,EACtB,WAAW,EAAE,MAAM,GAClB;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE;CA2D5C"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { isAnimatedSignal } from "../../animation/animated-signal.js";
|
|
2
|
+
import { BaseLayoutStrategy } from "./base-strategy.js";
|
|
3
|
+
function toLayoutNumber(value) {
|
|
4
|
+
if (value === void 0) return void 0;
|
|
5
|
+
return isAnimatedSignal(value) ? value.value : value;
|
|
6
|
+
}
|
|
7
|
+
class StackLayoutStrategy extends BaseLayoutStrategy {
|
|
8
|
+
/**
|
|
9
|
+
* Calculate content dimensions for stack layout
|
|
10
|
+
* For stack, we track max dimensions as children overlay
|
|
11
|
+
* @param children - Array of layout children
|
|
12
|
+
* @param context - Layout context
|
|
13
|
+
* @returns Content metrics
|
|
14
|
+
*/
|
|
15
|
+
calculateMetrics(children, _context) {
|
|
16
|
+
let maxWidth = 0;
|
|
17
|
+
let maxHeight = 0;
|
|
18
|
+
for (const child of children) {
|
|
19
|
+
const total = this.getTotalChildSize(child);
|
|
20
|
+
maxWidth = Math.max(maxWidth, total.width);
|
|
21
|
+
maxHeight = Math.max(maxHeight, total.height);
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
maxWidth,
|
|
25
|
+
maxHeight,
|
|
26
|
+
totalMainSize: 0
|
|
27
|
+
// Not applicable for stack
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Position a child in stack layout
|
|
32
|
+
* All children positioned at same location, aligned via alignItems
|
|
33
|
+
* @param child - Layout child
|
|
34
|
+
* @param _index - Child index (unused for stack layout)
|
|
35
|
+
* @param context - Layout context
|
|
36
|
+
* @param currentMain - Current position (unused for stack)
|
|
37
|
+
* @returns Position and unchanged currentMain
|
|
38
|
+
*/
|
|
39
|
+
positionChild(child, _index, context, currentMain) {
|
|
40
|
+
const margin = this.getMarginValues(child);
|
|
41
|
+
const { alignItems } = context.containerProps;
|
|
42
|
+
const isHeadless = child.child.__layoutProps?.headless;
|
|
43
|
+
let x;
|
|
44
|
+
let y;
|
|
45
|
+
if (isHeadless) {
|
|
46
|
+
return {
|
|
47
|
+
position: {
|
|
48
|
+
x: toLayoutNumber(child.child.__layoutProps?.x) ?? 0,
|
|
49
|
+
y: toLayoutNumber(child.child.__layoutProps?.y) ?? 0
|
|
50
|
+
},
|
|
51
|
+
nextMain: currentMain
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
switch (alignItems) {
|
|
55
|
+
case "start":
|
|
56
|
+
x = context.padding.left + margin.left;
|
|
57
|
+
y = context.padding.top + margin.top;
|
|
58
|
+
break;
|
|
59
|
+
case "center":
|
|
60
|
+
x = context.padding.left + (context.contentArea.width - child.size.width) / 2;
|
|
61
|
+
y = context.padding.top + (context.contentArea.height - child.size.height) / 2;
|
|
62
|
+
break;
|
|
63
|
+
case "end":
|
|
64
|
+
x = context.padding.left + context.contentArea.width - child.size.width - margin.right;
|
|
65
|
+
y = context.padding.top + context.contentArea.height - child.size.height - margin.bottom;
|
|
66
|
+
break;
|
|
67
|
+
case "stretch":
|
|
68
|
+
x = context.padding.left + margin.left;
|
|
69
|
+
y = context.padding.top + margin.top;
|
|
70
|
+
break;
|
|
71
|
+
default:
|
|
72
|
+
x = context.padding.left + margin.left;
|
|
73
|
+
y = context.padding.top + margin.top;
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
const childX = toLayoutNumber(child.child.__layoutProps?.x);
|
|
77
|
+
const childY = toLayoutNumber(child.child.__layoutProps?.y);
|
|
78
|
+
if (childX !== void 0) {
|
|
79
|
+
x += childX;
|
|
80
|
+
}
|
|
81
|
+
if (childY !== void 0) {
|
|
82
|
+
y += childY;
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
position: { x, y },
|
|
86
|
+
nextMain: currentMain
|
|
87
|
+
// Stack doesn't advance main axis
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
export {
|
|
92
|
+
StackLayoutStrategy
|
|
93
|
+
};
|
|
94
|
+
//# sourceMappingURL=stack-layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stack-layout.js","sources":["../../../src/layout/strategies/stack-layout.ts"],"sourcesContent":["/**\n * Stack layout strategy (overlay positioning)\n * Like SwiftUI's ZStack - all children positioned at same location\n */\nimport { isAnimatedSignal } from '../../animation/animated-signal'\nimport type { LayoutChild, LayoutContext, Position } from '../types'\nimport type { ContentMetrics } from '../utils/dimension-calculator'\nimport { BaseLayoutStrategy } from './base-strategy'\n\n/**\n * Unwrap a layout prop value — resolves AnimatedSignal to its .value,\n * passes through plain numbers, returns undefined for undefined.\n */\nfunction toLayoutNumber(value: unknown): number | undefined {\n if (value === undefined) return undefined\n return isAnimatedSignal(value) ? value.value : (value as number)\n}\n\n/**\n * Stack layout strategy - overlays all children at the same position\n */\nexport class StackLayoutStrategy extends BaseLayoutStrategy {\n /**\n * Calculate content dimensions for stack layout\n * For stack, we track max dimensions as children overlay\n * @param children - Array of layout children\n * @param context - Layout context\n * @returns Content metrics\n */\n calculateMetrics(children: LayoutChild[], _context: LayoutContext): ContentMetrics {\n let maxWidth = 0\n let maxHeight = 0\n\n for (const child of children) {\n const total = this.getTotalChildSize(child)\n maxWidth = Math.max(maxWidth, total.width)\n maxHeight = Math.max(maxHeight, total.height)\n }\n\n return {\n maxWidth,\n maxHeight,\n totalMainSize: 0, // Not applicable for stack\n }\n }\n\n /**\n * Position a child in stack layout\n * All children positioned at same location, aligned via alignItems\n * @param child - Layout child\n * @param _index - Child index (unused for stack layout)\n * @param context - Layout context\n * @param currentMain - Current position (unused for stack)\n * @returns Position and unchanged currentMain\n */\n positionChild(\n child: LayoutChild,\n _index: number,\n context: LayoutContext,\n currentMain: number\n ): { position: Position; nextMain: number } {\n const margin = this.getMarginValues(child)\n const { alignItems } = context.containerProps\n const isHeadless = child.child.__layoutProps?.headless\n\n let x: number\n let y: number\n\n if (isHeadless) {\n return {\n position: {\n x: toLayoutNumber(child.child.__layoutProps?.x) ?? 0,\n y: toLayoutNumber(child.child.__layoutProps?.y) ?? 0,\n },\n nextMain: currentMain,\n }\n }\n\n // Position based on alignItems (applies to both axes for stack)\n switch (alignItems) {\n case 'start':\n x = context.padding.left + margin.left\n y = context.padding.top + margin.top\n break\n case 'center':\n x = context.padding.left + (context.contentArea.width - child.size.width) / 2\n y = context.padding.top + (context.contentArea.height - child.size.height) / 2\n break\n case 'end':\n x = context.padding.left + context.contentArea.width - child.size.width - margin.right\n y = context.padding.top + context.contentArea.height - child.size.height - margin.bottom\n break\n case 'stretch':\n // TODO: Implement stretch - for now behave like start\n x = context.padding.left + margin.left\n y = context.padding.top + margin.top\n break\n default:\n x = context.padding.left + margin.left\n y = context.padding.top + margin.top\n break\n }\n\n // Apply explicit x/y offsets if provided\n const childX = toLayoutNumber(child.child.__layoutProps?.x)\n const childY = toLayoutNumber(child.child.__layoutProps?.y)\n\n if (childX !== undefined) {\n x += childX\n }\n if (childY !== undefined) {\n y += childY\n }\n\n return {\n position: { x, y },\n nextMain: currentMain, // Stack doesn't advance main axis\n }\n }\n}\n"],"names":[],"mappings":";;AAaA,SAAS,eAAe,OAAoC;AAC1D,MAAI,UAAU,OAAW,QAAO;AAChC,SAAO,iBAAiB,KAAK,IAAI,MAAM,QAAS;AAClD;AAKO,MAAM,4BAA4B,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ1D,iBAAiB,UAAyB,UAAyC;AACjF,QAAI,WAAW;AACf,QAAI,YAAY;AAEhB,eAAW,SAAS,UAAU;AAC5B,YAAM,QAAQ,KAAK,kBAAkB,KAAK;AAC1C,iBAAW,KAAK,IAAI,UAAU,MAAM,KAAK;AACzC,kBAAY,KAAK,IAAI,WAAW,MAAM,MAAM;AAAA,IAC9C;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,eAAe;AAAA;AAAA,IAAA;AAAA,EAEnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,cACE,OACA,QACA,SACA,aAC0C;AAC1C,UAAM,SAAS,KAAK,gBAAgB,KAAK;AACzC,UAAM,EAAE,eAAe,QAAQ;AAC/B,UAAM,aAAa,MAAM,MAAM,eAAe;AAE9C,QAAI;AACJ,QAAI;AAEJ,QAAI,YAAY;AACd,aAAO;AAAA,QACL,UAAU;AAAA,UACR,GAAG,eAAe,MAAM,MAAM,eAAe,CAAC,KAAK;AAAA,UACnD,GAAG,eAAe,MAAM,MAAM,eAAe,CAAC,KAAK;AAAA,QAAA;AAAA,QAErD,UAAU;AAAA,MAAA;AAAA,IAEd;AAGA,YAAQ,YAAA;AAAA,MACN,KAAK;AACH,YAAI,QAAQ,QAAQ,OAAO,OAAO;AAClC,YAAI,QAAQ,QAAQ,MAAM,OAAO;AACjC;AAAA,MACF,KAAK;AACH,YAAI,QAAQ,QAAQ,QAAQ,QAAQ,YAAY,QAAQ,MAAM,KAAK,SAAS;AAC5E,YAAI,QAAQ,QAAQ,OAAO,QAAQ,YAAY,SAAS,MAAM,KAAK,UAAU;AAC7E;AAAA,MACF,KAAK;AACH,YAAI,QAAQ,QAAQ,OAAO,QAAQ,YAAY,QAAQ,MAAM,KAAK,QAAQ,OAAO;AACjF,YAAI,QAAQ,QAAQ,MAAM,QAAQ,YAAY,SAAS,MAAM,KAAK,SAAS,OAAO;AAClF;AAAA,MACF,KAAK;AAEH,YAAI,QAAQ,QAAQ,OAAO,OAAO;AAClC,YAAI,QAAQ,QAAQ,MAAM,OAAO;AACjC;AAAA,MACF;AACE,YAAI,QAAQ,QAAQ,OAAO,OAAO;AAClC,YAAI,QAAQ,QAAQ,MAAM,OAAO;AACjC;AAAA,IAAA;AAIJ,UAAM,SAAS,eAAe,MAAM,MAAM,eAAe,CAAC;AAC1D,UAAM,SAAS,eAAe,MAAM,MAAM,eAAe,CAAC;AAE1D,QAAI,WAAW,QAAW;AACxB,WAAK;AAAA,IACP;AACA,QAAI,WAAW,QAAW;AACxB,WAAK;AAAA,IACP;AAEA,WAAO;AAAA,MACL,UAAU,EAAE,GAAG,EAAA;AAAA,MACf,UAAU;AAAA;AAAA,IAAA;AAAA,EAEd;AACF;"}
|