import { BlockActionType, BlockAvatarFacing, BlockAvatarSize, BlockBorderWidth, BlockButtonAppearance, BlockButtonSize, BlockGap, BlockHorizontalAlignment, BlockIconSize, BlockImageResizeMode, BlockPadding, BlockRadius, BlockSizeUnit, BlockSpacerShape, BlockSpacerSize, BlockStackDirection, BlockTextOutline, BlockTextOverflow, BlockTextSize, BlockTextWeight, BlockType, BlockVerticalAlignment, } from '@devvit/protos';
import { ButtonSize } from '@reddit/faceplate-ui/templates/button.js';
import { nothing } from 'lit';
import { brightnessByColor } from './templates/color.js';
import { getSizes, isHTMLElement, parseDimension, ref, resolveColors, sanitizeStyleInfo, } from './templates/util.js';
export function defaultClasses(block, ctx) {
    const type = block.type;
    return {
        'box-border': true,
        'overflow-hidden': type === BlockType.BLOCK_ROOT || type === BlockType.BLOCK_STACK,
        'm-0': type === BlockType.BLOCK_IMAGE,
        relative: true,
        ...stackChildClass(ctx.stackDirection),
        ...sizingClass(getSizes(block)),
        ...cursorClass(block),
    };
}
export function defaultStyles(block, ctx, reverse = false) {
    return sanitizeStyleInfo({
        ...sizingStyle(getSizes(block)),
        ...childGapStyle(ctx, reverse),
    });
}
export function stackDirectionClass(direction, reverse) {
    const vstack = direction === BlockStackDirection.STACK_VERTICAL;
    const hstack = direction === BlockStackDirection.STACK_HORIZONTAL;
    const zstack = direction === BlockStackDirection.STACK_DEPTH;
    return {
        flex: vstack || hstack,
        'flex-row': hstack,
        'flex-row-reverse': hstack && reverse === true,
        'flex-col': vstack,
        'flex-col-reverse': vstack && reverse === true,
        grid: zstack,
        'grid-cols-1': zstack,
        'dx-zstack': zstack,
        'auto-cols-fr': zstack,
        'auto-rows-fr': zstack,
    };
}
export function stackChildClass(parentDirection) {
    const zstack = parentDirection === BlockStackDirection.STACK_DEPTH;
    return {
        'col-start-1': zstack,
        'row-start-1': zstack,
    };
}
export function sizingClass(sizing) {
    return {
        'shrink-0': sizing?.grow !== true,
        'col-start-1': sizing?.grow === true,
        'row-start-1': sizing?.grow === true,
        shrink: sizing?.grow === true,
        grow: sizing?.grow === true,
    };
}
export function sizingStyle(sizing) {
    return sanitizeStyleInfo({
        width: sizing?.grow === true ? undefined : parseDimension(sizing?.width?.value),
        minWidth: sizing?.grow === true ? undefined : parseDimension(sizing?.width?.min),
        maxWidth: sizing?.grow === true ? undefined : parseDimension(sizing?.width?.max),
        height: sizing?.grow === true ? undefined : parseDimension(sizing?.height?.value),
        minHeight: sizing?.grow === true ? undefined : parseDimension(sizing?.height?.min),
        maxHeight: sizing?.grow === true ? undefined : parseDimension(sizing?.height?.max),
    });
}
export function growWrapperSizingStyle(block) {
    const sizes = getSizes(block);
    return sanitizeStyleInfo({
        width: parseDimension(sizes?.width?.value),
        minWidth: parseDimension(sizes?.width?.min),
        maxWidth: parseDimension(sizes?.width?.max),
        height: parseDimension(sizes?.height?.value),
        minHeight: parseDimension(sizes?.height?.min),
        maxHeight: parseDimension(sizes?.height?.max),
    });
}
export function paddingClass(padding) {
    return {
        'p-0': padding === undefined || padding === BlockPadding.PADDING_NONE,
        'p-2xs': padding === BlockPadding.PADDING_XSMALL,
        'p-xs': padding === BlockPadding.PADDING_SMALL,
        'p-md': padding === BlockPadding.PADDING_MEDIUM,
        'p-xl': padding === BlockPadding.PADDING_LARGE,
    };
}
export function alignmentClass(direction, align, block) {
    const hstack = direction === BlockStackDirection.STACK_HORIZONTAL;
    const vstack = direction === BlockStackDirection.STACK_VERTICAL;
    const zstack = direction === BlockStackDirection.STACK_DEPTH;
    const hnone = align === undefined || align.horizontal === undefined;
    const start = align?.horizontal === BlockHorizontalAlignment.ALIGN_START;
    const center = align?.horizontal === BlockHorizontalAlignment.ALIGN_CENTER;
    const end = align?.horizontal === BlockHorizontalAlignment.ALIGN_END;
    const vnone = align === undefined || align.vertical === undefined;
    const top = align?.vertical === BlockVerticalAlignment.ALIGN_TOP;
    const middle = align?.vertical === BlockVerticalAlignment.ALIGN_MIDDLE;
    const bottom = align?.vertical === BlockVerticalAlignment.ALIGN_BOTTOM;
    const sizes = getSizes(block);
    return {
        // Primary axis alignment
        'justify-start': (start && hstack) || (top && vstack),
        'justify-center': (center && hstack) || (middle && vstack),
        'justify-end': (end && hstack) || (bottom && vstack),
        // Alternate for ZStack
        'justify-items-start': (hnone && zstack) || (start && zstack),
        'justify-items-center': center && zstack,
        'justify-items-end': end && zstack,
        // Cross-axis alignment
        'items-start': (top && (hstack || zstack)) || (start && vstack) || (vnone && zstack),
        'items-center': (middle && (hstack || zstack)) || (center && vstack),
        'items-stretch': (vnone && hstack) || (hnone && vstack),
        'items-end': (bottom && (hstack || zstack)) || (end && vstack),
        // CSS grid alignment for ZStack
        ...(zstack && sizes && { ...zstackAlignmentClass(align, sizes) }),
    };
}
/* ZStacks use CSS grid and require extra alignment classes over hstack and vstacks */
export function zstackAlignmentClass(align, sizes) {
    // ZStacks with grow set to true should always stretch content
    if (sizes.grow) {
        return {
            'content-stretch': true,
        };
    }
    return {
        'content-start': align?.vertical === BlockVerticalAlignment.ALIGN_TOP,
        'content-center': align?.vertical === BlockVerticalAlignment.ALIGN_MIDDLE,
        'content-end': align?.vertical === BlockVerticalAlignment.ALIGN_BOTTOM,
    };
}
export function backgroundClass(hasBgColor) {
    return {
        'dx-bg-color': hasBgColor,
    };
}
export function backgroundStyle(colors, legacyColor) {
    const [light, dark] = resolveColors(colors, legacyColor);
    return sanitizeStyleInfo({
        '--dx-bg-color-light': light,
        '--dx-bg-color-dark': dark,
    });
}
export function borderClass(border) {
    const thin = border?.width === BlockBorderWidth.BORDER_WIDTH_THIN;
    const thick = border?.width === BlockBorderWidth.BORDER_WIDTH_THICK;
    const none = !thin && !thick;
    const hasBorder = border !== undefined && !none;
    const hasColor = (border?.colors?.dark ?? border?.colors?.light ?? border?.color) !== undefined;
    return {
        'border-0': !hasBorder,
        'border-solid': hasBorder,
        'border-dx-thin': thin,
        'border-dx-thick': thick,
        'border-neutral-border': hasBorder && !hasColor,
        'dx-border-color': hasBorder,
    };
}
export function borderStyle(border) {
    const [light, dark] = resolveColors(border?.colors, border?.color);
    return sanitizeStyleInfo({
        '--dx-border-color-light': light,
        '--dx-border-color-dark': dark,
    });
}
export function radiusClass(radius) {
    return {
        'rounded-none': radius === undefined || radius === BlockRadius.RADIUS_NONE,
        'rounded-dx-sm': radius === BlockRadius.RADIUS_SMALL,
        'rounded-dx-md': radius === BlockRadius.RADIUS_MEDIUM,
        'rounded-dx-lg': radius === BlockRadius.RADIUS_LARGE,
        'rounded-full': radius === BlockRadius.RADIUS_FULL,
    };
}
export function textSizeClass(size) {
    return {
        'text-10': size === BlockTextSize.TEXT_SIZE_XSMALL,
        'text-12': size === BlockTextSize.TEXT_SIZE_SMALL,
        'text-14': size === BlockTextSize.TEXT_SIZE_MEDIUM || size === undefined,
        'text-16': size === BlockTextSize.TEXT_SIZE_LARGE,
        'text-18': size === BlockTextSize.TEXT_SIZE_XLARGE,
        'text-24': size === BlockTextSize.TEXT_SIZE_XXLARGE,
    };
}
export function textAlignClass(alignment) {
    return {
        'text-start': alignment === undefined ||
            alignment.horizontal === undefined ||
            alignment.horizontal === BlockHorizontalAlignment.ALIGN_START,
        'text-center': alignment?.horizontal === BlockHorizontalAlignment.ALIGN_CENTER,
        'text-end': alignment?.horizontal === BlockHorizontalAlignment.ALIGN_END,
    };
}
export function textWeightClass(weight) {
    return {
        'font-normal': weight === BlockTextWeight.TEXT_WEIGHT_REGULAR,
        'font-semibold': weight === BlockTextWeight.TEXT_WEIGHT_BOLD,
    };
}
export function textSelectClass(selection) {
    return {
        'select-none': selection === false,
        'select-text': selection === true,
        'select-auto': selection === undefined,
    };
}
export function textColorClass() {
    return {
        'dx-text-color': true,
    };
}
export function textColorStyle(colors, legacyColor) {
    const [light, dark] = resolveColors(colors, legacyColor);
    return sanitizeStyleInfo({
        '--dx-text-color-light': light,
        '--dx-text-color-dark': dark,
    });
}
export function spacerSizeClass(size, shape, stackDirection) {
    const zstack = stackDirection === BlockStackDirection.STACK_DEPTH;
    if (zstack) {
        return {};
    }
    const square = shape === BlockSpacerShape.SPACER_SQUARE;
    const thin = shape === BlockSpacerShape.SPACER_THIN;
    const xsmall = size === BlockSpacerSize.SPACER_XSMALL;
    const small = size === undefined || size === BlockSpacerSize.SPACER_SMALL;
    const medium = size === BlockSpacerSize.SPACER_MEDIUM;
    const large = size === BlockSpacerSize.SPACER_LARGE;
    const vstack = stackDirection === BlockStackDirection.STACK_VERTICAL;
    const hstack = stackDirection === BlockStackDirection.STACK_HORIZONTAL;
    return {
        'w-2xs': xsmall && (hstack || square),
        'w-xs': small && (hstack || square),
        'w-md': medium && (hstack || square),
        'w-xl': large && (hstack || square),
        'h-2xs': xsmall && (vstack || square),
        'h-xs': small && (vstack || square),
        'h-md': medium && (vstack || square),
        'h-xl': large && (vstack || square),
        'w-px': vstack && thin,
        'h-px': hstack && thin,
    };
}
export function iconSizeClass(size) {
    const xsmall = size === BlockIconSize.ICON_SIZE_XSMALL;
    const small = size === BlockIconSize.ICON_SIZE_SMALL;
    const medium = size === BlockIconSize.ICON_SIZE_MEDIUM || size === undefined;
    const large = size === BlockIconSize.ICON_SIZE_LARGE;
    return {
        '[&>svg]:block': true,
        '[&>svg]:aspect-square': true,
        '[&>svg]:align-middle': true,
        '[&>svg]:text-center': true,
        '[&>svg]:w-sm': xsmall,
        '[&>svg]:h-sm': xsmall,
        '[&>svg]:w-md': small,
        '[&>svg]:h-md': small,
        '[&>svg]:w-[1.25rem]': medium,
        '[&>svg]:h-[1.25rem]': medium,
        '[&>svg]:w-lg': large,
        '[&>svg]:h-lg': large,
    };
}
export function avatarSizeClass(size) {
    return {
        'aspect-square': true,
        'w-md': size === BlockAvatarSize.AVATAR_SIZE_XXSMALL,
        'w-lg': size === BlockAvatarSize.AVATAR_SIZE_XSMALL,
        'w-xl': size === undefined || size === BlockAvatarSize.AVATAR_SIZE_SMALL,
        'w-[2.5rem]': size === BlockAvatarSize.AVATAR_SIZE_MEDIUM,
        'w-2xl': size === BlockAvatarSize.AVATAR_SIZE_LARGE,
        'w-[3.5rem]': size === BlockAvatarSize.AVATAR_SIZE_XLARGE,
        'w-3xl': size === BlockAvatarSize.AVATAR_SIZE_XXLARGE,
        'w-[5.5rem]': size === BlockAvatarSize.AVATAR_SIZE_XXXLARGE,
    };
}
export function facingClass(facing) {
    return {
        'scale-x-100': facing === undefined || facing === BlockAvatarFacing.AVATAR_FACING_RIGHT,
        '-scale-x-100': facing === BlockAvatarFacing.AVATAR_FACING_LEFT,
    };
}
export function buttonAppearance(appearance) {
    let buttonAppearance;
    switch (appearance) {
        case BlockButtonAppearance.BUTTON_APPEARANCE_PRIMARY:
            buttonAppearance = 'primary';
            break;
        case BlockButtonAppearance.BUTTON_APPEARANCE_PLAIN:
            buttonAppearance = 'plain';
            break;
        case BlockButtonAppearance.BUTTON_APPEARANCE_BORDERED:
            buttonAppearance = 'bordered';
            break;
        case BlockButtonAppearance.BUTTON_APPEARANCE_MEDIA:
            buttonAppearance = 'media';
            break;
        case BlockButtonAppearance.BUTTON_APPEARANCE_SUCCESS:
            buttonAppearance = 'success';
            break;
        case BlockButtonAppearance.BUTTON_APPEARANCE_DESTRUCTIVE:
            buttonAppearance = 'destructive';
            break;
        case BlockButtonAppearance.BUTTON_APPEARANCE_SECONDARY:
        default:
            buttonAppearance = 'secondary';
            break;
    }
    return buttonAppearance;
}
export function buttonSize(size) {
    let buttonSize;
    switch (size) {
        case BlockButtonSize.BUTTON_SIZE_SMALL:
            buttonSize = ButtonSize.Small;
            break;
        case BlockButtonSize.BUTTON_SIZE_LARGE:
            buttonSize = ButtonSize.Large;
            break;
        case BlockButtonSize.BUTTON_SIZE_MEDIUM:
        default:
            buttonSize = ButtonSize.Medium;
            break;
    }
    return buttonSize;
}
export function cursorClass(block) {
    return {
        'cursor-pointer': !!block.actions.find((a) => a.type === BlockActionType.ACTION_CLICK),
    };
}
export function pointerEventsClass(actionable) {
    return {
        'pointer-events-none': !actionable,
        '[&>:not(.pointer-events-none)]:pointer-events-auto': !actionable,
        'pointer-events-auto': actionable,
    };
}
export function onClickAction(block, ctx) {
    const clickAction = block.actions.find((a) => a.type === BlockActionType.ACTION_CLICK);
    if (clickAction) {
        return () => {
            ctx.onAction?.(clickAction);
        };
    }
}
export function onWebViewAction(block, ctx) {
    const webviewAction = block.actions.find((a) => a.type === BlockActionType.ACTION_WEBVIEW);
    if (webviewAction) {
        return (ev) => {
            ctx.onAction?.({ ...webviewAction, data: ev.detail });
        };
    }
}
export function setTextOutline(thickness) {
    let thicknessClass;
    switch (thickness) {
        case BlockTextOutline.TEXT_OUTLINE_THIN:
            thicknessClass = 'thin';
            break;
        case BlockTextOutline.TEXT_OUTLINE_THICK:
            thicknessClass = 'thick';
            break;
        default:
            return nothing;
    }
    return ref((el) => {
        if (isHTMLElement(el)) {
            let retry = true;
            const apply = () => {
                const color = window.getComputedStyle(el).color;
                if (!color && retry) {
                    retry = false;
                    window.setTimeout(() => apply(), 0);
                    return;
                }
                const brightness = brightnessByColor(color) > 127 ? 'bright' : 'dark';
                el.classList.forEach((name) => {
                    if (name.startsWith('text-outline-')) {
                        el.classList.remove(name);
                    }
                });
                el.classList.add(`text-outline-${thicknessClass}-${brightness}`);
            };
            apply();
        }
    });
}
export function textOverflowClass(config) {
    const wrap = config.wrap === true;
    const overflow = config.overflow;
    return {
        'overflow-hidden': true,
        'text-clip': overflow === BlockTextOverflow.TEXT_OVERFLOW_CLIP,
        'text-ellipsis': overflow === BlockTextOverflow.TEXT_OVERFLOW_ELLIPSE || overflow === undefined,
        'whitespace-pre-line': wrap,
        'whitespace-nowrap': !wrap,
    };
}
/**
 * Converts the BlockGap enum values to pixels
 */
