import { usePopover } from "../hooks/usePopover.js";
import { useSearchInput } from "../hooks/useSearchInput.js";
import chevron_down_default from "../icons/chevron-down.js";
import { colors } from "../utils/colors/index.js";
import { common } from "../styledSystem/common.js";
import { animations } from "../styledSystem/animations.js";
import { descriptors } from "../customizables/elementDescriptors.js";
import { withFloatingTree } from "./contexts/index.js";
import { Button, Flex, Icon, Input, Text } from "../customizables/index.js";
import { Popover } from "./Popover.js";
import React, { useState } from "react";
import { createContextAndHook } from "@clerk/shared/react";
import { Fragment as Fragment$1, jsx, jsxs } from "@emotion/react/jsx-runtime";

//#region src/elements/Select.tsx
const [SelectStateCtx, useSelectState] = createContextAndHook("SelectState");
const defaultRenderOption = (option, _index) => {
	return /* @__PURE__ */ jsx(Flex, {
		sx: (theme) => ({
			position: "relative",
			width: "100%",
			padding: `${theme.space.$2} ${theme.space.$4}`,
			margin: `0 ${theme.space.$1}`,
			borderRadius: theme.radii.$md,
			"&:hover, &[data-focused=\"true\"]": { background: common.mutedBackground(theme) },
			"&::before": {
				content: "\"\"",
				position: "absolute",
				inset: `calc(${theme.space.$0x5} * -1) calc(${theme.space.$1} * -1)`
			}
		}),
		children: /* @__PURE__ */ jsx(Text, {
			truncate: true,
			children: option.label || option.value
		})
	});
};
const defaultButtonRenderOption = (option) => {
	return option.label || option.value;
};
const Select = withFloatingTree((props) => {
	const { value, options, onChange, renderOption, noResultsMessage, comparator, placeholder = "Select an option", searchPlaceholder, elementId, children, portal = false, referenceElement = null,...rest } = props;
	const popoverCtx = usePopover({
		autoUpdate: true,
		adjustToReferenceWidth: !!referenceElement,
		referenceElement
	});
	const togglePopover = popoverCtx.toggle;
	const focusedItemRef = React.useRef(null);
	const searchInputCtx = useSearchInput({
		items: options,
		comparator: comparator || (() => true)
	});
	const select = React.useCallback((option) => {
		onChange?.(option);
		togglePopover();
	}, [togglePopover, onChange]);
	const defaultChildren = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(SelectOptionList, {}), /* @__PURE__ */ jsx(SelectButton, {})] });
	return /* @__PURE__ */ jsx(SelectStateCtx.Provider, {
		value: { value: {
			popoverCtx,
			searchInputCtx,
			selectedOption: options.find((o) => o.value === value) || null,
			noResultsMessage,
			focusedItemRef,
			value,
			renderOption: renderOption || defaultRenderOption,
			buttonRenderOption: renderOption || defaultButtonRenderOption,
			placeholder,
			searchPlaceholder,
			comparator,
			select,
			onTriggerClick: togglePopover,
			elementId,
			portal
		} },
		...rest,
		children: React.Children.count(children) ? children : defaultChildren
	});
});
const SelectRenderOption = React.memo(React.forwardRef((props, ref) => {
	const { option, renderOption, isSelected, index, handleSelect, isFocused, elementId } = props;
	return /* @__PURE__ */ jsx(Flex, {
		ref,
		sx: {
			userSelect: "none",
			cursor: "pointer"
		},
		onClick: () => {
			handleSelect(option);
		},
		children: React.cloneElement(renderOption(option, index, isSelected), {
			elementDescriptor: descriptors.selectOption,
			elementId: descriptors.selectOption.setId(elementId),
			"data-selected": isSelected,
			"data-focused": isFocused
		})
	});
}));
const SelectSearchbar = (props) => {
	const { sx,...rest } = props;
	React.useEffect(() => {
		return () => props.onChange({ target: { value: "" } });
	}, []);
	const { elementId } = useSelectState();
	return /* @__PURE__ */ jsx(Flex, {
		sx: (t) => ({ padding: t.space.$0x5 }),
		children: /* @__PURE__ */ jsx(Input, {
			elementDescriptor: descriptors.selectSearchInput,
			elementId: descriptors.selectSearchInput.setId(elementId),
			focusRing: false,
			variant: "unstyled",
			sx: [(t) => ({
				borderRadius: t.radii.$md,
				backgroundColor: t.colors.$neutralAlpha100,
				padding: t.space.$2
			}), sx],
			...rest
		})
	});
};
const SelectNoResults = (props) => {
	const { sx,...rest } = props;
	return /* @__PURE__ */ jsx(Text, {
		as: "div",
		sx: [(theme) => ({
			width: "100%",
			padding: `${theme.space.$1} ${theme.space.$2} ${theme.space.$2} ${theme.space.$2}`
		}), sx],
		...rest
	});
};
const SelectOptionList = (props) => {
	const { containerSx, sx,...rest } = props;
	const { popoverCtx, searchInputCtx, value, renderOption, searchPlaceholder, comparator, focusedItemRef, noResultsMessage, select, onTriggerClick, elementId, portal } = useSelectState();
	const { filteredItems: options, searchInputProps } = searchInputCtx;
	const [focusedIndex, setFocusedIndex] = useState(0);
	const { isOpen, floating, styles, nodeId, context } = popoverCtx;
	const containerRef = React.useRef(null);
	const scrollToItemOnSelectedIndexChange = () => {
		if (!isOpen) {
			setFocusedIndex(-1);
			return;
		}
		focusedItemRef.current?.scrollIntoView?.({ block: "nearest" });
	};
	React.useEffect(scrollToItemOnSelectedIndexChange, [focusedIndex, isOpen]);
	React.useEffect(() => setFocusedIndex(0), [options.length]);
	React.useEffect(() => {
		if (!comparator) containerRef?.current?.focus();
		if (isOpen) {
			setFocusedIndex(options.findIndex((o) => o.value === value));
			focusedItemRef.current?.scrollIntoView?.({ block: "nearest" });
			return;
		}
	}, [isOpen]);
	const onKeyDown = (e) => {
		if (e.key === "ArrowUp") {
			e.preventDefault();
			if (isOpen) return setFocusedIndex((i = 0) => i === 0 ? options.length - 1 : i - 1);
			return onTriggerClick();
		}
		if (e.key === "ArrowDown") {
			e.preventDefault();
			if (isOpen) return setFocusedIndex((i = 0) => i === options.length - 1 ? 0 : i + 1);
			return onTriggerClick();
		}
		if (e.key === "Enter" && focusedIndex >= 0) {
			e.preventDefault();
			return select(options[focusedIndex]);
		}
	};
	return /* @__PURE__ */ jsx(Popover, {
		nodeId,
		context,
		isOpen,
		portal: portal || false,
		order: ["content"],
		children: /* @__PURE__ */ jsxs(Flex, {
			elementDescriptor: descriptors.selectOptionsContainer,
			elementId: descriptors.selectOptionsContainer.setId(elementId),
			ref: floating,
			onKeyDown,
			direction: "col",
			justify: "start",
			sx: [(theme) => ({
				backgroundColor: colors.makeSolid(theme.colors.$colorBackground),
				borderRadius: theme.radii.$lg,
				overflow: "hidden",
				animation: `${animations.dropdownSlideInScaleAndFade} ${theme.transitionDuration.$slower} ${theme.transitionTiming.$slowBezier}`,
				transformOrigin: "top center",
				boxShadow: theme.shadows.$menuShadow,
				zIndex: theme.zIndices.$dropdown
			}), sx],
			style: {
				...styles,
				left: styles.left - 1
			},
			children: [comparator && /* @__PURE__ */ jsx(SelectSearchbar, {
				placeholder: searchPlaceholder,
				...searchInputProps
			}), /* @__PURE__ */ jsxs(Flex, {
				ref: containerRef,
				direction: "col",
				tabIndex: comparator ? void 0 : 0,
				sx: [(theme) => ({
					gap: theme.space.$0x5,
					outline: "none",
					overflowY: "auto",
					maxHeight: "18vh",
					padding: `${theme.space.$0x5} ${theme.space.$0x5}`
				}), containerSx],
				...rest,
				children: [options.map((option, index) => {
					const isFocused = index === focusedIndex;
					const isSelected = value === option.value;
					return /* @__PURE__ */ jsx(SelectRenderOption, {
						index,
						ref: isFocused ? focusedItemRef : void 0,
						option,
						renderOption,
						isSelected,
						isFocused,
						handleSelect: select,
						elementId
					}, option.value);
				}), noResultsMessage && options.length === 0 && /* @__PURE__ */ jsx(SelectNoResults, { children: noResultsMessage })]
			})]
		})
	});
};
const SelectButton = (props) => {
	const { sx, children, icon, iconSx,...rest } = props;
	const { popoverCtx, onTriggerClick, buttonRenderOption, selectedOption, placeholder, elementId } = useSelectState();
	const { reference } = popoverCtx;
	let show = children;
	if (!children) show = selectedOption ? buttonRenderOption(selectedOption) : /* @__PURE__ */ jsx(Text, {
		as: "span",
		children: placeholder
	});
	return /* @__PURE__ */ jsxs(Button, {
		elementDescriptor: descriptors.selectButton,
		elementId: descriptors.selectButton.setId(elementId),
		ref: reference,
		variant: "outline",
		textVariant: "buttonLarge",
		onClick: onTriggerClick,
		sx: [(theme) => ({
			gap: theme.space.$2,
			paddingLeft: theme.space.$3x5,
			paddingRight: theme.space.$3x5,
			alignItems: "center",
			"> *": { pointerEvents: "none" }
		}), sx],
		...rest,
		children: [show, /* @__PURE__ */ jsx(Icon, {
			elementDescriptor: descriptors.selectButtonIcon,
			elementId: descriptors.selectButtonIcon.setId(elementId),
			size: "md",
			icon: icon || chevron_down_default,
			sx: iconSx
		})]
	});
};

//#endregion
export { Select, SelectButton, SelectOptionList };
//# sourceMappingURL=Select.js.map