import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { providerDistinguishesSharedComponents } from "../services/contentService";
import { useEffect, useLayoutEffect, useRef, useState } from "react";
import { useCanvasSelection, useEditContext } from "../client/editContext";
import { cn } from "../../lib/utils";
import { FRAME_CHROME_Z_INDEX, PlaceholderDropZone, } from "./PlaceholderDropZone";
import { buildComponentContextMenuItems } from "../ContextMenu";
import { getComponentById } from "../componentTreeHelper";
import { loadFieldButtons } from "../services/editService";
import { normalizeMarkerId } from "../utils";
import { Tooltip, TooltipContent, TooltipTrigger, } from "../../components/ui/tooltip";
import { componentFrameBgColorVariants, componentFrameBgHoverColorVariants, componentFrameBorderColorVariants, } from "../componentFrameColors";
import { GripVertical, ArrowUpFromDot, Sparkles } from "lucide-react";
import { useComponentDragHandle } from "./useComponentDragHandle";
import { FRAME_OUTSET, measureBridgeComponentRect, rectEquals, } from "./overlay/geometry";
import { useOverlayMeasurement } from "./overlay/useOverlayMeasurement";
const HEADER_RIGHT_OVERFLOW = 1.5;
const FRAME_FLIP_EASING = "cubic-bezier(0.2, 0, 0, 1)";
const FRAME_FLIP_TRANSITION = `transform 220ms ${FRAME_FLIP_EASING}`;
const FRAME_BOX_FLIP_TRANSITION = `left 220ms ${FRAME_FLIP_EASING}, ` +
    `top 220ms ${FRAME_FLIP_EASING}, ` +
    `width 220ms ${FRAME_FLIP_EASING}, ` +
    `height 220ms ${FRAME_FLIP_EASING}`;
