import { React } from "@lattice-ui/core"; import { mergeGuiProps, resolveSx, useTheme } from "@lattice-ui/style"; import { resolvePadding, resolveSpace } from "./space"; import type { LayoutDirection, StackAlign, StackAutoSize, StackJustify, StackProps } from "./types"; type StyleProps = React.Attributes & Record; function toHorizontalAlignment(value: StackAlign | StackJustify) { switch (value) { case "center": return Enum.HorizontalAlignment.Center; case "end": return Enum.HorizontalAlignment.Right; default: return Enum.HorizontalAlignment.Left; } } function toVerticalAlignment(value: StackAlign | StackJustify) { switch (value) { case "center": return Enum.VerticalAlignment.Center; case "end": return Enum.VerticalAlignment.Bottom; default: return Enum.VerticalAlignment.Top; } } function toAutomaticSize(autoSize: StackAutoSize | undefined, direction: LayoutDirection) { if (autoSize === undefined || autoSize === false) { return Enum.AutomaticSize.None; } if (autoSize === true) { return direction === "vertical" ? Enum.AutomaticSize.Y : Enum.AutomaticSize.X; } switch (autoSize) { case "x": return Enum.AutomaticSize.X; case "y": return Enum.AutomaticSize.Y; case "xy": return Enum.AutomaticSize.XY; default: return Enum.AutomaticSize.None; } } export function Stack(props: StackProps) { const direction = props.direction ?? "vertical"; const gap = props.gap ?? 0; const align = props.align ?? "start"; const justify = props.justify ?? "start"; const autoSize = props.autoSize; const sx = props.sx; const children = props.children; const asChild = (props as { asChild?: unknown }).asChild; if (asChild !== undefined) { error("[Stack] `asChild` is not supported in M3."); } const restProps: StyleProps = {}; for (const [rawKey, value] of pairs(props as Record)) { if (!typeIs(rawKey, "string")) { continue; } if ( rawKey === "direction" || rawKey === "gap" || rawKey === "align" || rawKey === "justify" || rawKey === "autoSize" || rawKey === "sx" || rawKey === "asChild" || rawKey === "padding" || rawKey === "paddingX" || rawKey === "paddingY" || rawKey === "paddingTop" || rawKey === "paddingRight" || rawKey === "paddingBottom" || rawKey === "paddingLeft" || rawKey === "children" ) { continue; } restProps[rawKey] = value; } const { theme } = useTheme(); const sxProps = resolveSx(sx, theme); const baseProps: Partial = { BackgroundTransparency: 1, BorderSizePixel: 0, AutomaticSize: toAutomaticSize(autoSize, direction), }; const mergedProps = mergeGuiProps(baseProps, sxProps, restProps); const resolvedGap = resolveSpace(theme, gap); const padding = resolvePadding(theme, props); const hasPadding = padding.top > 0 || padding.right > 0 || padding.bottom > 0 || padding.left > 0; const vertical = direction === "vertical"; const horizontalAlignment = vertical ? toHorizontalAlignment(align) : toHorizontalAlignment(justify); const verticalAlignment = vertical ? toVerticalAlignment(justify) : toVerticalAlignment(align); return ( )}> {hasPadding ? ( ) : undefined} {children} ); }