export function gapSize(gap) {
    switch (gap) {
        case BlockGap.GAP_SMALL:
            return 8;
        case BlockGap.GAP_MEDIUM:
            return 16;
        case BlockGap.GAP_LARGE:
            return 32;
    }
    return 0;
}
/**
 * Applies the necessary styles for a stack to appropriately
 * measure available space for relatively sized child blocks
 */
export function stackGapStyle(stackDirection, gap, padding, childCount, reverse) {
    if (!gap)
        return {};
    let paddingOffsetPx = 0;
    let paddingDirection;
    switch (padding) {
        case BlockPadding.PADDING_XSMALL:
            paddingOffsetPx = 4;
            break;
        case BlockPadding.PADDING_SMALL:
            paddingOffsetPx = 8;
            break;
        case BlockPadding.PADDING_MEDIUM:
            paddingOffsetPx = 16;
            break;
        case BlockPadding.PADDING_LARGE:
            paddingOffsetPx = 32;
            break;
    }
    switch (stackDirection) {
        case BlockStackDirection.STACK_HORIZONTAL:
            paddingDirection = reverse ? 'left' : 'right';
            break;
        case BlockStackDirection.STACK_VERTICAL:
            paddingDirection = reverse ? 'top' : 'bottom';
            break;
    }
    const gapOffsetPx = gapSize(gap) * (childCount - 1) + paddingOffsetPx;
    return sanitizeStyleInfo(paddingDirection && gapOffsetPx
        ? {
            [`padding-${paddingDirection}`]: `${gapOffsetPx}px`,
        }
        : {});
}
/**
 * Applies a relative offset in order to properly space a
 * child block within a stack that has gap.
 * If reverse, the offset is applied in the opposite direction.
 */
