/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-e634e55 | Cube Dev Team */
import { isDevEnv } from "../utils/is-dev-env.js";
import { hasStylesGenerated } from "../config.js";

//#region src/tasty/states/index.ts
/**
* Advanced State Mapping - Predefined States Management
*
* This module handles global and local predefined states for the Tasty styling system.
* See ADVANCED_STATE_MAPPING.md for full specification.
*/
const BUILTIN_STATES = new Set([
	"@starting",
	"@keyframes",
	"@properties",
	"@supports",
	"@inherit"
]);
let globalPredefinedStates = {};
const emittedWarnings = /* @__PURE__ */ new Set();
const devMode = isDevEnv();
/**
* Emit a warning only once
*/
function warnOnce(key, message) {
	if (devMode && !emittedWarnings.has(key)) {
		emittedWarnings.add(key);
		console.warn(message);
	}
}
/**
* Configure global predefined states
*/
function setGlobalPredefinedStates(states) {
	if (hasStylesGenerated()) {
		const newStateNames = Object.keys(states).join(", ");
		warnOnce(`dynamic-states:${newStateNames}`, `[Tasty] Cannot update predefined states after styles have been generated.\nThe new definition(s) for ${newStateNames} will be ignored.`);
		return;
	}
	for (const [name, value] of Object.entries(states)) {
		if (!/^@[A-Za-z][A-Za-z0-9-]*$/.test(name)) {
			warnOnce(`invalid-state-name:${name}`, `[Tasty] Invalid predefined state name '${name}'. Must start with '@' followed by a letter.`);
			continue;
		}
		if (BUILTIN_STATES.has(name)) {
			warnOnce(`reserved-state:${name}`, `[Tasty] Cannot define predefined state '${name}'. This name is reserved for built-in functionality.`);
			continue;
		}
		if (name === "@media" || name === "@root" || name === "@own" || name.startsWith("@(")) {
			warnOnce(`reserved-prefix:${name}`, `[Tasty] Cannot define predefined state '${name}'. This prefix is reserved for built-in functionality.`);
			continue;
		}
		const crossRefs = extractPredefinedStateRefs(value);
		if (crossRefs.length > 0) {
			warnOnce(`cross-ref:${name}`, `[Tasty] Predefined state '${name}' references another predefined state '${crossRefs[0]}'.\nPredefined states cannot reference each other. Use the full definition instead.`);
			continue;
		}
		if (globalPredefinedStates[name] && globalPredefinedStates[name] !== value) warnOnce(`duplicate-state:${name}`, `[Tasty] Duplicate predefined state '${name}' in configure(). The last definition will be used.`);
		globalPredefinedStates[name] = value;
	}
}
/**
* Get global predefined states
*/
function getGlobalPredefinedStates() {
	return globalPredefinedStates;
}
/**
* Regex to match predefined state references in a string
* Matches @name that is NOT followed by ( or : and is a complete word
* Uses word boundary and negative lookahead
*/
const PREDEFINED_STATE_PATTERN = /@([A-Za-z][A-Za-z0-9-]*)(?![A-Za-z0-9-:(])/g;
/**
* Extract predefined state references from a string
*/
function extractPredefinedStateRefs(value) {
	const matches = value.matchAll(PREDEFINED_STATE_PATTERN);
	const refs = [];
	for (const match of matches) {
		const stateName = "@" + match[1];
		if (!BUILTIN_STATES.has(stateName) && !refs.includes(stateName)) refs.push(stateName);
	}
	return refs;
}
/**
* Extract local predefined states from a styles object
* Local predefined states are top-level keys starting with @ that have string values
* and are valid predefined state names (not built-in like @media, @root, etc.)
*/
function extractLocalPredefinedStates(styles) {
	const localStates = {};
	if (!styles || typeof styles !== "object") return localStates;
	for (const [key, value] of Object.entries(styles)) if (key.startsWith("@") && typeof value === "string") {
		if (!/^@[A-Za-z][A-Za-z0-9-]*$/.test(key)) continue;
		if (BUILTIN_STATES.has(key)) continue;
		if (key === "@media" || key === "@root" || key === "@own" || key.startsWith("@(")) continue;
		const crossRefs = extractPredefinedStateRefs(value);
		if (crossRefs.length > 0) {
			warnOnce(`local-cross-ref:${key}`, `[Tasty] Predefined state '${key}' references another predefined state '${crossRefs[0]}'.\nPredefined states cannot reference each other. Use the full definition instead.`);
			continue;
		}
		localStates[key] = value;
	}
	return localStates;
}
/**
* Create a state parser context from styles
*/
function createStateParserContext(styles, isSubElement) {
	return {
		localPredefinedStates: styles ? extractLocalPredefinedStates(styles) : {},
		globalPredefinedStates: getGlobalPredefinedStates(),
		isSubElement
	};
}
/**
* Resolve a predefined state reference to its value
* Returns the resolved value or null if not found
*/
function resolvePredefinedState(stateKey, ctx) {
	if (ctx.localPredefinedStates[stateKey]) return ctx.localPredefinedStates[stateKey];
	if (ctx.globalPredefinedStates[stateKey]) return ctx.globalPredefinedStates[stateKey];
	warnOnce(`undefined-state:${stateKey}`, `[Tasty] Undefined predefined state '${stateKey}'.\nDefine it in configure({ states: { '${stateKey}': '...' } }) or in the component's styles.`);
	return null;
}
/**
* Expand dimension shorthands in a condition string
* w -> width, h -> height, is -> inline-size, bs -> block-size
*/
function expandDimensionShorthands(condition) {
	let result = condition;
	result = result.replace(/\bw\b/g, "width");
	result = result.replace(/\bh\b/g, "height");
	result = result.replace(/\bis\b/g, "inline-size");
	result = result.replace(/\bbs\b/g, "block-size");
	return result;
}
/**
* Convert tasty units in a string (e.g., 40x -> calc(var(--gap) * 40))
*/
function expandTastyUnits(value) {
	return value.replace(/(\d+(?:\.\d+)?)\s*x\b/g, (_, num) => {
		return `calc(var(--gap) * ${num})`;
	});
}
/**
* Find the index of the first comma at parentheses depth 0.
* Returns -1 if no top-level comma is found.
* This prevents splitting on commas inside function calls like scroll-state(a, b).
*/
function findTopLevelComma(s) {
	let depth = 0;
	for (let i = 0; i < s.length; i++) if (s[i] === "(") depth++;
	else if (s[i] === ")") depth--;
	else if (s[i] === "," && depth === 0) return i;
	return -1;
}

//#endregion
export { createStateParserContext, expandDimensionShorthands, expandTastyUnits, extractLocalPredefinedStates, extractPredefinedStateRefs, findTopLevelComma, resolvePredefinedState, setGlobalPredefinedStates };
//# sourceMappingURL=index.js.map