'use client';


import { createContext, useEffect, useRef, useState } from "react";
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";

//#region src/components/Input/OTPInput/Input.tsx
const syncTimeouts = (cb) => {
	return [
		setTimeout(cb, 0),
		setTimeout(cb, 10),
		setTimeout(cb, 50)
	];
};
const PWM_BADGE_MARGIN_RIGHT = 18;
const PWM_BADGE_SPACE_WIDTH_PX = 40;
const PWM_BADGE_SPACE_WIDTH = `${PWM_BADGE_SPACE_WIDTH_PX}px`;
const PASSWORD_MANAGERS_SELECTORS = [
	"[data-lastpass-icon-root]",
	"com-1password-button",
	"[data-dashlanecreated]",
	"[style$=\"2147483647 !important;\"]"
].join(",");
const usePasswordManagerBadge = ({ containerRef, inputRef, pushPasswordManagerStrategy, isFocused }) => {
	/** Password managers have a badge
	*  and I'll use this state to push them
	*  outside the input */
	const [hasPWMBadge, setHasPWMBadge] = useState(false);
	const [hasPWMBadgeSpace, setHasPWMBadgeSpace] = useState(false);
	const [done, setDone] = useState(false);
	const willPushPWMBadge = pushPasswordManagerStrategy === "none" ? false : (pushPasswordManagerStrategy === "increase-width" || pushPasswordManagerStrategy === "experimental-no-flickering") && hasPWMBadge && hasPWMBadgeSpace;
	const trackPWMBadge = () => {
		const container = containerRef.current;
		const input = inputRef.current;
		if (!container || !input || done || pushPasswordManagerStrategy === "none") return;
		const elementToCompare = container;
		const rightCornerX = elementToCompare.getBoundingClientRect().left + elementToCompare.offsetWidth;
		const centereredY = elementToCompare.getBoundingClientRect().top + elementToCompare.offsetHeight / 2;
		const x = rightCornerX - PWM_BADGE_MARGIN_RIGHT;
		const y = centereredY;
		if (document.querySelectorAll(PASSWORD_MANAGERS_SELECTORS).length === 0) {
			if (document.elementFromPoint(x, y) === container) return;
		}
		setHasPWMBadge(true);
		setDone(true);
	};
	useEffect(() => {
		const container = containerRef.current;
		if (!container || pushPasswordManagerStrategy === "none") return;
		const checkHasSpace = () => {
			setHasPWMBadgeSpace(window.innerWidth - container.getBoundingClientRect().right >= PWM_BADGE_SPACE_WIDTH_PX);
		};
		checkHasSpace();
		const interval = setInterval(checkHasSpace, 1e3);
		return () => {
			clearInterval(interval);
		};
	}, [containerRef, pushPasswordManagerStrategy]);
	useEffect(() => {
		const _isFocused = isFocused || document.activeElement === inputRef.current;
		if (pushPasswordManagerStrategy === "none" || !_isFocused) return;
		const t1 = setTimeout(trackPWMBadge, 0);
		const t2 = setTimeout(trackPWMBadge, 2e3);
		const t3 = setTimeout(trackPWMBadge, 5e3);
		const t4 = setTimeout(() => {
			setDone(true);
		}, 6e3);
		return () => {
			clearTimeout(t1);
			clearTimeout(t2);
			clearTimeout(t3);
			clearTimeout(t4);
		};
	}, [
		inputRef,
		isFocused,
		pushPasswordManagerStrategy
	]);
	return {
		hasPWMBadge,
		willPushPWMBadge,
		PWM_BADGE_SPACE_WIDTH
	};
};
const usePrevious = (value) => {
	const ref = useRef(void 0);
	useEffect(() => {
		ref.current = value;
	});
	return ref.current;
};
const OTPInputContext = createContext({});
const OTPInput = ({ value: uncheckedValue, onChange: uncheckedOnChange, maxLength, textAlign = "left", pattern, placeholder, inputMode = "numeric", onComplete, pushPasswordManagerStrategy = "increase-width", pasteTransformer, containerClassName, noScriptCSSFallback = NOSCRIPT_CSS_FALLBACK, render, children, ...props }) => {
	const [internalValue, setInternalValue] = useState(typeof props.defaultValue === "string" ? props.defaultValue : "");
	const value = uncheckedValue ?? internalValue;
	const previousValue = usePrevious(value);
	const onChange = (newValue) => {
		uncheckedOnChange?.(newValue);
		setInternalValue(newValue);
	};
	const regexp = pattern !== void 0 ? typeof pattern === "string" ? new RegExp(pattern) : pattern : null;
	/** useRef */
	const inputRef = useRef(null);
	const containerRef = useRef(null);
	const initialLoadRef = useRef({
		value,
		onChange,
		isIOS: typeof window !== "undefined" && window?.CSS?.supports?.("-webkit-touch-callout", "none")
	});
	const inputMetadataRef = useRef({ prev: [
		inputRef.current?.selectionStart ?? null,
		inputRef.current?.selectionEnd ?? null,
		inputRef.current?.selectionDirection ?? "none"
	] });
	useEffect(() => {
		const input = inputRef.current;
		const container = containerRef.current;
		if (!input || !container) return;
		if (initialLoadRef.current.value !== input.value) initialLoadRef.current.onChange(input.value);
		inputMetadataRef.current.prev = [
			input.selectionStart,
			input.selectionEnd,
			input.selectionDirection ?? "none"
		];
		const onDocumentSelectionChange = () => {
			if (document.activeElement !== input) {
				setMirrorSelectionStart(null);
				setMirrorSelectionEnd(null);
				return;
			}
			const _s = input.selectionStart;
			const _e = input.selectionEnd;
			const _dir = input.selectionDirection;
			const _ml = input.maxLength;
			const _val = input.value;
			const _prev = inputMetadataRef.current.prev;
			let start = -1;
			let end = -1;
			let direction = _dir ?? "none";
			if (_val.length !== 0 && _s !== null && _e !== null) {
				const isSingleCaret = _s === _e;
				const isInsertMode = _s === _val.length && _val.length < _ml;
				if (isSingleCaret && !isInsertMode) {
					const c = _s;
					if (c === 0) {
						start = 0;
						end = 1;
						direction = "forward";
					} else if (c === _ml) {
						start = c - 1;
						end = c;
						direction = "backward";
					} else if (_ml > 1 && _val.length > 1) {
						let offset = 0;
						if (_prev[0] !== null && _prev[1] !== null) {
							direction = c < _prev[1] ? "backward" : "forward";
							const wasPreviouslyInserting = _prev[0] === _prev[1] && _prev[0] < _ml;
							if (direction === "backward" && !wasPreviouslyInserting) offset = -1;
						}
						start = offset + c;
						end = offset + c + 1;
					}
				}
				if (start !== -1 && end !== -1 && start !== end) inputRef.current?.setSelectionRange(start, end, direction);
			}
			const s = start !== -1 ? start : _s;
			const e = end !== -1 ? end : _e;
			const dir = direction;
			setMirrorSelectionStart(s);
			setMirrorSelectionEnd(e);
			inputMetadataRef.current.prev = [
				s,
				e,
				dir
			];
		};
		document.addEventListener("selectionchange", onDocumentSelectionChange, { capture: true });
		onDocumentSelectionChange();
		if (document.activeElement === input) setIsFocused(true);
		if (!document.getElementById("input-otp-style")) {
			const styleEl = document.createElement("style");
			styleEl.id = "input-otp-style";
			document.head.appendChild(styleEl);
			if (styleEl.sheet) {
				const autofillStyles = "background: transparent !important; color: transparent !important; border-color: transparent !important; opacity: 0 !important; box-shadow: none !important; -webkit-box-shadow: none !important; -webkit-text-fill-color: transparent !important;";
				safeInsertRule(styleEl.sheet, "[data-input-otp]::selection { background: transparent !important; color: transparent !important; }");
				safeInsertRule(styleEl.sheet, `[data-input-otp]:autofill { ${autofillStyles} }`);
				safeInsertRule(styleEl.sheet, `[data-input-otp]:-webkit-autofill { ${autofillStyles} }`);
				safeInsertRule(styleEl.sheet, `@supports (-webkit-touch-callout: none) { [data-input-otp] { letter-spacing: -.6em !important; font-weight: 100 !important; font-stretch: ultra-condensed; font-optical-sizing: none !important; left: -1px !important; right: 1px !important; } }`);
				safeInsertRule(styleEl.sheet, `[data-input-otp] + * { pointer-events: all !important; }`);
			}
		}
		const updateRootHeight = () => {
			if (container) container.style.setProperty("--root-height", `${input.clientHeight}px`);
		};
		updateRootHeight();
		const resizeObserver = new ResizeObserver(updateRootHeight);
		resizeObserver.observe(input);
		return () => {
			document.removeEventListener("selectionchange", onDocumentSelectionChange, { capture: true });
			resizeObserver.disconnect();
		};
	}, []);
	/** Mirrors for UI rendering purpose only */
	const [isHoveringInput, setIsHoveringInput] = useState(false);
	const [isFocused, setIsFocused] = useState(false);
	const [mirrorSelectionStart, setMirrorSelectionStart] = useState(null);
	const [mirrorSelectionEnd, setMirrorSelectionEnd] = useState(null);
	/** Effects */
	useEffect(() => {
		syncTimeouts(() => {
			inputRef.current?.dispatchEvent(new Event("input"));
			const s = inputRef.current?.selectionStart ?? null;
			const e = inputRef.current?.selectionEnd ?? null;
			const dir = inputRef.current?.selectionDirection ?? "none";
			if (s !== null && e !== null) {
				setMirrorSelectionStart(s);
				setMirrorSelectionEnd(e);
				inputMetadataRef.current.prev = [
					s,
					e,
					dir
				];
			}
		});
	}, [value, isFocused]);
	useEffect(() => {
		if (previousValue === void 0) return;
		if (value !== previousValue && previousValue.length < maxLength && value.length === maxLength) onComplete?.(value);
	}, [
		maxLength,
		onComplete,
		previousValue,
		value
	]);
	const pwmb = usePasswordManagerBadge({
		containerRef,
		inputRef,
		pushPasswordManagerStrategy,
		isFocused
	});
	/** Event handlers */
	const _changeListener = (e) => {
		const newValue = e.currentTarget.value.slice(0, maxLength);
		if (newValue.length > 0 && regexp && !regexp.test(newValue)) {
			e.preventDefault();
			return;
		}
		if (typeof previousValue === "string" && newValue.length < previousValue.length) document.dispatchEvent(new Event("selectionchange"));
		onChange(newValue);
	};
	const _focusListener = () => {
		if (inputRef.current) {
			const start = Math.min(inputRef.current.value.length, maxLength - 1);
			const end = inputRef.current.value.length;
			inputRef.current?.setSelectionRange(start, end);
			setMirrorSelectionStart(start);
			setMirrorSelectionEnd(end);
		}
		setIsFocused(true);
	};
	const _pasteListener = (e) => {
		const input = inputRef.current;
		if (!pasteTransformer && (!initialLoadRef.current.isIOS || !e.clipboardData || !input)) return;
		const _content = e.clipboardData.getData("text/plain");
		const content = pasteTransformer ? pasteTransformer(_content) : _content;
		e.preventDefault();
		const start = inputRef.current?.selectionStart;
		const end = inputRef.current?.selectionEnd;
		const newValue = (start !== end ? value.slice(0, start ?? 0) + content + value.slice(end ?? 0) : value.slice(0, start ?? 0) + content + value.slice(start ?? 0)).slice(0, maxLength);
		if (newValue.length > 0 && regexp && !regexp.test(newValue)) return;
		if (input) {
			input.value = newValue;
			onChange(newValue);
			const _start = Math.min(newValue.length, maxLength - 1);
			const _end = newValue.length;
			input.setSelectionRange(_start, _end);
			setMirrorSelectionStart(_start);
			setMirrorSelectionEnd(_end);
		}
	};
	/** Styles */
	const rootStyle = {
		position: "relative",
		cursor: props.disabled ? "default" : "text",
		userSelect: "none",
		WebkitUserSelect: "none",
		pointerEvents: "none"
	};
	const inputStyle = {
		position: "absolute",
		inset: 0,
		width: pwmb.willPushPWMBadge ? `calc(100% + ${pwmb.PWM_BADGE_SPACE_WIDTH})` : "100%",
		clipPath: pwmb.willPushPWMBadge ? `inset(0 ${pwmb.PWM_BADGE_SPACE_WIDTH} 0 0)` : void 0,
		height: "100%",
		display: "flex",
		textAlign,
		opacity: "1",
		color: "transparent",
		pointerEvents: "all",
		background: "transparent",
		caretColor: "transparent",
		border: "0 solid transparent",
		outline: "0 solid transparent",
		boxShadow: "none",
		lineHeight: "1",
		letterSpacing: "-.5em",
		fontSize: "var(--root-height)",
		fontFamily: "monospace",
		zIndex: -1,
		fontVariantNumeric: "tabular-nums"
	};
	/** Rendering */
	const renderedInput = /* @__PURE__ */ jsx("input", {
		autoComplete: props.autoComplete || "one-time-code",
		...props,
		"data-input-otp": true,
		"data-input-otp-placeholder-shown": value.length === 0 || void 0,
		"data-input-otp-mss": mirrorSelectionStart,
		"data-input-otp-mse": mirrorSelectionEnd,
		inputMode,
		pattern: regexp?.source,
		"aria-placeholder": placeholder,
		style: inputStyle,
		maxLength,
		value,
		ref: inputRef,
		onPaste: (e) => {
			_pasteListener(e);
			props.onPaste?.(e);
		},
		onChange: _changeListener,
		onMouseOver: (e) => {
			setIsHoveringInput(true);
			props.onMouseOver?.(e);
		},
		onMouseLeave: (e) => {
			setIsHoveringInput(false);
			props.onMouseLeave?.(e);
		},
		onFocus: (e) => {
			_focusListener();
			props.onFocus?.(e);
		},
		onBlur: (e) => {
			setIsFocused(false);
			props.onBlur?.(e);
		}
	});
	const setSelection = (index) => {
		const input = inputRef.current;
		if (!input || props.disabled) return;
		const clampedIndex = Math.max(0, Math.min(index, maxLength - 1));
		if (document.activeElement !== input) input.focus();
		const hasChar = value[clampedIndex] !== void 0;
		const start = clampedIndex;
		const end = hasChar ? clampedIndex + 1 : clampedIndex;
		input.setSelectionRange(start, end);
		setMirrorSelectionStart(start);
		setMirrorSelectionEnd(end);
		setIsFocused(true);
	};
	const contextValue = {
		slots: Array.from({ length: maxLength }).map((_, slotIdx) => {
			const isActive = isFocused && mirrorSelectionStart !== null && mirrorSelectionEnd !== null && (mirrorSelectionStart === mirrorSelectionEnd && slotIdx === mirrorSelectionStart || slotIdx >= mirrorSelectionStart && slotIdx < mirrorSelectionEnd);
			const char = value[slotIdx] !== void 0 ? value[slotIdx] : null;
			return {
				char,
				placeholderChar: value[0] !== void 0 ? null : placeholder?.[slotIdx] ?? null,
				isActive,
				hasFakeCaret: isActive && char === null
			};
		}),
		isFocused,
		isHovering: !props.disabled && isHoveringInput,
		setSelection
	};
	const renderedChildren = render !== void 0 ? render(contextValue) : /* @__PURE__ */ jsx(OTPInputContext.Provider, {
		value: contextValue,
		children
	});
	return /* @__PURE__ */ jsxs(Fragment$1, { children: [noScriptCSSFallback !== null && /* @__PURE__ */ jsx("noscript", { children: /* @__PURE__ */ jsx("style", { children: noScriptCSSFallback }) }), /* @__PURE__ */ jsxs("div", {
		ref: containerRef,
		"data-input-otp-container": true,
		style: rootStyle,
		className: containerClassName,
		children: [renderedChildren, /* @__PURE__ */ jsx("div", {
			style: {
				position: "absolute",
				inset: 0
			},
			children: renderedInput
		})]
	})] });
};
const safeInsertRule = (sheet, rule) => {
	try {
		sheet.insertRule(rule);
	} catch {
		console.error("input-otp could not insert CSS rule:", rule);
	}
};
const NOSCRIPT_CSS_FALLBACK = `
[data-input-otp] {
  --nojs-bg: white !important;
  --nojs-fg: black !important;

  background-color: var(--nojs-bg) !important;
  color: var(--nojs-fg) !important;
  caret-color: var(--nojs-fg) !important;
  letter-spacing: .25em !important;
  text-align: center !important;
  border: 1px solid var(--nojs-fg) !important;
  border-radius: 4px !important;
  width: 100% !important;
}
@media (prefers-color-scheme: dark) {
  [data-input-otp] {
    --nojs-bg: black !important;
    --nojs-fg: white !important;
  }
}`;

//#endregion
export { OTPInput, OTPInputContext, usePasswordManagerBadge, usePrevious };
//# sourceMappingURL=Input.mjs.map