/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-f1f3d22 | Cube Dev Team */
import { processTokens, stringifyTokens } from "./utils/process-tokens.js";
import { useStyles } from "./hooks/useStyles.js";
import { BASE_STYLES } from "./styles/list.js";
import { getDisplayName } from "./utils/get-display-name.js";
import { mergeStyles } from "./utils/merge-styles.js";
import { _modAttrs } from "./utils/mod-attrs.js";
import { createElement, forwardRef, useMemo } from "react";
import { isValidElementType } from "react-is";

//#region src/tasty/tasty.tsx
/**
* Precalculated entries for performance optimization
*/
const IS_PROPERTIES_ENTRIES = Object.entries({
	isDisabled: "disabled",
	isHidden: "hidden",
	isChecked: "checked"
});
/**
* Helper function to handle is* properties consistently
* Transforms is* props to HTML attributes and adds corresponding data-* attributes
*/
function handleIsProperties(props) {
	for (const [isProperty, targetAttribute] of IS_PROPERTIES_ENTRIES) {
		if (isProperty in props) {
			props[targetAttribute] = props[isProperty];
			delete props[isProperty];
		}
		const dataAttribute = `data-${targetAttribute}`;
		if (!(dataAttribute in props) && props[targetAttribute]) props[dataAttribute] = "";
	}
}
/**
* Creates a sub-element component for compound component patterns.
* Sub-elements are lightweight components with data-element attribute for CSS targeting.
*/
function createSubElement(elementName, definition) {
	const config = typeof definition === "string" ? { as: definition } : definition;
	const tag = config.as ?? "div";
	const defaultQa = config.qa;
	const defaultQaVal = config.qaVal;
	const SubElement = forwardRef((props, ref) => {
		const { qa, qaVal, mods, tokens, isDisabled, isHidden, isChecked, className, style, ...htmlProps } = props;
		let modProps;
		if (mods) modProps = _modAttrs(mods);
		const tokenStyle = tokens ? processTokens(tokens) : void 0;
		let mergedStyle;
		if (tokenStyle || style) mergedStyle = tokenStyle && style ? {
			...tokenStyle,
			...style
		} : tokenStyle ?? style;
		const elementProps = {
			"data-element": elementName,
			"data-qa": qa ?? defaultQa,
			"data-qaval": qaVal ?? defaultQaVal,
			...modProps || {},
			...htmlProps,
			className,
			style: mergedStyle,
			isDisabled,
			isHidden,
			isChecked,
			ref
		};
		handleIsProperties(elementProps);
		if (elementProps["data-qa"] === void 0) delete elementProps["data-qa"];
		if (elementProps["data-qaval"] === void 0) delete elementProps["data-qaval"];
		return createElement(tag, elementProps);
	});
	SubElement.displayName = `SubElement(${elementName})`;
	return SubElement;
}
function tasty(Component, options) {
	if (isValidElementType(Component)) return tastyWrap(Component, options);
	return tastyElement(Component);
}
function tastyWrap(Component, options) {
	let { as: extendTag, element: extendElement, ...defaultProps } = options ?? {};
	let propsWithStyles = ["styles"].concat(Object.keys(defaultProps).filter((prop) => prop.endsWith("Styles")));
	const _WrappedComponent = forwardRef((props, ref) => {
		const { as, element, ...restProps } = props;
		const mergedStylesMap = useMemo(() => {
			return propsWithStyles.reduce((map, prop) => {
				const restValue = restProps[prop];
				const defaultValue = defaultProps[prop];
				if (restValue != null && defaultValue != null) map[prop] = mergeStyles(defaultValue, restValue);
				else map[prop] = restValue ?? defaultValue;
				return map;
			}, {});
		}, [propsWithStyles.map((prop) => props[prop])]);
		return createElement(Component, {
			...defaultProps,
			...restProps,
			...mergedStylesMap,
			as: as ?? extendTag,
			element: element || extendElement,
			ref
		});
	});
	_WrappedComponent.displayName = `TastyWrappedComponent(${getDisplayName(Component, defaultProps.qa ?? extendTag ?? "Anonymous")})`;
	return _WrappedComponent;
}
function tastyElement(tastyOptions) {
	let { as: originalAs = "div", element: defaultElement, styles: defaultStyles, styleProps, variants, tokens: defaultTokens, elements, ...defaultProps } = tastyOptions;
	let variantStylesMap;
	if (variants) {
		variantStylesMap = Object.entries(variants).reduce((map, [variant, variantStyles]) => {
			map[variant] = mergeStyles(defaultStyles, variantStyles);
			return map;
		}, {});
		if (!variantStylesMap["default"]) variantStylesMap["default"] = defaultStyles;
	}
	let { qa: defaultQa, qaVal: defaultQaVal, ...otherDefaultProps } = defaultProps ?? {};
	const _TastyComponent = forwardRef((allProps, ref) => {
		let { as, styles, variant, mods, element, qa, qaVal, className: userClassName, tokens, style, ...otherProps } = allProps;
		let propStyles = null;
		const propsToCheck = styleProps ? styleProps.concat(BASE_STYLES) : BASE_STYLES;
		for (const prop of propsToCheck) {
			const key = prop;
			if (!propStyles) propStyles = {};
			if (key in otherProps) {
				propStyles[key] = otherProps[key];
				delete otherProps[key];
			}
		}
		if (!styles || styles && Object.keys(styles).length === 0) styles = void 0;
		const baseStyles = variantStylesMap ? variantStylesMap[variant || "default"] ?? variantStylesMap["default"] : defaultStyles;
		const { className: stylesClassName } = useStyles(useMemo(() => {
			const hasStyles = styles && Object.keys(styles).length > 0;
			const hasPropStyles = propStyles && Object.keys(propStyles).length > 0;
			if (!hasStyles && !hasPropStyles) return baseStyles;
			return mergeStyles(baseStyles, styles, propStyles);
		}, [
			baseStyles,
			styles,
			propStyles
		]));
		const mergedTokens = useMemo(() => {
			if (!defaultTokens && !tokens) return void 0;
			if (!defaultTokens) return tokens;
			if (!tokens) return defaultTokens;
			return {
				...defaultTokens,
				...tokens
			};
		}, [stringifyTokens(tokens)]);
		const processedTokenStyle = useMemo(() => {
			return processTokens(mergedTokens);
		}, [mergedTokens]);
		const mergedStyle = useMemo(() => {
			if (!processedTokenStyle && !style) return void 0;
			if (!processedTokenStyle) return style;
			if (!style) return processedTokenStyle;
			return {
				...processedTokenStyle,
				...style
			};
		}, [processedTokenStyle, style]);
		let modProps;
		if (mods) modProps = _modAttrs(mods);
		const finalClassName = [userClassName || "", stylesClassName].filter(Boolean).join(" ");
		const elementProps = {
			"data-element": element || defaultElement,
			"data-qa": qa || defaultQa,
			"data-qaval": qaVal || defaultQaVal,
			...otherDefaultProps,
			...modProps || {},
			...otherProps,
			className: finalClassName,
			style: mergedStyle,
			ref
		};
		handleIsProperties(elementProps);
		return createElement(as ?? originalAs, elementProps);
	});
	_TastyComponent.displayName = `TastyComponent(${defaultProps.qa || originalAs})`;
	if (elements) {
		const subElements = Object.entries(elements).reduce((acc, [name, definition]) => {
			acc[name] = createSubElement(name, definition);
			return acc;
		}, {});
		return Object.assign(_TastyComponent, subElements);
	}
	return _TastyComponent;
}
const Element = tasty({});

//#endregion
export { Element, tasty };
//# sourceMappingURL=tasty.js.map