{
  "version": 3,
  "sources": ["../../src/hooks/state-utils.js"],
  "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { getBlockType } from '@wordpress/blocks';\nimport { splitSelectorList } from '@wordpress/global-styles-engine';\n\n/**\n * Given a block's `selectors.root` value, returns the part of the selector\n * that is relative to the block wrapper \u2014 i.e., everything after the first\n * compound selector segment.\n *\n * Examples:\n *   \".wp-block-button .wp-block-button__link\" \u2192 \".wp-block-button__link\"\n *   \".wp-block-foo > .inner\"                 \u2192 \"> .inner\"\n *   \".wp-block-foo\"                          \u2192 null (no descendant)\n *\n * @param {string} rootSelector The block's `selectors.root` value.\n * @return {string|null} Relative selector, or null if rootSelector targets the wrapper itself.\n */\nexport function getRelativeRootSelector( rootSelector ) {\n\t// Match everything after the first compound selector (up to the first\n\t// whitespace or combinator character).\n\t// Require at least one combinator character (space, >, +, ~) between the\n\t// first compound selector and the rest. Without this anchor, a greedy\n\t// quantifier would backtrack into the first token and produce false matches.\n\tconst match = rootSelector.trim().match( /^[^ >+~]+[ >+~](.*)$/ );\n\tif ( ! match ) {\n\t\treturn null;\n\t}\n\tconst rest = match[ 1 ].trim();\n\treturn rest || null;\n}\n\n/**\n * Builds a scoped selector from a block selector and optional suffix.\n *\n * If the block selector targets a descendant, the descendant portion is scoped\n * under the provided base selector. Otherwise the base selector itself is used.\n *\n * @param {string} baseSelector  The block-instance scoping selector.\n * @param {string} blockSelector The block or feature selector from block metadata.\n * @param {string} suffix        Optional selector suffix, e.g. \":hover\".\n * @return {string} The scoped CSS selector.\n */\nexport function buildScopedBlockSelector(\n\tbaseSelector,\n\tblockSelector,\n\tsuffix = ''\n) {\n\tif ( typeof blockSelector !== 'string' || ! blockSelector ) {\n\t\treturn splitSelectorList( baseSelector )\n\t\t\t.map( ( selector ) => `${ selector.trim() }${ suffix }` )\n\t\t\t.join( ', ' );\n\t}\n\n\tconst baseSelectors = splitSelectorList( baseSelector ).filter(\n\t\t( selector ) => selector.trim()\n\t);\n\tconst selectors = splitSelectorList( blockSelector ).filter( ( selector ) =>\n\t\tselector.trim()\n\t);\n\n\tif ( ! selectors.length ) {\n\t\treturn baseSelectors\n\t\t\t.map( ( selector ) => `${ selector.trim() }${ suffix }` )\n\t\t\t.join( ', ' );\n\t}\n\n\treturn selectors\n\t\t.map( ( selector ) => {\n\t\t\tselector = selector.trim();\n\n\t\t\t/*\n\t\t\t * Replace only the leading block selector part (e.g. class name,\n\t\t\t * attribute selector, ID, or tag name) with the block instance selector.\n\t\t\t * Preserve anything after that prefix, including modifier classes on the\n\t\t\t * same element and combinators without spaces.\n\t\t\t */\n\t\t\tconst match = selector.match( /^([.#]?[-_a-zA-Z0-9]+|\\[[^\\]]+\\])/ );\n\t\t\tif ( match ) {\n\t\t\t\treturn baseSelectors\n\t\t\t\t\t.map(\n\t\t\t\t\t\t( base ) =>\n\t\t\t\t\t\t\t`${ base.trim() }${ selector.slice(\n\t\t\t\t\t\t\t\tmatch[ 0 ].length\n\t\t\t\t\t\t\t) }${ suffix }`\n\t\t\t\t\t)\n\t\t\t\t\t.join( ', ' );\n\t\t\t}\n\n\t\t\treturn baseSelectors\n\t\t\t\t.map( ( base ) => `${ base.trim() }${ suffix }` )\n\t\t\t\t.join( ', ' );\n\t\t} )\n\t\t.join( ', ' );\n}\n\n/**\n * Builds the scoped selector for root block style state styles.\n *\n * Uses the block's `selectors.root` to determine which element should receive\n * root-level state styles. If `selectors.root` describes a descendant element\n * (e.g. `.wp-block-button .wp-block-button__link`), the relative portion is\n * scoped under `baseSelector`. If no descendant is present, falls back to the\n * base selector.\n *\n * @param {string} baseSelector The block-instance scoping class selector.\n * @param {string} name         The block name, used to look up selectors.\n * @return {string} The fully-scoped CSS selector for root state styles.\n */\nexport function buildRootStyleStateSelector( baseSelector, name ) {\n\tconst rootSelector = getBlockType( name )?.selectors?.root;\n\treturn buildScopedBlockSelector( baseSelector, rootSelector );\n}\n\n/**\n * Builds the scoped CSS selector for a block state (e.g. :hover, :focus).\n *\n * Uses the block's `selectors.root` to determine which element the state\n * pseudo-class should apply to. If `selectors.root` describes a descendant\n * element (e.g. \".wp-block-button .wp-block-button__link\"), the relative\n * portion (\".wp-block-button__link\") is scoped under `baseSelector`. If no\n * descendant is present, falls back to appending the state to `baseSelector`.\n *\n * @param {string} baseSelector The block-instance scoping class selector.\n * @param {string} name         The block name, used to look up selectors.\n * @param {string} state        The pseudo-class string, e.g. \":hover\".\n * @return {string} The fully-scoped CSS selector for this state.\n */\nexport function buildPseudoStyleStateSelector( baseSelector, name, state ) {\n\treturn `${ buildRootStyleStateSelector( baseSelector, name ) }${ state }`;\n}\n\nexport function buildStateSelector( baseSelector, name, state ) {\n\tconst rootSelector = getBlockType( name )?.selectors?.root;\n\treturn buildScopedBlockSelector( baseSelector, rootSelector, state );\n}\n\n/**\n * Builds the CSS selector used to preview a state on the editor canvas,\n * scoped to a specific block instance via its `data-block` attribute.\n *\n * For blocks whose `selectors.root` targets a descendant element\n * (e.g. \".wp-block-button .wp-block-button__link\"), the selector targets\n * that descendant inside the block wrapper. Otherwise it targets the wrapper\n * itself.\n *\n * @param {string} clientId The block's clientId.\n * @param {string} name     The block name, used to look up selectors.\n * @return {string} CSS selector scoped to this block instance.\n */\nexport function buildCanvasStateSelector( clientId, name ) {\n\tconst rootSelector = getBlockType( name )?.selectors?.root;\n\treturn buildScopedBlockSelector(\n\t\t`[data-block=\"${ clientId }\"]`,\n\t\trootSelector\n\t);\n}\n"],
  "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,oBAA6B;AAC7B,kCAAkC;AAe3B,SAAS,wBAAyB,cAAe;AAMvD,QAAM,QAAQ,aAAa,KAAK,EAAE,MAAO,sBAAuB;AAChE,MAAK,CAAE,OAAQ;AACd,WAAO;AAAA,EACR;AACA,QAAM,OAAO,MAAO,CAAE,EAAE,KAAK;AAC7B,SAAO,QAAQ;AAChB;AAaO,SAAS,yBACf,cACA,eACA,SAAS,IACR;AACD,MAAK,OAAO,kBAAkB,YAAY,CAAE,eAAgB;AAC3D,eAAO,+CAAmB,YAAa,EACrC,IAAK,CAAE,aAAc,GAAI,SAAS,KAAK,CAAE,GAAI,MAAO,EAAG,EACvD,KAAM,IAAK;AAAA,EACd;AAEA,QAAM,oBAAgB,+CAAmB,YAAa,EAAE;AAAA,IACvD,CAAE,aAAc,SAAS,KAAK;AAAA,EAC/B;AACA,QAAM,gBAAY,+CAAmB,aAAc,EAAE;AAAA,IAAQ,CAAE,aAC9D,SAAS,KAAK;AAAA,EACf;AAEA,MAAK,CAAE,UAAU,QAAS;AACzB,WAAO,cACL,IAAK,CAAE,aAAc,GAAI,SAAS,KAAK,CAAE,GAAI,MAAO,EAAG,EACvD,KAAM,IAAK;AAAA,EACd;AAEA,SAAO,UACL,IAAK,CAAE,aAAc;AACrB,eAAW,SAAS,KAAK;AAQzB,UAAM,QAAQ,SAAS,MAAO,mCAAoC;AAClE,QAAK,OAAQ;AACZ,aAAO,cACL;AAAA,QACA,CAAE,SACD,GAAI,KAAK,KAAK,CAAE,GAAI,SAAS;AAAA,UAC5B,MAAO,CAAE,EAAE;AAAA,QACZ,CAAE,GAAI,MAAO;AAAA,MACf,EACC,KAAM,IAAK;AAAA,IACd;AAEA,WAAO,cACL,IAAK,CAAE,SAAU,GAAI,KAAK,KAAK,CAAE,GAAI,MAAO,EAAG,EAC/C,KAAM,IAAK;AAAA,EACd,CAAE,EACD,KAAM,IAAK;AACd;AAeO,SAAS,4BAA6B,cAAc,MAAO;AACjE,QAAM,mBAAe,4BAAc,IAAK,GAAG,WAAW;AACtD,SAAO,yBAA0B,cAAc,YAAa;AAC7D;AAgBO,SAAS,8BAA+B,cAAc,MAAM,OAAQ;AAC1E,SAAO,GAAI,4BAA6B,cAAc,IAAK,CAAE,GAAI,KAAM;AACxE;AAEO,SAAS,mBAAoB,cAAc,MAAM,OAAQ;AAC/D,QAAM,mBAAe,4BAAc,IAAK,GAAG,WAAW;AACtD,SAAO,yBAA0B,cAAc,cAAc,KAAM;AACpE;AAeO,SAAS,yBAA0B,UAAU,MAAO;AAC1D,QAAM,mBAAe,4BAAc,IAAK,GAAG,WAAW;AACtD,SAAO;AAAA,IACN,gBAAiB,QAAS;AAAA,IAC1B;AAAA,EACD;AACD;",
  "names": []
}
