/*! © 2026 Yahoo, Inc. UDS v0.0.0-development */
const require_StateAxis = require("../types/StateAxis.cjs");
const require_canonicalizeStateKey = require("./canonicalizeStateKey.cjs");
//#region ../automated-config/dist/utils/pseudoStateSelectors.js
/*! © 2026 Yahoo, Inc. UDS Default Config v0.0.0-development */
const LEGACY_STATE_ATOMS = new Set([
	"disabled",
	"focused",
	"focused-keyboard",
	"selected"
]);
function isKnownStateAtom(atom) {
	return require_StateAxis.isAtomicState(atom) || LEGACY_STATE_ATOMS.has(atom);
}
/**
* Each atom selector contributes exactly (0,1,0) to specificity. The base
* component class adds another (0,1,0), so a full rule's specificity is
* `(0, 1 + atom-count, 0)`:
*
*   rest        → (0,1,0)  e.g. `.uds-input-...root`
*   1-atom      → (0,2,0)  e.g. `.uds-input-...root:hover...`
*   2-atom      → (0,3,0)  e.g. `.uds-input-...root:has(...):hover...`
*   3-atom      → (0,4,0)
*   4-atom      → (0,5,0)
*
* Cross-rank cascade (compound beats atom beats rest) is therefore encoded
* in CSS class-count specificity, not source order — making the cascade-
* cancellation feature robust to any tool that reorders rules within a
* stylesheet. Within a rank (e.g. `:hover` vs `:focus-visible`, both
* (0,2,0)) source order still arbitrates; the resolver computes intra-rank
* order inline from `STATE_PRIORITY`. See {@link resolvePropertyStates}.
*
* Why each entry is (0,1,0):
*
* - `:hover` / `:active` / `:focus*` / `:visited` are single pseudo-classes,
*   each (0,1,0).
* - `:hover` and `:active` carry a `:where(:not(...))` blocker so the rule
*   doesn't match when the element is also active/disabled. The outer
*   `:where()` zeros the `:not(...)` contribution, leaving the bare pseudo-
*   class's (0,1,0) as the only contributor.
* - `:is(:disabled, :has(:disabled))` takes the max specificity of its
*   args; both are (0,1,0), so the whole is (0,1,0).
* - `:has(...)` selectors take the specificity of their arg's most specific
*   complex selector. Arguments are pseudo-classes or attribute selectors at
*   (0,1,0); where a form-control scope is also needed (e.g. `readonly` —
*   non-form-control elements default to `:read-only` per spec, so a bare
*   `:has(:read-only)` matches any container with DIV/SPAN children), the
*   scope goes inside `:where(...)` so its (0,0,1) type-selector contribution
*   is zeroed.
*
* **Consumer override ergonomics:** a plain `.my-input:hover` is (0,2,0),
* which ties library 1-atom rules at (0,2,0); source order decides. To
* unconditionally beat the library, consumers need (0,3,0) (e.g.
* `.scope .my-input:hover` or `.my-input.my-input:hover`).
*/
const ATOMIC_SELECTORS = {
	hover: ":hover:where(:not(:active, :disabled, :has(:disabled)))",
	pressed: ":active:where(:not(:disabled, :has(:disabled)))",
	disabled: ":is(:disabled, :has(:disabled))",
	visited: ":visited",
	focused: ":focus",
	"focus-within": ":focus-within",
	"focus-visible": ":focus-visible",
	"focused-keyboard": ":focus-visible",
	readonly: ":has(:read-only:where(input, textarea))",
	invalid: ":has([aria-invalid=\"true\"])",
	"placeholder-shown": ":has(:placeholder-shown)",
	autofill: ":has(:autofill, :-webkit-autofill)",
	selected: "[aria-selected=\"true\"]"
};
const ATOMIC_DOCS_CLASSES = {
	hover: "hover",
	pressed: "active",
	disabled: "has-disabled",
	visited: "visited",
	focused: "focus",
	"focus-within": "focus-within",
	"focus-visible": "focus-visible",
	"focused-keyboard": "focus-visible",
	readonly: "input-readonly",
	invalid: "has-input-invalid",
	"placeholder-shown": "has-input-placeholder-shown",
	autofill: "has-input-autofill",
	selected: "aria-selected"
};
/**
* Returns the CSS pseudo-selector string for a state key.
*
* - `'rest'`, `''`, and fully-unknown keys return `''`. An unknown atom inside
*   an otherwise-known compound is skipped (the known atoms still contribute) —
*   but callers only pass canonical validated keys, so that case doesn't arise
*   in practice.
* - Atomic keys return their entry from {@link ATOMIC_SELECTORS}.
* - Compound keys (`'a&b'`) return the concatenation of each atomic selector
*   in the order they appear in the key.
*/
function getStateSelector(stateKey) {
	const atoms = require_canonicalizeStateKey.splitStateKey(stateKey);
	if (atoms.length === 0) return "";
	let selector = "";
	for (const atom of atoms) if (isKnownStateAtom(atom)) selector += ATOMIC_SELECTORS[atom];
	return selector;
}
/**
* Returns the docs-mode class name for a state key, used to force-trigger
* pseudo-states in docs/Storybook previews.
*
* - `'rest'`, `''`, and fully-unknown keys return `''`. An unknown atom inside
*   an otherwise-known compound is skipped (the known atoms still contribute) —
*   but callers only pass canonical validated keys, so that case doesn't arise
*   in practice.
* - Atomic keys return their entry from {@link ATOMIC_DOCS_CLASSES}.
* - Compound keys join atomic docs classes with `'-and-'`.
*/
function getStateDocsClass(stateKey) {
	const atoms = require_canonicalizeStateKey.splitStateKey(stateKey);
	if (atoms.length === 0) return "";
	const parts = [];
	for (const atom of atoms) if (isKnownStateAtom(atom)) parts.push(ATOMIC_DOCS_CLASSES[atom]);
	return parts.join("-and-");
}
//#endregion
exports.getStateDocsClass = getStateDocsClass;
exports.getStateSelector = getStateSelector;
exports.isKnownStateAtom = isKnownStateAtom;
