utils_dynamic_component_v-stack.js

import { v } from "../v-node";
import { useDebounce, useState } from "../render";

/**
 * @typedef vStackProps
 * @property {'vertical' | 'horizontal'} [direction=vertical]
 * 방향
 * @property {number} [gap=0]
 * 간격 픽셀
 */

/**
 * 나열형 컴포넌트
 *
 * 반드시 자식 컴포넌트는 id, top, left 값을 전달받아 사용하여야 합니다.
 *
 * @function vStack
 * @param {vStackProps} props  속성
 * @returns {VNode} 가상 노드
 * @deprecated $react를 사용하세요.
 * @memberof $v
 */
export function vStack(props) {
    const { direction = "vertical", gap = 0, children, ...others } = props;
    const [scrollPos, setScrollPos] = useState([0, 0]);
    const updateScrollPos = useDebounce((h, v) => {
        setScrollPos([h, v], { render: false });
    }, 300);

    // 원본 컴포넌트 위치 변경 방식
    return v("div", {
        onVScroll: (obj, e) => {
            if (e.type === "none" || e.type === "last") {
                return;
            }

            updateScrollPos(scrollPos[0], e.pos);
        },
        onHScroll: (obj, e) => {
            if (e.type === "none" || e.type === "last") {
                return;
            }

            updateScrollPos(e.pos, scrollPos[1]);
        },
        scrollX: scrollPos[0],
        scrollY: scrollPos[1],
        ...others,
        children: [
            ...children.map((c, i) => {
                switch (direction) {
                    case "horizontal":
                        c.props.id = `stack${i}`;
                        c.props.top ??= 0;
                        c.props.left = i > 0 ? `stack${i - 1}:${gap ?? 0}` : 0;
                        return c;
                    case "vertical":
                        c.props.id = `stack${i}`;
                        c.props.left ??= 0;
                        c.props.top = i > 0 ? `stack${i - 1}:${gap ?? 0}` : 0;
                        return c;
                }
            }),
        ],
    });
}