import { useLoadingStatus } from "../hooks/useLoadingStatus.js";
import { common } from "../styledSystem/common.js";
import { mqu } from "../styledSystem/breakpoints.js";
import { useFormControl } from "../utils/useFormControl.js";
import { descriptors } from "../customizables/elementDescriptors.js";
import { useAppearance } from "../customizables/AppearanceContext.js";
import { useCardState } from "./contexts/index.js";
import { Box, Flex, OTPInputSegment } from "../customizables/index.js";
import { sleep } from "../utils/sleep.js";
import { handleError } from "../utils/errorHandler.js";
import { TimerButton } from "./TimerButton.js";
import React, { useCallback } from "react";
import { createContextAndHook } from "@clerk/shared/react";
import { Fragment as Fragment$1, jsx, jsxs } from "@emotion/react/jsx-runtime";
import { OTPInput, REGEXP_ONLY_DIGITS } from "input-otp";

//#region src/elements/CodeControl.tsx
const useFieldOTP = (params) => {
	const card = useCardState();
	const { id = "code", onCodeEntryFinished: paramsOnCodeEntryFinished, onResendCodeClicked: paramsOnResendCodeClicked, onResolve: paramsOnResolve } = params;
	const codeControlState = useFormControl(id, "");
	const codeControl = useCodeControl(codeControlState);
	const status = useLoadingStatus();
	const resolve = async (param) => {
		codeControlState.setSuccess("success");
		await sleep(750);
		await paramsOnResolve?.(param);
	};
	const reject = async (err) => {
		handleError(err, [codeControlState], card.setError);
		status.setIdle();
		await sleep(750);
		codeControl.reset();
	};
	codeControl.onCodeEntryFinished((code) => {
		status.setLoading();
		codeControlState.clearFeedback();
		paramsOnCodeEntryFinished(code, resolve, reject);
	});
	const onFakeContinue = () => {
		codeControlState.clearFeedback();
		paramsOnCodeEntryFinished("", resolve, reject);
	};
	const onResendCode = useCallback((e) => {
		codeControl.reset();
		paramsOnResendCodeClicked?.(e);
	}, [codeControl, paramsOnResendCodeClicked]);
	return {
		isLoading: status.isLoading,
		otpControl: codeControl,
		onResendCode: paramsOnResendCodeClicked ? onResendCode : void 0,
		onFakeContinue
	};
};
const useCodeControl = (formControl, options) => {
	const userOnCodeEnteredCallback = React.useRef();
	const defaultValue = formControl.value;
	const { feedback, feedbackType, onChange, clearFeedback } = formControl;
	const { length = 6 } = options || {};
	const [values, setValues] = React.useState(() => defaultValue ? defaultValue.split("").slice(0, length) : Array.from({ length }, () => ""));
	const onCodeEntryFinished = (cb) => {
		userOnCodeEnteredCallback.current = cb;
	};
	const reset = React.useCallback(() => {
		setValues(Array.from({ length }, () => ""));
	}, [length]);
	React.useEffect(() => {
		if (values.filter((c) => c).length === length) {
			const code = values.map((c) => c || " ").join("");
			userOnCodeEnteredCallback.current?.(code);
		} else {
			const code = values.join("");
			onChange?.({ target: { value: code } });
		}
	}, [values.toString()]);
	return {
		otpInputProps: {
			length,
			values,
			setValues,
			feedback,
			feedbackType,
			clearFeedback
		},
		onCodeEntryFinished,
		reset
	};
};
const [OTPInputContext, useOTPInputContext] = createContextAndHook("OTPInputContext");
const OTPRoot = ({ children,...props }) => {
	return /* @__PURE__ */ jsx(OTPInputContext.Provider, {
		value: { value: props },
		children
	});
};
const OTPResendButton = () => {
	const { resendButton, onResendCode, isLoading, otpControl } = useOTPInputContext();
	if (!onResendCode) return null;
	return /* @__PURE__ */ jsx(TimerButton, {
		elementDescriptor: descriptors.formResendCodeLink,
		onClick: onResendCode,
		startDisabled: true,
		isDisabled: otpControl.otpInputProps.feedbackType === "success" || isLoading,
		showCounter: otpControl.otpInputProps.feedbackType !== "success",
		localizationKey: resendButton
	});
};
const OTPCodeControl = () => {
	const [disabled, setDisabled] = React.useState(false);
	const { otpControl, isLoading, isDisabled } = useOTPInputContext();
	const { autoFocus: optionAutoFocus } = useAppearance().parsedOptions;
	const { feedback, values, setValues, feedbackType, length } = otpControl.otpInputProps;
	React.useEffect(() => {
		if (feedback) setDisabled(true);
	}, [feedback]);
	return /* @__PURE__ */ jsx(Box, {
		elementDescriptor: descriptors.otpCodeFieldInputContainer,
		sx: { position: "relative" },
		children: /* @__PURE__ */ jsx(OTPInput, {
			autoFocus: optionAutoFocus,
			"aria-label": "Enter verification code",
			"aria-required": true,
			maxLength: length,
			inputMode: "numeric",
			pattern: REGEXP_ONLY_DIGITS,
			textAlign: "center",
			value: values.join(""),
			onChange: (newValue) => {
				setValues(newValue.split(""));
			},
			render: ({ slots }) => /* @__PURE__ */ jsx(Flex, {
				align: "center",
				elementDescriptor: descriptors.otpCodeFieldInputs,
				gap: 2,
				hasError: feedbackType === "error",
				isLoading,
				role: "group",
				children: slots.map((slot, index) => /* @__PURE__ */ jsx(Slot, {
					elementDescriptor: descriptors.otpCodeFieldInput,
					isDisabled: isDisabled || isLoading || disabled || feedbackType === "success",
					hasError: feedbackType === "error",
					isSuccessfullyFilled: feedbackType === "success",
					...slot
				}, index))
			})
		})
	});
};
function Slot(props) {
	const { isSuccessfullyFilled,...otpProps } = props;
	const { char, hasFakeCaret, isActive, placeholderChar,...rest } = otpProps;
	return /* @__PURE__ */ jsxs(OTPInputSegment, {
		"data-testid": "otp-input-segment",
		...rest,
		focusRing: isActive,
		variant: "default",
		sx: (t) => ({
			textAlign: "center",
			...common.textVariants(t).h2,
			padding: `${t.space.$0x5} 0`,
			boxSizing: "border-box",
			display: "flex",
			position: "relative",
			alignItems: "center",
			justifyContent: "center",
			height: t.space.$10,
			width: t.space.$10,
			color: t.colors.$colorInputForeground,
			borderWidth: t.borderWidths.$normal,
			borderRadius: t.radii.$md,
			...isSuccessfullyFilled ? { borderColor: t.colors.$success500 } : common.borderColor(t, props),
			backgroundColor: "unset",
			[mqu.sm]: {
				height: t.space.$8,
				width: t.space.$8
			}
		}),
		children: [char !== null && /* @__PURE__ */ jsx("div", { children: char }), hasFakeCaret && /* @__PURE__ */ jsx(FakeCaret, {})]
	});
}
function FakeCaret() {
	return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("style", { children: `
        @keyframes caret-blink-animation {
          0%, 50% {
            opacity: 1;
          }
          51%, 100% {
            opacity: 0;
          }
        }
      ` }), /* @__PURE__ */ jsx(Flex, {
		align: "center",
		justify: "center",
		sx: () => ({
			animation: "caret-blink-animation 1s infinite",
			pointerEvents: "none",
			position: "absolute",
			inset: 0
		}),
		children: /* @__PURE__ */ jsx(Box, { sx: (t) => ({
			height: t.space.$4,
			width: t.space.$px,
			backgroundColor: t.colors.$colorInputForeground
		}) })
	})] });
}

//#endregion
export { OTPCodeControl, OTPResendButton, OTPRoot, useFieldOTP };
//# sourceMappingURL=CodeControl.js.map