/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-b04eed0 | Cube Dev Team */
import { extractStyles } from "../../../utils/styles.js";
import { useCombinedRefs } from "../../../utils/react/useCombinedRefs.js";
import { Provider, useProviderProps } from "../../../provider.js";
import { timeout } from "../../../utils/promise.js";
import { useForm } from "./use-form.js";
import { CONTAINER_STYLES, filterBaseProps, tasty } from "@tenphi/tasty";
import { createContext, forwardRef, useContext, useRef } from "react";
import { jsx } from "react/jsx-runtime";
import { useDOMRef } from "@react-spectrum/utils";

//#region src/components/form/Form/Form.tsx
const FormContext = createContext({});
const FormElement = tasty({
	as: "form",
	qa: "Form",
	styles: {
		display: {
			"": "block",
			horizontal: "flex"
		},
		flow: {
			"": "column",
			horizontal: "row"
		},
		placeItems: {
			"": "initial",
			horizontal: "center"
		},
		gap: "2x",
		"$label-width": "25x"
	}
});
function useFormProps(props) {
	return {
		...useContext(FormContext),
		...props
	};
}
const formPropNames = new Set([
	"action",
	"autoComplete",
	"encType",
	"method",
	"target"
]);
function Form(props, ref) {
	props = useProviderProps(props);
	let { qa, name, children, labelPosition, orientation, necessityIndicator, isDisabled, isReadOnly, validationState, labelStyles, validateTrigger, showValid, defaultValues, onValuesChange, requiredMark = true, form, labelWidth, onSubmit, onSubmitFailed, ...otherProps } = props;
	const defaultValuesRef = useRef(defaultValues);
	const firstRunRef = useRef(true);
	const isHorizontal = orientation === "horizontal";
	if (!orientation) orientation = "vertical";
	if (!labelPosition) labelPosition = isHorizontal ? "side" : "top";
	if (!labelWidth) labelWidth = isHorizontal ? "auto" : void 0;
	ref = useCombinedRefs(ref);
	let onSubmitCallback;
	if ((onSubmit || onSubmitFailed) && !otherProps.action) onSubmitCallback = async (e) => {
		if (e && e?.preventDefault) {
			e && e?.preventDefault && e?.preventDefault();
			e && e?.stopPropagation && e?.stopPropagation();
			if (e.nativeEvent) {
				const evt = e.nativeEvent;
				if (evt.submitter && evt.submitter.getAttribute("type") !== "submit") return;
			}
		}
		if (!form || form.isSubmitting) return;
		form.submitError = null;
		form.setSubmitting(true);
		try {
			try {
				await form.validateFields();
			} catch (e) {
				form?.setSubmitting(false);
				return;
			}
			await timeout();
			await onSubmit?.(form.getFormData());
		} catch (e) {
			await timeout();
			form.submitError = e;
			onSubmitFailed?.(e);
			if (e instanceof Error) throw e;
		} finally {
			form?.setSubmitting(false);
		}
	};
	[form] = useForm(form, ref && ref.current, {
		onSubmit: onSubmitCallback,
		onValuesChange
	});
	let styles = extractStyles(otherProps, CONTAINER_STYLES);
	if (labelWidth) styles["$label-width"] = labelWidth;
	let domRef = useDOMRef(ref);
	let ctx = {
		labelPosition,
		labelStyles,
		orientation,
		necessityIndicator,
		validateTrigger,
		requiredMark,
		showValid,
		form,
		submitError: form.submitError,
		idPrefix: name
	};
	if (firstRunRef.current && form) {
		if (defaultValues) {
			form.setInitialFieldsValue(defaultValues);
			form.resetFields(void 0, true);
			firstRunRef.current = false;
		}
	}
	if (defaultValuesRef.current !== defaultValues) {
		form?.setInitialFieldsValue(defaultValues ?? {});
		defaultValuesRef.current = defaultValues;
	}
	return /* @__PURE__ */ jsx(FormElement, {
		...filterBaseProps(otherProps, { propNames: formPropNames }),
		ref: domRef,
		noValidate: true,
		qa,
		styles,
		mods: {
			"has-sider": labelPosition === "side",
			"has-split": labelPosition === "split",
			horizontal: isHorizontal
		},
		onSubmit: onSubmitCallback,
		children: /* @__PURE__ */ jsx(FormContext.Provider, {
			value: ctx,
			children: /* @__PURE__ */ jsx(Provider, {
				insideForm: true,
				isDisabled,
				isReadOnly,
				validationState,
				children
			})
		})
	});
}
/**
* Forms allow users to enter data that can be submitted while providing alignment and styling for form fields.
*/
const _Form = forwardRef(Form);
_Form.displayName = "Form";

//#endregion
export { FormContext, _Form, useFormProps };
//# sourceMappingURL=Form.js.map