import { S as useToNumber } from "./dist-DKc2ivHS.js";
import { S as useVModel } from "./dist-9-XTMhb-.js";
import { t as useDefaults } from "./useDefaults-BzP4qZBu.js";
import { t as useId$1 } from "./useId-Fh-Arhb7.js";
import { a as useDirection, c as getActiveElement, l as createContext, n as usePrimitiveElement, r as Primitive } from "./VisuallyHidden-BYzyjJiY.js";
import { n as useComposing, t as VisuallyHiddenInput_default } from "./VisuallyHiddenInput-CUrc8XXa.js";
import { t as useForwardExpose } from "./useForwardExpose-DDvk7mir.js";
import { t as BFormInput_default } from "./BFormInput-BwvdFGDu.js";
import { Fragment, computed, createBlock, createElementBlock, createVNode, defineComponent, mergeModels, mergeProps, nextTick, normalizeClass, onMounted, onUnmounted, openBlock, ref, renderList, renderSlot, toRefs, unref, useModel, watch, withCtx, withKeys } from "vue";
//#region ../../node_modules/.pnpm/reka-ui@2.10.3_vue@3.5.41_typescript@5.9.3_/node_modules/reka-ui/dist/shared/useArrowNavigation.js
var ignoredElement = ["INPUT", "TEXTAREA"];
/**
* Allow arrow navigation for every html element with data-reka-collection-item tag
*
* @param e               Keyboard event
* @param currentElement  Event initiator element or any element that wants to handle the navigation
* @param parentElement   Parent element where contains all the collection items, this will collect every item to be used when nav
* @param options         further options
* @returns               the navigated html element or null if none
*/
function useArrowNavigation(e, currentElement, parentElement, options = {}) {
	if (!currentElement || options.enableIgnoredElement && ignoredElement.includes(currentElement.nodeName)) return null;
	const { arrowKeyOptions = "both", attributeName = "[data-reka-collection-item]", itemsArray = [], loop = true, dir = "ltr", preventScroll = true, focus = false } = options;
	const [right, left, up, down, home, end] = [
		e.key === "ArrowRight",
		e.key === "ArrowLeft",
		e.key === "ArrowUp",
		e.key === "ArrowDown",
		e.key === "Home",
		e.key === "End"
	];
	const goingVertical = up || down;
	const goingHorizontal = right || left;
	if (!home && !end && (!goingVertical && !goingHorizontal || arrowKeyOptions === "vertical" && goingHorizontal || arrowKeyOptions === "horizontal" && goingVertical)) return null;
	const allCollectionItems = parentElement ? Array.from(parentElement.querySelectorAll(attributeName)) : itemsArray;
	if (!allCollectionItems.length) return null;
	if (preventScroll) e.preventDefault();
	let item = null;
	if (goingHorizontal || goingVertical) item = findNextFocusableElement(allCollectionItems, currentElement, {
		goForward: goingVertical ? down : dir === "ltr" ? right : left,
		loop
	});
	else if (home) item = allCollectionItems.at(0) || null;
	else if (end) item = allCollectionItems.at(-1) || null;
	if (focus) item?.focus();
	return item;
}
/**
* Recursive function to find the next focusable element to avoid disabled elements
*
* @param elements Elements to navigate
* @param currentElement Current active element
* @param options
* @returns next focusable element
*/
function findNextFocusableElement(elements, currentElement, options, iterations = !elements.includes(currentElement) ? elements.length + 1 : elements.length) {
	if (--iterations === 0) return null;
	const index = elements.indexOf(currentElement);
	let newIndex;
	if (index === -1) newIndex = options.goForward ? 0 : elements.length - 1;
	else newIndex = options.goForward ? index + 1 : index - 1;
	if (!options.loop && (newIndex < 0 || newIndex >= elements.length)) return null;
	const candidate = elements[(newIndex + elements.length) % elements.length];
	if (!candidate) return null;
	if (candidate.hasAttribute("disabled") && candidate.getAttribute("disabled") !== "false") return findNextFocusableElement(elements, candidate, options, iterations);
	return candidate;
}
//#endregion
//#region ../../node_modules/.pnpm/reka-ui@2.10.3_vue@3.5.41_typescript@5.9.3_/node_modules/reka-ui/dist/PinInput/PinInputRoot.js
var [injectPinInputRootContext, providePinInputRootContext] = /*#__PURE__*/ createContext("PinInputRoot");
var PinInputRoot_default = /* @__PURE__ */ defineComponent({
	inheritAttrs: false,
	__name: "PinInputRoot",
	props: {
		modelValue: {
			type: null,
			required: false
		},
		defaultValue: {
			type: null,
			required: false
		},
		placeholder: {
			type: String,
			required: false,
			default: ""
		},
		mask: {
			type: Boolean,
			required: false
		},
		otp: {
			type: Boolean,
			required: false
		},
		type: {
			type: null,
			required: false,
			default: "text"
		},
		dir: {
			type: String,
			required: false
		},
		disabled: {
			type: Boolean,
			required: false
		},
		id: {
			type: String,
			required: false
		},
		asChild: {
			type: Boolean,
			required: false
		},
		as: {
			type: null,
			required: false
		},
		name: {
			type: String,
			required: false
		},
		required: {
			type: Boolean,
			required: false
		}
	},
	emits: ["update:modelValue", "complete"],
	setup(__props, { emit: __emit }) {
		const props = __props;
		const emits = __emit;
		const { mask, otp, placeholder, type, disabled, dir: propDir } = toRefs(props);
		const { forwardRef } = useForwardExpose();
		const dir = useDirection(propDir);
		const modelValue = useVModel(props, "modelValue", emits, {
			defaultValue: props.defaultValue ?? [],
			passive: true,
			deep: true
		});
		const currentModelValue = computed(() => Array.isArray(modelValue.value) ? [...modelValue.value] : []);
		const inputElements = ref(/* @__PURE__ */ new Set());
		function onInputElementChange(el) {
			inputElements.value.add(el);
		}
		const isNumericMode = computed(() => props.type === "number");
		const isCompleted = computed(() => {
			return currentModelValue.value.filter((i) => !!i || isNumericMode.value && i === 0).length === inputElements.value.size;
		});
		watch(modelValue, () => {
			if (isCompleted.value) emits("complete", modelValue.value);
		}, { deep: true });
		providePinInputRootContext({
			modelValue,
			currentModelValue,
			mask,
			otp,
			placeholder,
			type,
			dir,
			disabled,
			isCompleted,
			inputElements,
			onInputElementChange,
			isNumericMode
		});
		return (_ctx, _cache) => {
			return openBlock(), createBlock(unref(Primitive), mergeProps(_ctx.$attrs, {
				ref: unref(forwardRef),
				dir: unref(dir),
				"data-complete": isCompleted.value ? "" : void 0,
				"data-disabled": unref(disabled) ? "" : void 0
			}), {
				default: withCtx(() => [renderSlot(_ctx.$slots, "default", { modelValue: unref(modelValue) }), createVNode(VisuallyHiddenInput_default, {
					id: _ctx.id,
					as: "input",
					feature: "focusable",
					tabindex: "-1",
					value: currentModelValue.value.join(""),
					name: _ctx.name ?? "",
					disabled: unref(disabled),
					required: _ctx.required,
					onFocus: _cache[0] || (_cache[0] = ($event) => Array.from(inputElements.value)?.[0]?.focus())
				}, null, 8, [
					"id",
					"value",
					"name",
					"disabled",
					"required"
				])]),
				_: 3
			}, 16, [
				"dir",
				"data-complete",
				"data-disabled"
			]);
		};
	}
});
//#endregion
//#region ../../node_modules/.pnpm/reka-ui@2.10.3_vue@3.5.41_typescript@5.9.3_/node_modules/reka-ui/dist/PinInput/PinInputInput.js
var PinInputInput_default = /* @__PURE__ */ defineComponent({
	__name: "PinInputInput",
	props: {
		index: {
			type: Number,
			required: true
		},
		disabled: {
			type: Boolean,
			required: false
		},
		asChild: {
			type: Boolean,
			required: false
		},
		as: {
			type: null,
			required: false,
			default: "input"
		}
	},
	setup(__props) {
		const props = __props;
		const context = injectPinInputRootContext();
		const inputElements = computed(() => [...context.inputElements.value]);
		const currentValue = computed(() => context.currentModelValue.value[props.index]);
		const disabled = computed(() => props.disabled || context.disabled.value);
		const isOtpMode = computed(() => context.otp.value);
		const isPasswordMode = computed(() => context.mask.value);
		const NUMBER_REG = /^\d*$/;
		const NON_NUMBER_REG = /\D/g;
		const { primitiveElement, currentElement } = usePrimitiveElement();
		const { isComposing, handleCompositionStart, handleCompositionEnd } = useComposing((event) => {
			const target = event.target;
			const value = event.data || target.value;
			if (context.isNumericMode.value) {
				const filtered = value.replace(NON_NUMBER_REG, "");
				if (!filtered) {
					target.value = "";
					return;
				}
				if (filtered.length > 1) {
					handleMultipleCharacter(filtered);
					return;
				}
				target.value = filtered;
				updateModelValueAt(props.index, filtered);
				const nextEl$1 = inputElements.value[props.index + 1];
				if (nextEl$1) nextEl$1.focus();
				return;
			}
			if (value.length > 1) {
				handleMultipleCharacter(value);
				return;
			}
			target.value = value;
			updateModelValueAt(props.index, value);
			const nextEl = inputElements.value[props.index + 1];
			if (nextEl) nextEl.focus();
		});
		function handleInput(event) {
			if (isComposing.value || event.isComposing) return;
			const target = event.target;
			if ((event.data?.length ?? 0) > 1) {
				handleMultipleCharacter(target.value);
				return;
			}
			if (context.isNumericMode.value && !NUMBER_REG.test(target.value)) {
				target.value = target.value.replace(NON_NUMBER_REG, "");
				return;
			}
			target.value = event.data || target.value.slice(-1);
			updateModelValueAt(props.index, target.value);
			const nextEl = inputElements.value[props.index + 1];
			if (nextEl) nextEl.focus();
		}
		function updatePlaceholder() {
			nextTick(() => {
				const target = currentElement.value;
				if (!target) return;
				if (!target.value && target === getActiveElement()) target.placeholder = "";
				else target.placeholder = context.placeholder.value;
			});
		}
		function handleKeydown(event) {
			if (isComposing.value || event.isComposing) return;
			useArrowNavigation(event, getActiveElement(), void 0, {
				itemsArray: inputElements.value,
				focus: true,
				loop: false,
				arrowKeyOptions: "horizontal",
				dir: context.dir.value
			});
		}
		function handleBackspace(event) {
			event.preventDefault();
			if (event.target.value) updateModelValueAt(props.index, "");
			else {
				const prevEl = inputElements.value[props.index - 1];
				if (prevEl) {
					prevEl.focus();
					updateModelValueAt(props.index - 1, "");
				}
			}
		}
		function handleDelete(event) {
			if (event.key === "Delete") {
				event.preventDefault();
				updateModelValueAt(props.index, "");
			}
		}
		function handleFocus(event) {
			if (context.otp.value) {
				const firstEmptyInputIdx = inputElements.value.findIndex((_, idx) => context.currentModelValue.value[idx] === "" || context.currentModelValue.value[idx] === void 0);
				if (firstEmptyInputIdx !== -1 && firstEmptyInputIdx < props.index) {
					inputElements.value[firstEmptyInputIdx].focus();
					return;
				}
			}
			event.target.setSelectionRange(1, 1);
			updatePlaceholder();
		}
		function handleBlur(event) {
			updatePlaceholder();
		}
		function handlePaste(event) {
			event.preventDefault();
			const clipboardData = event.clipboardData;
			if (!clipboardData) return;
			const rawValues = clipboardData.getData("text");
			handleMultipleCharacter(context.isNumericMode.value ? rawValues.replace(NON_NUMBER_REG, "") : rawValues);
		}
		function handleMultipleCharacter(values) {
			const tempModelValue = [...context.currentModelValue.value];
			const initialIndex = values.length >= inputElements.value.length ? 0 : props.index;
			const lastIndex = Math.min(initialIndex + values.length, inputElements.value.length);
			for (let i = initialIndex; i < lastIndex; i++) {
				const input = inputElements.value[i];
				const value = values[i - initialIndex];
				if (context.isNumericMode.value) {
					const num = Number.parseInt(value);
					if (Number.isNaN(num)) continue;
					tempModelValue[i] = num;
				} else tempModelValue[i] = value;
				input.focus();
			}
			context.modelValue.value = tempModelValue;
			inputElements.value[lastIndex]?.focus();
		}
		function removeTrailingEmptyStrings(input) {
			let i = input.length - 1;
			while (i >= 0 && input[i] === "") {
				input.pop();
				i--;
			}
			return input;
		}
		function updateModelValueAt(index, value) {
			const tempModelValue = [...context.currentModelValue.value];
			if (context.isNumericMode.value) {
				const num = +value;
				if (value === "" || isNaN(num)) delete tempModelValue[index];
				else tempModelValue[index] = num;
			} else tempModelValue[index] = value;
			context.modelValue.value = removeTrailingEmptyStrings(tempModelValue);
		}
		watch(currentValue, updatePlaceholder);
		onMounted(() => {
			context.onInputElementChange(currentElement.value);
		});
		onUnmounted(() => {
			context.inputElements?.value.delete(currentElement.value);
		});
		return (_ctx, _cache) => {
			return openBlock(), createBlock(unref(Primitive), {
				ref_key: "primitiveElement",
				ref: primitiveElement,
				autocapitalize: "none",
				as: _ctx.as,
				"as-child": _ctx.asChild,
				autocomplete: isOtpMode.value ? "one-time-code" : "false",
				type: isPasswordMode.value ? "password" : "text",
				inputmode: unref(context).isNumericMode.value ? "numeric" : "text",
				pattern: unref(context).isNumericMode.value ? "[0-9]*" : void 0,
				placeholder: unref(context).placeholder.value,
				value: currentValue.value,
				disabled: disabled.value,
				"data-disabled": disabled.value ? "" : void 0,
				"data-complete": unref(context).isCompleted.value ? "" : void 0,
				"aria-label": `pin input ${_ctx.index + 1} of ${inputElements.value.length}`,
				onInput: _cache[0] || (_cache[0] = ($event) => handleInput($event)),
				onKeydown: [
					withKeys(handleKeydown, [
						"left",
						"right",
						"up",
						"down",
						"home",
						"end"
					]),
					withKeys(handleBackspace, ["backspace"]),
					withKeys(handleDelete, ["delete"])
				],
				onFocus: handleFocus,
				onBlur: handleBlur,
				onPaste: handlePaste,
				onCompositionstart: unref(handleCompositionStart),
				onCompositionend: unref(handleCompositionEnd)
			}, {
				default: withCtx(() => [renderSlot(_ctx.$slots, "default")]),
				_: 3
			}, 8, [
				"as",
				"as-child",
				"autocomplete",
				"type",
				"inputmode",
				"pattern",
				"placeholder",
				"value",
				"disabled",
				"data-disabled",
				"data-complete",
				"aria-label",
				"onCompositionstart",
				"onCompositionend"
			]);
		};
	}
});
//#endregion
//#region src/components/BFormOtp/BFormOtp.vue?vue&type=script&setup=true&lang.ts
var lengthDefault = 6;
//#endregion
//#region src/components/BFormOtp/BFormOtp.vue
var BFormOtp_default = /* @__PURE__ */ defineComponent({
	__name: "BFormOtp",
	props: /*@__PURE__*/ mergeModels({
		ariaInvalid: {
			type: [Boolean, String],
			default: void 0
		},
		ariaLabel: { default: void 0 },
		autofocus: {
			type: Boolean,
			default: false
		},
		dir: { default: void 0 },
		disabled: {
			type: Boolean,
			default: false
		},
		form: { default: void 0 },
		id: { default: void 0 },
		length: { default: lengthDefault },
		mask: {
			type: Boolean,
			default: false
		},
		name: { default: void 0 },
		otp: {
			type: Boolean,
			default: false
		},
		placeholder: { default: "" },
		plaintext: {
			type: Boolean,
			default: false
		},
		readonly: {
			type: Boolean,
			default: false
		},
		required: {
			type: Boolean,
			default: false
		},
		separator: {},
		size: { default: void 0 },
		state: {
			type: [Boolean, null],
			default: null
		},
		type: { default: "text" }
	}, {
		"modelValue": { default: () => [] },
		"modelModifiers": {}
	}),
	emits: /*@__PURE__*/ mergeModels(["complete"], ["update:modelValue"]),
	setup(__props, { emit: __emit }) {
		const props = useDefaults(__props, "BFormOtp");
		const emit = __emit;
		const modelValue = useModel(__props, "modelValue");
		const computedId = useId$1(() => props.id);
		const lengthNumber = useToNumber(() => props.length, {
			nanToZero: true,
			method: "parseInt"
		});
		const computedLength = computed(() => lengthNumber.value > 0 ? lengthNumber.value : lengthDefault);
		const rootClasses = computed(() => [
			"b-form-otp",
			"d-flex",
			"gap-2",
			"align-items-center",
			{ [`b-form-otp-${props.size}`]: !!props.size }
		]);
		return (_ctx, _cache) => {
			return openBlock(), createBlock(unref(PinInputRoot_default), {
				id: unref(computedId),
				modelValue: modelValue.value,
				"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => modelValue.value = $event),
				class: normalizeClass(rootClasses.value),
				disabled: unref(props).disabled,
				dir: unref(props).dir,
				mask: unref(props).mask,
				name: unref(props).name,
				otp: unref(props).otp,
				placeholder: unref(props).placeholder,
				required: unref(props).required,
				type: unref(props).type,
				onComplete: _cache[1] || (_cache[1] = ($event) => emit("complete", $event))
			}, {
				default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(computedLength.value, (_, i) => {
					return openBlock(), createBlock(unref(PinInputInput_default), {
						key: i,
						index: i,
						disabled: unref(props).disabled,
						"as-child": ""
					}, {
						default: withCtx(() => [createVNode(BFormInput_default, {
							class: "b-form-otp-field",
							"aria-label": `${unref(props).ariaLabel || "Pin"} ${i + 1} of ${computedLength.value}`,
							"aria-invalid": unref(props).ariaInvalid,
							autofocus: unref(props).autofocus && i === 0,
							disabled: unref(props).disabled,
							form: unref(props).form,
							plaintext: unref(props).plaintext,
							readonly: unref(props).readonly,
							size: unref(props).size,
							state: unref(props).state
						}, null, 8, [
							"aria-label",
							"aria-invalid",
							"autofocus",
							"disabled",
							"form",
							"plaintext",
							"readonly",
							"size",
							"state"
						])]),
						_: 2
					}, 1032, ["index", "disabled"]);
				}), 128))]),
				_: 1
			}, 8, [
				"id",
				"modelValue",
				"class",
				"disabled",
				"dir",
				"mask",
				"name",
				"otp",
				"placeholder",
				"required",
				"type"
			]);
		};
	}
});
//#endregion
export { BFormOtp_default as t };

//# sourceMappingURL=BFormOtp-I1t8dqPS.js.map