export function childGapStyle(ctx, reverse) {
    const offset = (ctx.gapSize ?? 0) * (ctx.childIndex ?? 0);
    let offsetDirection;
    switch (ctx.stackDirection) {
        case BlockStackDirection.STACK_HORIZONTAL:
            offsetDirection = reverse ? 'right' : 'left';
            break;
        case BlockStackDirection.STACK_VERTICAL:
            offsetDirection = reverse ? 'bottom' : 'top';
            break;
    }
    return sanitizeStyleInfo(offsetDirection && offset
        ? {
            [offsetDirection]: `${offset}px`,
        }
        : {});
}
export function imageClasses(resizeMode) {
    return {
        'bg-center': true,
        'bg-no-repeat': true,
        'bg-cover': resizeMode === BlockImageResizeMode.IMAGE_RESIZE_COVER,
        'bg-contain': resizeMode === undefined || resizeMode === BlockImageResizeMode.IMAGE_RESIZE_FIT,
    };
}
export function imageStyle(url, resizeMode, imageWidth, imageHeight, canvasSize) {
    const size = {};
    switch (resizeMode) {
        case BlockImageResizeMode.IMAGE_RESIZE_FILL:
            size['backgroundSize'] = `100% 100%`;
            break;
        case BlockImageResizeMode.IMAGE_RESIZE_SCALE_DOWN: {
            if (canvasSize?.height?.value?.unit === BlockSizeUnit.SIZE_UNIT_PERCENT ||
                canvasSize?.width?.value?.unit === BlockSizeUnit.SIZE_UNIT_PERCENT) {
                size['backgroundSize'] = 'contain';
                break;
            }
            const calculationHeight = canvasSize?.height?.value?.unit === BlockSizeUnit.SIZE_UNIT_PIXELS
                ? Math.min(canvasSize.height.value.value, imageHeight)
                : imageHeight;
            const calculationWidth = canvasSize?.width?.value?.unit === BlockSizeUnit.SIZE_UNIT_PIXELS
                ? Math.min(canvasSize.width.value.value, imageWidth)
                : imageWidth;
            if (calculationWidth > calculationHeight) {
                size['backgroundSize'] = `auto clamp(0px, 100%, ${calculationWidth}px)`;
            }
            else {
                size['backgroundSize'] = `clamp(0px, 100%, ${calculationHeight}px) auto`;
            }
            break;
        }
        case BlockImageResizeMode.IMAGE_RESIZE_NONE:
            size['backgroundSize'] = `${imageWidth}px ${imageHeight}px`;
    }
    return {
        backgroundImage: `url('${url}')`,
        width: canvasSize?.grow ? '100%' : canvasSize?.width ? undefined : `${imageWidth}px`,
        height: canvasSize?.grow ? '100%' : canvasSize?.height ? undefined : `${imageHeight}px`,
        ...size,
    };
}
//# sourceMappingURL=attributes.js.map