'use client';

import { cn } from "../../utils/cn.mjs";
import { Badge, BadgeColor } from "../Badge/index.mjs";
import { Command, CommandRoot } from "../Command/index.mjs";
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
import { Check, X } from "lucide-react";
import { jsx, jsxs } from "react/jsx-runtime";

//#region src/components/Select/Multiselect.tsx
const MultiSelectContext = createContext(null);
/**
* Custom hook to access MultiSelect context
*
* Provides access to the internal state and methods of the MultiSelect component.
* Must be used within a MultiSelect component tree.
*
* @returns MultiSelectContextProps - All context properties and methods
* @throws Error when used outside of MultiSelect component
*
* @example
* ```tsx
* function CustomMultiSelectItem() {
*   const { value, onValueChange, open } = useMultiSelect();
*   // Use context properties...
* }
* ```
*/
const useMultiSelect = () => {
	const context = useContext(MultiSelectContext);
	if (!context) throw new Error("useMultiSelect must be used within MultiSelectProvider");
	return context;
};
/**
* MultiSelect - A comprehensive multi-selection dropdown component
*
* An advanced multi-select component that combines the functionality of a searchable dropdown
* with the ability to select multiple values. Built on top of Command component primitives,
* it provides filtering, keyboard navigation, and visual feedback through badges.
*
* ## Key Features
* - **Multi-Selection**: Select multiple options with visual badge representation
* - **Searchable**: Built-in filtering to quickly find options in large lists
* - **Keyboard Navigation**: Full arrow key navigation with optional looping
* - **Accessibility**: Screen reader support, ARIA attributes, and focus management
* - **Flexible State**: Both controlled and uncontrolled usage patterns
* - **Rich UI**: Customizable badges, icons, and content layout
*
* ## Use Cases
* - Tag/category selection in forms
* - Multi-user assignment interfaces
* - Feature/permission selection
* - Filter selection in search interfaces
* - Any multi-choice selection requirement
*
* ## Architecture
* The component follows a compound pattern similar to Select:
* - `MultiSelect` (root): Manages state and provides context
* - `MultiSelect.Trigger`: Container for input and selected badges
* - `MultiSelect.Input`: Searchable input field with filtering
* - `MultiSelect.Content`: Dropdown container for options
* - `MultiSelect.List`: Options container with keyboard navigation
* - `MultiSelect.Item`: Individual selectable options
*
* ## Accessibility
* - **Keyboard Navigation**: Arrow keys, Enter to select, Backspace to remove
* - **Screen Readers**: Proper ARIA labels and live region announcements
* - **Focus Management**: Clear focus indicators and logical tab flow
* - **Search**: Real-time filtering with screen reader announcements
*
* @example
* Basic multi-select usage:
* ```tsx
* const [frameworks, setFrameworks] = useState<string[]>([]);
*
* <MultiSelect values={frameworks} onValueChange={setFrameworks}>
*   <MultiSelect.Trigger>
*     <MultiSelect.Input placeholder="Select frameworks..." />
*   </MultiSelect.Trigger>
*   <MultiSelect.Content>
*     <MultiSelect.List>
*       <MultiSelect.Item value="react">React</MultiSelect.Item>
*       <MultiSelect.Item value="vue">Vue</MultiSelect.Item>
*       <MultiSelect.Item value="svelte">Svelte</MultiSelect.Item>
*     </MultiSelect.List>
*   </MultiSelect.Content>
* </MultiSelect>
* ```
*
* @example
* Advanced usage with keyboard looping:
* ```tsx
* <MultiSelect defaultValues={['react']} loop>
*   <MultiSelect.Trigger>
*     <MultiSelect.Input placeholder="Choose technologies..." />
*   </MultiSelect.Trigger>
*   <MultiSelect.Content>
*     <MultiSelect.List>
*       <MultiSelect.Item value="react">⚛️ React</MultiSelect.Item>
*       <MultiSelect.Item value="vue">💚 Vue</MultiSelect.Item>
*       <MultiSelect.Item value="angular">🔴 Angular</MultiSelect.Item>
*     </MultiSelect.List>
*   </MultiSelect.Content>
* </MultiSelect>
* ```
*
* @example
* Form integration with validation:
* ```tsx
* <form>
*   <MultiSelect
*     values={selectedSkills}
*     onValueChange={setSelectedSkills}
*     required
*   >
*     <MultiSelect.Trigger className="min-h-[2.5rem]">
*       <MultiSelect.Input placeholder="Select your skills..." />
*     </MultiSelect.Trigger>
*     <MultiSelect.Content>
*       <MultiSelect.List>
*         <MultiSelect.Item value="javascript">JavaScript</MultiSelect.Item>
*         <MultiSelect.Item value="typescript">TypeScript</MultiSelect.Item>
*         <MultiSelect.Item value="python">Python</MultiSelect.Item>
*       </MultiSelect.List>
*     </MultiSelect.Content>
*   </MultiSelect>
* </form>
* ```
*/
const MultiSelectRoot = ({ values: valuesProp, defaultValues, onValueChange, loop = false, className, children, dir, ...props }) => {
	const [value, setValue] = useState(defaultValues ?? []);
	const [inputValue, setInputValue] = useState("");
	const [open, setOpen] = useState(false);
	const [activeIndex, setActiveIndex] = useState(-1);
	const inputRef = useRef(null);
	const [isValueSelected, setIsValueSelected] = useState(false);
	const [selectedValue, setSelectedValue] = useState("");
	useEffect(() => {
		if (valuesProp) setValue(valuesProp);
	}, [valuesProp]);
	const onValueChangeHandler = useCallback((val) => {
		if (value.includes(val)) {
			const newValue = value.filter((item) => item !== val);
			setValue(newValue);
			onValueChange?.(newValue);
		} else {
			const newValue = [...value, val];
			setValue(newValue);
			onValueChange?.(newValue);
		}
	}, [value]);
	const handleSelect = useCallback((e) => {
		e.preventDefault();
		const target = e.currentTarget;
		const selection = target.value.substring(target.selectionStart ?? 0, target.selectionEnd ?? 0);
		setSelectedValue(selection);
		setIsValueSelected(selection === inputValue);
	}, [inputValue]);
	const handleKeyDown = useCallback((e) => {
		e.stopPropagation();
		const target = inputRef.current;
		if (!target) return;
		const moveNext = () => {
			const nextIndex = activeIndex + 1;
			setActiveIndex(nextIndex > value.length - 1 ? loop ? 0 : -1 : nextIndex);
		};
		const movePrev = () => {
			const prevIndex = activeIndex - 1;
			setActiveIndex(prevIndex < 0 ? value.length - 1 : prevIndex);
		};
		const moveCurrent = () => {
			setActiveIndex(activeIndex - 1 <= 0 ? value.length - 1 === 0 ? -1 : 0 : activeIndex - 1);
		};
		switch (e.key) {
			case "ArrowLeft":
				if (dir === "rtl") {
					if (value.length > 0 && (activeIndex !== -1 || loop)) moveNext();
				} else if (value.length > 0 && target.selectionStart === 0) movePrev();
				break;
			case "ArrowRight":
				if (dir === "rtl") {
					if (value.length > 0 && target.selectionStart === 0) movePrev();
				} else if (value.length > 0 && (activeIndex !== -1 || loop)) moveNext();
				break;
			case "Backspace":
			case "Delete":
				if (value.length > 0) {
					if (activeIndex !== -1 && activeIndex < value.length) {
						onValueChangeHandler(value[activeIndex]);
						moveCurrent();
					} else if (target.selectionStart === 0 && selectedValue === inputValue || isValueSelected) onValueChangeHandler(value[value.length - 1]);
				}
				break;
			case "Enter":
				setOpen(true);
				break;
			case "Escape":
				if (activeIndex !== -1) setActiveIndex(-1);
				else if (open) setOpen(false);
				break;
		}
	}, [
		value,
		inputValue,
		activeIndex,
		loop
	]);
	return /* @__PURE__ */ jsx(MultiSelectContext, {
		value: useMemo(() => ({
			value,
			onValueChange: onValueChangeHandler,
			open,
			setOpen,
			inputValue,
			setInputValue,
			activeIndex,
			setActiveIndex,
			ref: inputRef,
			handleSelect
		}), [
			value,
			onValueChangeHandler,
			open,
			setOpen,
			inputValue,
			setInputValue,
			activeIndex,
			setActiveIndex,
			inputRef,
			handleSelect
		]),
		children: /* @__PURE__ */ jsx(CommandRoot, {
			onKeyDown: handleKeyDown,
			className: cn("flex w-full flex-col gap-2 overflow-visible bg-transparent", className),
			dir,
			...props,
			children
		})
	});
};
const MultiSelectTrigger = ({ className, getBadgeValue = (value) => value, validationStyleEnabled = false, children, ...props }) => {
	const { value, onValueChange, activeIndex } = useMultiSelect();
	const mousePreventDefault = useCallback((e) => {
		e.preventDefault();
		e.stopPropagation();
	}, []);
	return /* @__PURE__ */ jsxs("div", {
		className: cn("flex w-full flex-col gap-3", "cursor-pointer select-text text-base shadow-none outline-none md:text-sm", "rounded-xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl", "px-2 py-3 md:py-2", "bg-neutral-50 dark:bg-neutral-950", "text-text", "ring-0", "focus-within:outline-none", "focus-within:ring-3", "focus-within:ring-neutral-200", "dark:focus-within:ring-neutral-500", "focus-within:ring-offset-white", "dark:focus-within:ring-offset-neutral-500", "[box-shadow:none]", "disabled:cursor-not-allowed disabled:opacity-50", "aria-invalid:border-error", validationStyleEnabled && "valid:border-success invalid:border-error", className),
		...props,
		children: [value.length > 0 && /* @__PURE__ */ jsx("div", {
			className: "flex w-full flex-wrap gap-1",
			children: value.map((item, index) => /* @__PURE__ */ jsxs(Badge, {
				className: cn("flex items-center gap-1 rounded-xl px-1", activeIndex === index && "ring-2 ring-muted-foreground"),
				color: BadgeColor.TEXT,
				children: [/* @__PURE__ */ jsx("span", {
					className: "text-xs",
					children: getBadgeValue(item)
				}), /* @__PURE__ */ jsxs("button", {
					"aria-label": `Remove ${item} option`,
					"aria-roledescription": "button to remove option",
					onMouseDown: mousePreventDefault,
					onClick: () => onValueChange(item),
					children: [/* @__PURE__ */ jsxs("span", {
						className: "sr-only",
						children: [
							"Remove ",
							item,
							" option"
						]
					}), /* @__PURE__ */ jsx(X, { className: "size-4 cursor-pointer" })]
				})]
			}, item))
		}), children]
	});
};
const MultiSelectInput = ({ className, ...props }) => {
	const { setOpen, inputValue, setInputValue, activeIndex, setActiveIndex, handleSelect, ref: inputRef } = useMultiSelect();
	return /* @__PURE__ */ jsx(Command.Input, {
		...props,
		tabIndex: 0,
		ref: inputRef,
		value: inputValue,
		onValueChange: activeIndex === -1 ? setInputValue : void 0,
		onSelect: handleSelect,
		onBlur: () => setOpen(false),
		onFocus: () => setOpen(true),
		onClick: () => setActiveIndex(-1),
		className: cn("ml-2 flex-1 cursor-pointer outline-hidden", className, activeIndex !== -1 && "caret-transparent")
	});
};
const MultiSelectContent = ({ children }) => {
	const { open } = useMultiSelect();
	return /* @__PURE__ */ jsx("div", {
		className: "relative",
		children: open && children
	});
};
const MultiSelectList = ({ className, children }) => /* @__PURE__ */ jsxs(Command.List, {
	className: cn("absolute top-0 z-10 flex w-full flex-col gap-2", "rounded-xl p-2 shadow-md", "bg-white dark:bg-neutral-950", "text-text", "border border-neutral-200 dark:border-neutral-800", "transition-colors", className),
	children: [children, /* @__PURE__ */ jsx(Command.Empty, { children: /* @__PURE__ */ jsx("span", {
		className: "text-muted-foreground",
		children: "No results found"
	}) })]
});
const MultiSelectItem = ({ className, value, children, ...props }) => {
	const { value: Options, onValueChange, setInputValue } = useMultiSelect();
	const mousePreventDefault = useCallback((e) => {
		e.preventDefault();
		e.stopPropagation();
	}, []);
	const isIncluded = Options.includes(value);
	return /* @__PURE__ */ jsxs(Command.Item, {
		...props,
		onSelect: () => {
			onValueChange(value);
			setInputValue("");
		},
		className: cn("flex cursor-pointer justify-between", "rounded-lg px-2 py-1", "transition-colors", "hover:bg-neutral/10", isIncluded && "opacity-50", props.disabled && "cursor-not-allowed opacity-50", className),
		onMouseDown: mousePreventDefault,
		children: [children, isIncluded && /* @__PURE__ */ jsx(Check, { className: "size-4" })]
	});
};
/**
*
* Usage example:
* ```jsx
* <MultiSelect
*   values={value}
*   onValuesChange={setValue}
*   loop
* >
*   <MultiSelect.Trigger>
*     <MultiSelect.Input placeholder="Select your framework" />
*   </MultiSelect.Trigger>
*   <MultiSelect.Content>
*     <MultiSelect.List>
*       <MultiSelect.Item value={"React"}>React</MultiSelect.Item>
*       <MultiSelect.Item value={"Vue"}>Vue</MultiSelect.Item>
*       <MultiSelect.Item value={"Svelte"}>Svelte</MultiSelect.Item>
*     </MultiSelect.List>
*   </MultiSelect.Content>
* </MultiSelect>
* ```
*/
const MultiSelect = MultiSelectRoot;
MultiSelect.Trigger = MultiSelectTrigger;
MultiSelect.Input = MultiSelectInput;
MultiSelect.Content = MultiSelectContent;
MultiSelect.List = MultiSelectList;
MultiSelect.Item = MultiSelectItem;

//#endregion
export { MultiSelect };
//# sourceMappingURL=Multiselect.mjs.map