/*! ratio-ui · design system for knowledge sharing · https://github.com/losol/ratio-ui · (c) 2026 Losol AS · MPL-2.0 */
"use client";
import { Input as Input$1 } from "./Input.js";
import { componentStyles, formStyles, textStyles } from "../styles/formStyles.js";
import { Label as Label$1 } from "../common/Label.js";
import { InputError } from "../common/InputError.js";
import { InputDescription } from "../common/InputDescription.js";
import { COUNTRY_CODES } from "./PhoneInputCountryCodes.js";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { jsx, jsxs } from "react/jsx-runtime";
import { Button, ComboBox, Input, ListBox, ListBoxItem, Popover } from "react-aria-components";
//#region src/forms/Input/PhoneInput.tsx
var PHONE_VALIDATION_RULES = {
	"+47": {
		exact: 8,
		message: "Norwegian phone numbers must be exactly 8 digits"
	},
	"+46": {
		min: 7,
		max: 13,
		message: "Swedish phone numbers must be 7 to 13 digits"
	},
	"+45": {
		exact: 8,
		message: "Danish phone numbers must be exactly 8 digits"
	}
};
var CountryItem = React.memo(({ country, stableId }) => /* @__PURE__ */ jsxs(ListBoxItem, {
	id: stableId,
	textValue: `${country.flag} ${country.code} ${country.name}`,
	className: componentStyles.listBoxItem,
	children: [
		/* @__PURE__ */ jsx("span", {
			className: "text-lg mr-2",
			children: country.flag
		}),
		/* @__PURE__ */ jsx("span", {
			className: textStyles.listBoxItemPrimary,
			children: country.code
		}),
		/* @__PURE__ */ jsx("span", {
			className: `${textStyles.listBoxItemSecondary} ml-2`,
			children: country.name
		})
	]
}, stableId));
CountryItem.displayName = "CountryItem";
function PhoneInput({ name = "phone", label = "Phone Number", description, defaultCode = "+47", countries = COUNTRY_CODES, value, errors, disabled, onChange, testId }) {
	const defaultCountry = useMemo(() => countries.find((c) => c.code === defaultCode) || countries[0] || {
		name: "",
		code: "",
		flag: ""
	}, [countries, defaultCode]);
	const [country, setCountry] = useState(defaultCountry);
	const [localNumber, setLocalNumber] = useState("");
	const [comboInputValue, setComboInputValue] = useState("");
	const [localError, setLocalError] = useState(null);
	const emitChange = useCallback((selectedCountry, number) => {
		const fullNumber = selectedCountry ? `${selectedCountry.code}${number}` : number;
		onChange?.({
			fullNumber,
			localNumber: number,
			country: selectedCountry
		});
	}, [onChange]);
	useEffect(() => {
		if (!value) {
			setLocalNumber("");
			return;
		}
		const matchedCountry = countries.find((c) => value.startsWith(c.code));
		if (matchedCountry) {
			setCountry(matchedCountry);
			setLocalNumber(value.slice(matchedCountry.code.length));
		} else {
			setCountry(defaultCountry);
			setLocalNumber(value.replace(/^\+/, ""));
		}
	}, [
		value,
		countries,
		defaultCountry
	]);
	useEffect(() => {
		setComboInputValue(country.code);
	}, [country]);
	const handleNumberChange = useCallback((e) => {
		const cleaned = e.target.value.replaceAll(/\D/g, "");
		setLocalNumber(cleaned);
		setLocalError(null);
		emitChange(country, cleaned);
	}, [country, emitChange]);
	const handleNumberBlur = useCallback(() => {
		if (!localNumber) {
			setLocalError(null);
			return;
		}
		const rule = PHONE_VALIDATION_RULES[country.code];
		let error = null;
		if (rule) {
			if (rule.exact !== void 0 && localNumber.length !== rule.exact) error = rule.message;
			else if (rule.min !== void 0 && localNumber.length < rule.min || rule.max !== void 0 && localNumber.length > rule.max) error = rule.message;
		} else if (localNumber.length < 6) error = "Phone number must be at least 6 digits";
		else if (localNumber.length > 15) error = "Phone number must be at most 15 digits";
		setLocalError(error);
	}, [country.code, localNumber]);
	const handleCountryChange = useCallback((key) => {
		if (!key || key === "no-results") {
			emitChange(null, localNumber);
			return;
		}
		const [code, encodedName] = String(key).split(":");
		const name = encodedName?.replaceAll("_", " ");
		const selectedCountry = countries.find((c) => c.code === code && c.name === name) || null;
		if (selectedCountry) setCountry(selectedCountry);
		emitChange(selectedCountry, localNumber);
	}, [
		countries,
		emitChange,
		localNumber
	]);
	const handleInputChange = useCallback((val) => {
		setComboInputValue(val);
	}, []);
	const handleOpenChange = useCallback((isOpen) => {
		if (!isOpen) setComboInputValue(country.code);
	}, [country]);
	const commitTypedCountryCode = useCallback((raw) => {
		const typed = raw.trim();
		if (!typed) return false;
		const normalized = typed.startsWith("+") ? typed : `+${typed}`;
		const matched = countries.find((c) => c.code.toLowerCase() === normalized.toLowerCase());
		if (matched) {
			if (matched.code !== country.code) {
				setCountry(matched);
				emitChange(matched, localNumber);
			}
			setComboInputValue(matched.code);
			return true;
		}
		return false;
	}, [
		countries,
		country.code,
		emitChange,
		localNumber
	]);
	const handleInputBlur = useCallback(() => {
		if (!commitTypedCountryCode(comboInputValue)) setComboInputValue(country.code);
	}, [
		commitTypedCountryCode,
		comboInputValue,
		country.code
	]);
	const filteredCountries = useMemo(() => {
		const query = comboInputValue.trim().toLowerCase();
		if (!query || query === country.code.toLowerCase()) return countries;
		return countries.filter((c) => c.name.toLowerCase().includes(query) || c.code.toLowerCase().includes(query));
	}, [
		countries,
		comboInputValue,
		country.code
	]);
	const selectedKey = useMemo(() => {
		return country.code && country.name ? `${country.code}:${country.name.replaceAll(/\s+/g, "_")}` : null;
	}, [country.code, country.name]);
	const renderedCountries = useMemo(() => {
		return filteredCountries.map((countryItem) => {
			const stableId = `${countryItem.code}:${countryItem.name.replaceAll(/\s+/g, "_")}`;
			return /* @__PURE__ */ jsx(CountryItem, {
				country: countryItem,
				stableId
			}, stableId);
		});
	}, [filteredCountries]);
	return /* @__PURE__ */ jsxs("div", {
		className: formStyles.inputWrapper,
		children: [
			label && /* @__PURE__ */ jsx(Label$1, { children: label }),
			description && /* @__PURE__ */ jsx(InputDescription, { children: description }),
			/* @__PURE__ */ jsxs("div", {
				className: `${componentStyles.phoneInputContainer} flex items-stretch`,
				children: [/* @__PURE__ */ jsxs(ComboBox, {
					selectedKey,
					inputValue: comboInputValue,
					onSelectionChange: handleCountryChange,
					onInputChange: handleInputChange,
					onOpenChange: handleOpenChange,
					className: `${componentStyles.integratedComboBoxContainer} min-w-16 max-w-24`,
					allowsCustomValue: false,
					isDisabled: disabled,
					"aria-label": "Select country code",
					menuTrigger: "input",
					children: [/* @__PURE__ */ jsxs("div", {
						className: componentStyles.comboBoxInputWrapper,
						children: [/* @__PURE__ */ jsx(Input, {
							className: componentStyles.comboBoxInputField,
							placeholder: "Select country",
							onBlur: handleInputBlur,
							onKeyDown: (e) => {
								if (e.key === "Tab" || e.key === "Enter") {
									const val = e.target.value;
									commitTypedCountryCode(val);
								}
							}
						}), /* @__PURE__ */ jsx(Button, {
							className: `px-2 ${textStyles.dropdownButton}`,
							children: "▾"
						})]
					}), /* @__PURE__ */ jsx(Popover, {
						className: `${componentStyles.popover} max-h-60 overflow-hidden`,
						children: /* @__PURE__ */ jsxs(ListBox, {
							className: "max-h-60 overflow-y-auto",
							children: [renderedCountries, filteredCountries.length === 0 && /* @__PURE__ */ jsx(ListBoxItem, {
								id: "no-results",
								textValue: "No countries found",
								className: `px-3 py-2 ${textStyles.emptyStateText}`,
								isDisabled: true,
								children: "No countries found"
							})]
						})
					})]
				}), /* @__PURE__ */ jsx(Input$1, {
					name,
					type: "tel",
					inputMode: "numeric",
					pattern: "[0-9]*",
					value: localNumber,
					onChange: handleNumberChange,
					onBlur: handleNumberBlur,
					disabled,
					placeholder: "Enter phone number",
					className: "p-2 bg-card text-(--text) border-0 rounded-none focus:ring-0 flex-1 w-full",
					"data-testid": testId
				})]
			}),
			(localError || errors?.[name]?.message) && /* @__PURE__ */ jsx(InputError, {
				errors: { [name]: { message: localError || errors?.[name]?.message || "" } },
				name
			})
		]
	});
}
//#endregion
export { PhoneInput };

//# sourceMappingURL=PhoneInput.js.map