/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-af8d194 | Cube Dev Team */
import { isDevEnv } from "../utils/is-dev-env.js";
import { alignStyle } from "./align.js";
import { borderStyle } from "./border.js";
import { createStyle } from "./createStyle.js";
import { colorStyle } from "./color.js";
import { displayStyle } from "./display.js";
import { fadeStyle } from "./fade.js";
import { fillStyle, svgFillStyle } from "./fill.js";
import { flowStyle } from "./flow.js";
import { gapStyle } from "./gap.js";
import { heightStyle } from "./height.js";
import { insetStyle } from "./inset.js";
import { justifyStyle } from "./justify.js";
import { marginStyle } from "./margin.js";
import { outlineStyle } from "./outline.js";
import { paddingStyle } from "./padding.js";
import { presetStyle } from "./preset.js";
import { radiusStyle } from "./radius.js";
import { resetStyle } from "./reset.js";
import { scrollbarStyle } from "./scrollbar.js";
import { shadowStyle } from "./shadow.js";
import { styledScrollbarStyle } from "./styledScrollbar.js";
import { transitionStyle } from "./transition.js";
import { widthStyle } from "./width.js";

//#region src/tasty/styles/predefined.ts
const devMode = isDevEnv();
const columnsConverter = (val) => {
	if (typeof val === "number") return "minmax(1px, 1fr) ".repeat(val).trim();
};
const rowsConverter = (val) => {
	if (typeof val === "number") return "auto ".repeat(val).trim();
};
const STYLE_HANDLER_MAP = {};
let initialHandlerMapSnapshot = null;
/**
* Capture a snapshot of the current STYLE_HANDLER_MAP.
* Called after predefine() to preserve built-in handler state.
*/
function captureInitialHandlerState() {
	initialHandlerMapSnapshot = {};
	for (const key of Object.keys(STYLE_HANDLER_MAP)) initialHandlerMapSnapshot[key] = [...STYLE_HANDLER_MAP[key]];
}
/**
* Reset STYLE_HANDLER_MAP to the initial built-in state.
* Called by resetConfig() to restore handlers after tests.
*/
function resetHandlers() {
	if (!initialHandlerMapSnapshot) return;
	for (const key of Object.keys(STYLE_HANDLER_MAP)) delete STYLE_HANDLER_MAP[key];
	for (const key of Object.keys(initialHandlerMapSnapshot)) STYLE_HANDLER_MAP[key] = [...initialHandlerMapSnapshot[key]];
}
function defineCustomStyle(names, handler) {
	let handlerWithLookup;
	if (typeof names === "function") {
		handlerWithLookup = names;
		names = handlerWithLookup.__lookupStyles;
	} else if (handler) handlerWithLookup = Object.assign(handler, { __lookupStyles: names });
	else {
		console.warn("CubeUIKit: incorrect custom style definition: ", names);
		return;
	}
	if (Array.isArray(names)) names.forEach((name) => {
		if (!STYLE_HANDLER_MAP[name]) STYLE_HANDLER_MAP[name] = [];
		STYLE_HANDLER_MAP[name].push(handlerWithLookup);
	});
}
function defineStyleAlias(styleName, cssStyleName, converter) {
	const styleHandler = createStyle(styleName, cssStyleName, converter);
	if (!STYLE_HANDLER_MAP[styleName]) STYLE_HANDLER_MAP[styleName] = [];
	STYLE_HANDLER_MAP[styleName].push(styleHandler);
}
function predefine() {
	defineStyleAlias("gridAreas", "grid-template-areas");
	defineStyleAlias("gridColumns", "grid-template-columns", columnsConverter);
	defineStyleAlias("gridRows", "grid-template-rows", rowsConverter);
	defineStyleAlias("gridTemplate", "grid-template", (val) => {
		if (typeof val !== "string") return;
		return val.split("/").map((s, i) => (i ? columnsConverter : rowsConverter)(s)).join("/");
	});
	[
		displayStyle,
		transitionStyle,
		resetStyle,
		fillStyle,
		svgFillStyle,
		widthStyle,
		marginStyle,
		gapStyle,
		flowStyle,
		colorStyle,
		heightStyle,
		radiusStyle,
		borderStyle,
		shadowStyle,
		paddingStyle,
		alignStyle,
		justifyStyle,
		presetStyle,
		outlineStyle,
		styledScrollbarStyle,
		scrollbarStyle,
		fadeStyle,
		insetStyle
	].forEach((handler) => defineCustomStyle(handler));
	captureInitialHandlerState();
	return {
		STYLE_HANDLER_MAP,
		defineCustomStyle,
		defineStyleAlias
	};
}
/**
* Normalize a handler definition to a StyleHandler with __lookupStyles.
* - Function only: lookup styles inferred from key name
* - [string, fn]: single lookup style
* - [string[], fn]: multiple lookup styles
*/
function normalizeHandlerDefinition(keyName, definition) {
	let handler;
	let lookupStyles;
	if (typeof definition === "function") {
		handler = definition;
		lookupStyles = [keyName];
	} else if (Array.isArray(definition)) {
		const [first, fn] = definition;
		if (typeof fn !== "function") throw new Error(`[Tasty] Invalid handler definition for "${keyName}". Tuple must have a function as the second element: [string, function] or [string[], function].`);
		handler = fn;
		if (typeof first === "string") lookupStyles = [first];
		else if (Array.isArray(first)) lookupStyles = first;
		else throw new Error(`[Tasty] Invalid handler definition for "${keyName}". First element must be a string or string array.`);
	} else throw new Error(`[Tasty] Invalid handler definition for "${keyName}". Expected function, [string, function], or [string[], function].`);
	validateHandler(keyName, handler, lookupStyles);
	const wrappedHandler = ((props) => handler(props));
	wrappedHandler.__lookupStyles = lookupStyles;
	return wrappedHandler;
}
/**
* Validate a handler definition in development mode.
*/
function validateHandler(name, handler, lookupStyles) {
	if (!devMode) return;
	if (typeof handler !== "function") console.warn(`[Tasty] Handler "${name}" is not a function. Handlers must be functions that return CSSMap, CSSMap[], or void.`);
	if (!lookupStyles || !Array.isArray(lookupStyles) || lookupStyles.length === 0) console.warn(`[Tasty] Handler "${name}" has invalid lookupStyles. Expected non-empty array of style names.`);
}
/**
* Register a custom handler, replacing any existing handlers for the same lookup styles.
* This is called by configure() to process user-defined handlers.
*
* When registering a handler for style X, any existing handler that processes X
* is removed from ALL its lookup styles to prevent double-processing.
* For example, if gapStyle handles ['display', 'flow', 'gap'] and a new handler
* is registered for just ['gap'], gapStyle is removed from display and flow too.
*/
function registerHandler(handler) {
	const lookupStyles = handler.__lookupStyles;
	if (!lookupStyles || lookupStyles.length === 0) {
		if (devMode) console.warn("[Tasty] Cannot register handler without __lookupStyles property.");
		return;
	}
	const handlersToRemove = /* @__PURE__ */ new Set();
	for (const styleName of lookupStyles) {
		const existing = STYLE_HANDLER_MAP[styleName];
		if (existing) for (const existingHandler of existing) handlersToRemove.add(existingHandler);
	}
	for (const oldHandler of handlersToRemove) {
		const oldLookupStyles = oldHandler.__lookupStyles;
		if (oldLookupStyles) for (const oldStyleName of oldLookupStyles) {
			const handlers = STYLE_HANDLER_MAP[oldStyleName];
			if (handlers) {
				const filtered = handlers.filter((h) => h !== oldHandler);
				if (filtered.length === 0) delete STYLE_HANDLER_MAP[oldStyleName];
				else STYLE_HANDLER_MAP[oldStyleName] = filtered;
			}
		}
	}
	for (const styleName of lookupStyles) {
		const existing = STYLE_HANDLER_MAP[styleName];
		if (existing) existing.push(handler);
		else STYLE_HANDLER_MAP[styleName] = [handler];
	}
}
/**
* Create a wrapped handler that can be safely called by users.
* The wrapper preserves __lookupStyles for proper registration.
*/
function wrapHandler(handler) {
	const fn = handler;
	const wrapped = ((props) => fn(props));
	wrapped.__lookupStyles = handler.__lookupStyles;
	return wrapped;
}
/**
* Exported object containing wrapped predefined style handlers.
* Users can import and call these to extend or delegate to built-in behavior.
*
* Internal handlers use *Style suffix for searchability.
* External API uses short names for convenience.
*
* @example
* ```ts
* import { styleHandlers, configure } from '@cube-dev/ui-kit';
*
* configure({
*   handlers: {
*     fill: ({ fill }) => {
*       if (fill?.startsWith('gradient:')) {
*         return { background: fill.slice(9) };
*       }
*       return styleHandlers.fill({ fill });
*     },
*   },
* });
* ```
*/
const styleHandlers = {
	align: wrapHandler(alignStyle),
	border: wrapHandler(borderStyle),
	color: wrapHandler(colorStyle),
	display: wrapHandler(displayStyle),
	fade: wrapHandler(fadeStyle),
	fill: wrapHandler(fillStyle),
	svgFill: wrapHandler(svgFillStyle),
	flow: wrapHandler(flowStyle),
	gap: wrapHandler(gapStyle),
	height: wrapHandler(heightStyle),
	inset: wrapHandler(insetStyle),
	justify: wrapHandler(justifyStyle),
	margin: wrapHandler(marginStyle),
	outline: wrapHandler(outlineStyle),
	padding: wrapHandler(paddingStyle),
	preset: wrapHandler(presetStyle),
	radius: wrapHandler(radiusStyle),
	reset: wrapHandler(resetStyle),
	scrollbar: wrapHandler(scrollbarStyle),
	shadow: wrapHandler(shadowStyle),
	styledScrollbar: wrapHandler(styledScrollbarStyle),
	transition: wrapHandler(transitionStyle),
	width: wrapHandler(widthStyle)
};

//#endregion
export { normalizeHandlerDefinition, predefine, registerHandler, resetHandlers, styleHandlers };
//# sourceMappingURL=predefined.js.map