const FRAME_FLIP_CLEANUP_MS = 260;
// The header hugs the frame's padding box (its offsets resolved against the
// bordered frame element before it moved into the borderless full-frame
// animation wrapper), so the frame border widths shift it inward.
function getFrameMenuHeaderOffsets(rectY, geometry) {
    const isInsideFrame = geometry.isMultiSelected || rectY < geometry.headerHeight;
    return {
        isInsideFrame,
        right: geometry.frameBorderWidth - HEADER_RIGHT_OVERFLOW,
        top: isInsideFrame
            ? geometry.frameTopBorderWidth
            : geometry.frameTopBorderWidth - geometry.headerHeight,
    };
}
// Absolute overlay-space anchor (right/top edge) of the header, for FLIP deltas.
function getFrameMenuHeaderAnchor(rect, geometry) {
    const offsets = getFrameMenuHeaderOffsets(rect.y, geometry);
    return {
        right: rect.x + rect.width + FRAME_OUTSET - offsets.right,
        top: rect.y - FRAME_OUTSET + offsets.top,
    };
}
function componentOverlayMeasurementEquals(previous, next) {
    if (previous.componentKey !== next.componentKey)
        return false;
    if (!rectEquals(previous.rect, next.rect))
        return false;
    if (previous.elements.length !== next.elements.length)
        return false;
    return previous.elements.every((element, index) => element === next.elements[index]);
}
function bridgeIdsMatch(left, right) {
    const normalizedLeft = normalizeMarkerId(left);
    const normalizedRight = normalizeMarkerId(right);
    return (!!normalizedLeft && !!normalizedRight && normalizedLeft === normalizedRight);
}
function fieldMatchesBridgeId(field, fieldId) {
    return (bridgeIdsMatch(field.id, fieldId) ||
        bridgeIdsMatch(field.name, fieldId) ||
        bridgeIdsMatch(field.displayName, fieldId));
}
export function FrameMenu(props) {
    const editContext = useEditContext();
    if (!props.component || !editContext)
        return null;
    return _jsx(FrameMenuContent, { ...props, editContext: editContext });
}
function FrameMenuContent({ component, isSelected = true, compareView, pageViewContext, editContext, openInsertMenuKey, onInsertMenuOpenChange, }) {
    const canvasSelection = useCanvasSelection();
    const frameRef = useRef(null);
    const headerAnimationRef = useRef(null);
    const headerRef = useRef(null);
    const previousFrameRef = useRef(null);
    const frameAnimationFrameRef = useRef(null);
    const frameAnimationTimeoutRef = useRef(null);
    const isHoverFrame = !isSelected;
    const [commands, setCommands] = useState([]);
    const [commandComponentKey, setCommandComponentKey] = useState(null);
    const [isHeaderWiderThanComponent, setIsHeaderWiderThanComponent] = useState(false);
    const componentFrameKey = normalizeMarkerId(component.id) || component.id;
    const isMultiSelected = isSelected && canvasSelection.length > 1;
    const headerHeight = isHoverFrame ? 20 : 36;
    // Mirrors the border/border-2/border-t-0 classes on the frame element.
    const frameBorderWidth = isHoverFrame ? 1 : 2;
    const frameTopBorderWidth = !isHoverFrame && !isMultiSelected && isHeaderWiderThanComponent
        ? 0
        : frameBorderWidth;
    const componentMeasurement = useOverlayMeasurement((metrics) => {
        const bridgeResult = measureBridgeComponentRect(pageViewContext.bridgeGeometry, component, metrics);
        if (bridgeResult?.rect) {
            return { ...bridgeResult, componentKey: componentFrameKey };
        }
        return { componentKey: componentFrameKey, rect: null, elements: [] };
    }, [component, componentFrameKey, pageViewContext.bridgeGeometry], {
        initialValue: { componentKey: null, rect: null, elements: [] },
        equals: componentOverlayMeasurementEquals,
        interests: ["viewport", "layout", "adornment-data"],
        validateBeforePaint: true,
    });
    const isCurrentComponentMeasurement = componentMeasurement.componentKey === componentFrameKey;
    const componentRect = componentMeasurement.rect ?? undefined;
    useLayoutEffect(() => {
        if (!componentRect || !isCurrentComponentMeasurement)
            return;
        // Snapshot the anchor alongside the rect so a later animation starts from
        // where the header actually was, even if isMultiSelected etc. changed
        // between this commit and the animating one.
        const currentHeaderAnchor = getFrameMenuHeaderAnchor(componentRect, {
            headerHeight,
            isMultiSelected,
            frameBorderWidth,
            frameTopBorderWidth,
        });
        const previous = previousFrameRef.current;
        previousFrameRef.current = {
            componentKey: componentFrameKey,
            rect: componentRect,
            headerAnchor: currentHeaderAnchor,
        };
        const frameElement = frameRef.current;
        if (!frameElement ||
            isHoverFrame ||
            !previous ||
            previous.componentKey === componentFrameKey ||
            window.matchMedia?.("(prefers-reduced-motion: reduce)").matches) {
            return;
        }
        const deltaX = previous.rect.x - componentRect.x;
        const deltaY = previous.rect.y - componentRect.y;
        const headerDeltaX = previous.headerAnchor.right - currentHeaderAnchor.right;
        const headerDeltaY = previous.headerAnchor.top - currentHeaderAnchor.top;
        const previousFrameWidth = previous.rect.width + FRAME_OUTSET * 2;
        const previousFrameHeight = previous.rect.height + FRAME_OUTSET * 2;
        const currentFrameWidth = componentRect.width + FRAME_OUTSET * 2;
        const currentFrameHeight = componentRect.height + FRAME_OUTSET * 2;
        const widthDelta = previousFrameWidth - currentFrameWidth;
        const heightDelta = previousFrameHeight - currentFrameHeight;
        const shouldAnimate = Math.hypot(deltaX, deltaY) > 1 ||
            Math.abs(widthDelta) > 1 ||
            Math.abs(heightDelta) > 1;
        if (!shouldAnimate)
            return;
        const headerAnimationElement = headerAnimationRef.current;
        if (frameAnimationFrameRef.current !== null) {
            window.cancelAnimationFrame(frameAnimationFrameRef.current);
            frameAnimationFrameRef.current = null;
        }
        if (frameAnimationTimeoutRef.current !== null) {
            window.clearTimeout(frameAnimationTimeoutRef.current);
            frameAnimationTimeoutRef.current = null;
        }
        const animatedElements = [];
        if (headerAnimationElement) {
            if (Math.hypot(headerDeltaX, headerDeltaY) > 1) {
                animatedElements.push({
                    element: headerAnimationElement,
                    from: `translate(${headerDeltaX}px, ${headerDeltaY}px)`,
                    to: "translate(0px, 0px)",
                });
            }
            else {
                // Not animating the header this time; drop styles a cancelled run
                // may have left behind.
                headerAnimationElement.style.transition = "";
                headerAnimationElement.style.transform = "";
                headerAnimationElement.style.willChange = "";
            }
        }
        frameElement.style.transition = "none";
        frameElement.style.left = `${deltaX}px`;
        frameElement.style.top = `${deltaY}px`;
        frameElement.style.width = `${previousFrameWidth}px`;
        frameElement.style.height = `${previousFrameHeight}px`;
        frameElement.style.willChange = "left, top, width, height";
        for (const { element, from } of animatedElements) {
            element.style.transition = "none";
            element.style.transform = from;
            element.style.willChange = "transform";
        }
        // Flush the "from" styles so the transition below has a starting keyframe
        // even when nothing else forces a style recalc before the rAF fires.
        void frameElement.offsetWidth;
        frameAnimationFrameRef.current = window.requestAnimationFrame(() => {
            frameAnimationFrameRef.current = null;
            frameElement.style.transition = FRAME_BOX_FLIP_TRANSITION;
            frameElement.style.left = "0px";
            frameElement.style.top = "0px";
            frameElement.style.width = `${currentFrameWidth}px`;
            frameElement.style.height = `${currentFrameHeight}px`;
            for (const { element, to } of animatedElements) {
                element.style.transition = FRAME_FLIP_TRANSITION;
                element.style.transform = to;
            }
            frameAnimationTimeoutRef.current = window.setTimeout(() => {
                frameElement.style.transition = "";
                frameElement.style.left = "";
                frameElement.style.top = "";
                frameElement.style.width = "";
                frameElement.style.height = "";
                frameElement.style.willChange = "";
                for (const { element } of animatedElements) {
                    element.style.transition = "";
                    element.style.transform = "";
                    element.style.willChange = "";
                }
                frameAnimationTimeoutRef.current = null;
            }, FRAME_FLIP_CLEANUP_MS);
        });
    }, [
        componentFrameKey,
        componentRect,
        frameBorderWidth,
        frameTopBorderWidth,
        headerHeight,
        isCurrentComponentMeasurement,
        isHoverFrame,
        isMultiSelected,
    ]);
    useEffect(() => {
        return () => {
            if (frameAnimationFrameRef.current !== null) {
                window.cancelAnimationFrame(frameAnimationFrameRef.current);
            }
            if (frameAnimationTimeoutRef.current !== null) {
                window.clearTimeout(frameAnimationTimeoutRef.current);
            }
        };
    }, []);
    // Effect to measure header width and compare with componentRect
    useEffect(() => {
        if (!headerRef.current || !componentRect)
            return;
        const headerResizeObserver = new ResizeObserver((entries) => {
            for (const entry of entries) {
                const headerWidth = entry.contentRect.width;
                setIsHeaderWiderThanComponent(headerWidth > componentRect.width);
            }
        });
        headerResizeObserver.observe(headerRef.current);
        return () => {
            headerResizeObserver.disconnect();
        };
    }, [componentRect]);
    // const commands = editContext.getComponentCommands([component]);
    useEffect(() => {
        let cancelled = false;
        if (!isSelected) {
            return () => {
                cancelled = true;
            };
        }
        // Load commands asynchronously - don't block rendering
        async function loadCommands() {
            const commands = await editContext.getComponentCommands([component]);
            if (!cancelled) {
                setCommands(commands);
                setCommandComponentKey(componentFrameKey);
            }
        }
        // Use requestIdleCallback or setTimeout to defer command loading, allowing frame to render first
        if (typeof requestIdleCallback !== "undefined") {
            requestIdleCallback(() => {
                loadCommands();
            }, { timeout: 0 });
        }
        else {
            // Fallback for browsers without requestIdleCallback
            setTimeout(() => {
                loadCommands();
            }, 0);
        }
        return () => {
            cancelled = true;
        };
    }, [component, componentFrameKey, isSelected]);
    // Determine if draggable - layout components should not be draggable when showLayoutComponents is disabled
    const isLayoutReadonlyCheck = component.layoutId && !editContext.showLayoutComponents;
    const isDraggable = component.canBeMoved && !isLayoutReadonlyCheck;
    // Whole-component pointer drag (replaces native HTML5 DnD): forwards a
    // client-space gesture stream to the shared DragInsertionOverlay orchestration.
    const { onPointerDown: onGripPointerDown } = useComponentDragHandle({
        component,
        pageViewContext,
        enabled: isSelected && isDraggable,
    });
    const visibleCommands = commandComponentKey === componentFrameKey ? commands : [];
    const commandButtons = visibleCommands
        .filter((x) => !editContext.isCommandDisabled({ command: x }) &&
        x.visibilityScopes.indexOf("editFrame") >= 0)
        .map((x) => ({
        id: x.id + "_button",
        icon: x.icon,
        label: x.label,
        onClick: (ev) => {
            ev.stopPropagation();
            ev.preventDefault();
            editContext.executeCommand({
                command: x,
                event: ev,
            });
        },
    }));
    const customButtons = []; // TODO
    const buttons = isSelected ? [...customButtons, ...commandButtons] : [];
    const hasFrameButtons = buttons.length > 0;
    const frameButtonsMaxWidth = hasFrameButtons
        ? `${buttons.length * 34}px`
        : "0px";
    const isShared = component.isShared &&
        providerDistinguishesSharedComponents(pageViewContext.componentsProviderSettings);
    const isLayout = component.layoutId;
    // Layout components should be read-only when showLayoutComponents is disabled
    const isLayoutReadonly = isLayout && !editContext.showLayoutComponents;
    const isReadonly = editContext.mode === "preview" || compareView || isLayoutReadonly;
    const isInsertMode = editContext.mode === "edit" &&
        (editContext.insertMode || !!editContext.selectedForInsertion);
    function getColor() {
        if (isReadonly && !isLayoutReadonly)
            return "readonly";
        if (editContext?.mode === "suggestions")
            return "suggestions";
        if (isLayout)
            return "layout";
        if (isShared)
            return "shared";
        if (component.canBeMoved)
            return "default";
        return "nonMovable";
    }
    const color = getColor();
    // Calculate initial estimation for the header width
    const estimatedHeaderWidth = isHoverFrame
        ? component.name.length * 6 + 12
        : buttons.length * 30 + component.name.length * 8; // Approximate width calculation
    const initialIsHeaderWiderThanComponent = estimatedHeaderWidth > (componentRect?.width || 0);
    useEffect(() => {
        setIsHeaderWiderThanComponent(initialIsHeaderWiderThanComponent);
    }, [initialIsHeaderWiderThanComponent]);
    if (!componentRect)
        return null;
    const frameLeft = componentRect.x - FRAME_OUTSET;
    const frameTop = componentRect.y - FRAME_OUTSET;
    const frameWidth = componentRect.width + FRAME_OUTSET * 2;
    const frameHeight = componentRect.height + FRAME_OUTSET * 2;
    const headerOffsets = getFrameMenuHeaderOffsets(componentRect.y, {
        headerHeight,
        isMultiSelected,
        frameBorderWidth,
        frameTopBorderWidth,
    });
    // Check if the component's placeholder can accept more components
    const placeholder = component.parentPlaceholder;
    const parentComponent = placeholder?.parentComponent;
    const rootComponentId = pageViewContext.page?.rootComponent.id;
    const selectableParentComponent = parentComponent && parentComponent.id !== rootComponentId
        ? parentComponent
        : undefined;
    const canAppend = !isMultiSelected &&
        !isInsertMode &&
        placeholder?.editable &&
        placeholder?.insertOptions?.some((option) => !option.isHidden && !option.isInvalid);
    // Calculate position for the append dropzone (bottom center of component)
    const appendPosition = canAppend
        ? {
            x: componentRect.x + componentRect.width / 2,
            y: componentRect.y + componentRect.height,
        }
        : null;
    // Calculate the index after the current component
    const appendIndex = placeholder
        ? placeholder.components.findIndex((c) => c.id === component.id) + 1
        : 0;
    if (componentRect.width === 0 && componentRect.height === 0) {
        return null;
    }
    const resolveBridgeFieldAtPoint = async (clientX, clientY) => {
        const selectedRange = editContext.selectedRange;
        if (selectedRange?.text &&
            selectedRange.fieldId &&
            selectedRange.itemId &&
            selectedRange.language &&
            typeof selectedRange.version === "number") {
            const selectedItem = {
                id: selectedRange.itemId,
                language: selectedRange.language,
                version: selectedRange.version,
                database: pageViewContext.page?.item.database,
            };
            const fullItem = await editContext.itemsRepository.getItem(selectedItem);
            const selectedField = fullItem?.fields.find((candidate) => fieldMatchesBridgeId(candidate, selectedRange.fieldId));
            if (selectedField) {
                return {
                    fieldId: selectedField.id,
                    item: selectedItem,
                };
            }
        }
        const iframeRect = pageViewContext.editorIframe?.getBoundingClientRect();
        const geometry = pageViewContext.bridgeGeometry;
        if (!iframeRect || !geometry)
            return undefined;
        const hostX = clientX - iframeRect.left;
        const hostY = clientY - iframeRect.top;
        const fieldTarget = geometry.targets
            .filter((target) => {
            if (target.kind !== "field" || !target.fieldId)
                return false;
            const rect = target.rect;
            return (hostX >= rect.left &&
                hostX <= rect.right &&
                hostY >= rect.top &&
                hostY <= rect.bottom);
        })
            .sort((left, right) => left.rect.width * left.rect.height -
            right.rect.width * right.rect.height)[0];
        if (!fieldTarget?.fieldId)
            return undefined;
        const candidateItems = [];
        const addCandidateItem = (item) => {
            if (!item?.id || !item.language || typeof item.version !== "number") {
                return;
            }
            if (candidateItems.some((candidate) => bridgeIdsMatch(candidate.id, item.id) &&
                candidate.language.toLowerCase() === item.language.toLowerCase() &&
                candidate.version === item.version)) {
                return;
            }
            candidateItems.push({
                id: item.id,
                language: item.language,
                version: item.version,
                name: item.name,
                displayName: item.displayName,
                path: item.path,
                database: item.database,
            });
        };
        addCandidateItem(component.datasourceItem);
        component.items?.forEach(addCandidateItem);
        addCandidateItem(pageViewContext.page?.item);
        for (const item of candidateItems) {
            const fullItem = await editContext.itemsRepository.getItem(item);
            const field = fullItem?.fields.find((candidate) => fieldMatchesBridgeId(candidate, fieldTarget.fieldId));
            if (field) {
                return {
                    fieldId: field.id,
                    item,
                };
            }
        }
        const fallbackItem = candidateItems[0];
        if (!fallbackItem)
            return undefined;
        return {
            fieldId: fieldTarget.fieldId,
            item: fallbackItem,
        };
    };
    const handleHeaderContextMenu = async (e) => {
        if (!editContext)
            return;
        if (e.ctrlKey)
            return;
        e.preventDefault();
        e.stopPropagation();
        const clientX = e.clientX;
        const clientY = e.clientY;
        const { shiftKey, altKey, ctrlKey } = e;
        const currentSelection = editContext.getSelection();
        const selectedComponents = isSelected && currentSelection.length > 0
            ? currentSelection
                .map((id) => pageViewContext.page
                ? getComponentById(id, pageViewContext.page)
                : undefined)
                .filter((x) => x)
            : [component];
        const field = await resolveBridgeFieldAtPoint(clientX, clientY);
        const fieldButtons = field ? await loadFieldButtons(field) : [];
        const menuItems = await buildComponentContextMenuItems(selectedComponents, editContext, field, fieldButtons);
        if (menuItems.length > 0) {
            const syntheticEvent = new MouseEvent("contextmenu", {
                bubbles: true,
                cancelable: true,
                view: window,
                clientX,
                clientY,
                shiftKey,
                altKey,
                ctrlKey,
            });
            editContext.showContextMenu(syntheticEvent, menuItems);
        }
    };
    return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "tour-frame-menu pointer-events-none absolute", style: {
                    left: frameLeft,
                    top: frameTop,
                    width: frameWidth,
                    height: frameHeight,
                    zIndex: FRAME_CHROME_Z_INDEX,
                }, "data-testid": "frame-menu", children: [_jsx("div", { ref: frameRef, className: cn("pointer-events-none absolute inset-0 rounded-bl-xs", isHoverFrame ? "border" : "border-2", isHoverFrame
                            ? "border-neutral-grey-50"
                            : componentFrameBorderColorVariants[color], !isHoverFrame &&
                            !isMultiSelected &&
                            isHeaderWiderThanComponent &&
                            "border-t-0", !isMultiSelected && !isHeaderWiderThanComponent && "rounded-tl-xs", isMultiSelected && "rounded-t-xs") }), _jsx("div", { ref: headerAnimationRef, className: "pointer-events-none absolute inset-0", children: _jsxs("div", { ref: headerRef, className: cn("editframe-menu absolute z-1000 flex items-center text-white", isHoverFrame
                                ? "pointer-events-none px-1.5 text-[10px] leading-none font-medium"
                                : "pointer-events-auto pr-4 text-base", isHoverFrame
                                ? "bg-neutral-grey-50"
                                : componentFrameBgColorVariants[color], !isHoverFrame && componentFrameBgHoverColorVariants[color], !isHoverFrame &&
                                "animate-in slide-in-from-top-2 fade-in duration-100", !isHoverFrame && "transition-colors duration-100 ease-out", headerOffsets.isInsideFrame ? "rounded-bl" : "rounded-t", !isHoverFrame && isHeaderWiderThanComponent && "rounded-bl", isHoverFrame && "max-w-48 rounded-t"), style: {
                                right: headerOffsets.right,
                                top: headerOffsets.top,
                                zIndex: 800,
                                height: headerHeight + "px",
                            }, onContextMenu: isSelected ? handleHeaderContextMenu : undefined, children: [_jsxs("div", { onPointerDown: isSelected ? onGripPointerDown : undefined, className: cn("group flex min-w-0 items-center gap-1 text-nowrap", "transition-colors duration-150 ease-out", isHoverFrame ? "max-w-full truncate" : "p-2 text-sm", isSelected && isDraggable ? "cursor-move" : "cursor-default", isSelected && !isDraggable && "pl-6"), children: [isSelected && isDraggable && (_jsx(GripVertical, { strokeWidth: 1.5, className: "h-4 w-4 transition-transform duration-150 ease-out" })), _jsx("span", { className: "min-w-0 truncate", children: component.name }), isSelected && component.hasPersonalization && (_jsxs(Tooltip, { delayDuration: 500, children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { className: "inline-flex h-4 w-4 items-center justify-center rounded-full bg-white/20", "data-testid": "component-personalization-badge", children: _jsx(Sparkles, { strokeWidth: 1.5, height: 16, width: 16 }) }) }), _jsx(TooltipContent, { children: "Personalized" })] })), isSelected && selectableParentComponent && (_jsxs(Tooltip, { delayDuration: 500, children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": `Select parent ${selectableParentComponent.name}`, className: "inline-flex h-5 w-5 shrink-0 cursor-pointer items-center justify-center rounded-sm border-0 bg-transparent p-0 text-current opacity-0 transition-opacity group-hover:opacity-100 hover:bg-white/20 focus-visible:bg-white/20 focus-visible:opacity-100 focus-visible:outline-none", "data-testid": "frame-menu-select-parent", onPointerDown: (ev) => {
                                                            ev.stopPropagation();
                                                        }, onClick: () => {
                                                            editContext.select([selectableParentComponent.id]);
                                                        }, children: _jsx(ArrowUpFromDot, { strokeWidth: 1.5, height: 16, width: 16 }) }) }), _jsx(TooltipContent, { children: "Select parent" })] }))] }), isSelected && editContext.mode === "edit" && !isMultiSelected && (_jsx("div", { "aria-hidden": !hasFrameButtons, className: cn("flex shrink-0 items-center gap-2.5 overflow-hidden text-sm", "transition-[max-width,opacity,transform] duration-200 ease-out motion-reduce:transition-none", hasFrameButtons
                                        ? "translate-x-0 opacity-100"
                                        : "-translate-x-1 opacity-0"), style: { maxWidth: frameButtonsMaxWidth }, children: buttons.map((b) => (_jsxs(Tooltip, { delayDuration: 500, children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("div", { className: "hover:text-neutral-grey-15 inline-flex h-5 w-5 shrink-0 cursor-pointer items-center justify-center rounded-sm transition-colors duration-150 ease-out hover:bg-white/15 [&_svg]:h-4 [&_svg]:w-4", onClick: (ev) => {
                                                        ev.stopPropagation();
                                                        b.onClick(ev);
                                                    }, "data-testid": `frame-menu-${b.id}`, children: typeof b.icon === "string" ? (_jsx("i", { className: b.icon + " cursor-pointer text-sm" })) : (b.icon) }) }), _jsx(TooltipContent, { children: b.label })] }, b.id))) }))] }) })] }), isSelected &&
                canAppend &&
                !isReadonly &&
                editContext.mode === "edit" &&
                placeholder &&
                appendPosition && (_jsx(PlaceholderDropZone, { frameColor: color, pillLabel: "Append component", onDragHandlePointerDown: isDraggable ? onGripPointerDown : undefined, insertMenuTitle: "Append", placeholder: placeholder, description: `Append to ${placeholder.name}`, index: appendIndex, parentName: component.name, spotPosition: appendPosition, spotPositionElement: null, spotPositionAnchor: "bottom", size: "large", typeIdOnCtrlClick: component.typeId, insertMenuKey: `append:${componentFrameKey}:${placeholder.key}:${appendIndex}`, openInsertMenuKey: openInsertMenuKey, onInsertMenuOpenChange: onInsertMenuOpenChange }))] }));
}
//# sourceMappingURL=FrameMenu.js.map