nudge-ui 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (510) hide show
  1. package/README.md +66 -0
  2. package/bin/nudge-ui.mjs +7 -0
  3. package/dist/LICENSE +21 -0
  4. package/dist/client.mjs +261 -0
  5. package/dist/compiler/ast.d.ts +18 -0
  6. package/dist/compiler/ast.js +75 -0
  7. package/dist/compiler/componentContractTypes.d.ts +19 -0
  8. package/dist/compiler/componentContractTypes.js +1 -0
  9. package/dist/compiler/componentContracts.d.ts +2 -0
  10. package/dist/compiler/componentContracts.js +260 -0
  11. package/dist/compiler/componentInstrumentation.d.ts +32 -0
  12. package/dist/compiler/componentInstrumentation.js +140 -0
  13. package/dist/compiler/componentPolicyResolution.d.ts +71 -0
  14. package/dist/compiler/componentPolicyResolution.js +388 -0
  15. package/dist/compiler/index.d.ts +9 -0
  16. package/dist/compiler/index.js +9 -0
  17. package/dist/compiler/packageComponentContracts.d.ts +32 -0
  18. package/dist/compiler/packageComponentContracts.js +308 -0
  19. package/dist/compiler/reactComponentProtocols.d.ts +145 -0
  20. package/dist/compiler/reactComponentProtocols.js +47 -0
  21. package/dist/compiler/reactIdentity.d.ts +15 -0
  22. package/dist/compiler/reactIdentity.js +339 -0
  23. package/dist/compiler/sourcePaths.d.ts +12 -0
  24. package/dist/compiler/sourcePaths.js +27 -0
  25. package/dist/css/dialects/index.d.ts +62 -0
  26. package/dist/css/dialects/index.js +103 -0
  27. package/dist/css/dialects/tailwind.d.ts +46 -0
  28. package/dist/css/dialects/tailwind.js +119 -0
  29. package/dist/css/dialects/vanillaExtract.d.ts +20 -0
  30. package/dist/css/dialects/vanillaExtract.js +32 -0
  31. package/dist/css/index.d.ts +10 -0
  32. package/dist/css/index.js +10 -0
  33. package/dist/css/model/index.d.ts +190 -0
  34. package/dist/css/model/index.js +10 -0
  35. package/dist/css/token-inventory/index.d.ts +26 -0
  36. package/dist/css/token-inventory/index.js +24 -0
  37. package/dist/css/token-inventory/inventory.d.ts +8 -0
  38. package/dist/css/token-inventory/inventory.js +421 -0
  39. package/dist/css/token-inventory/parseStylesheet.d.ts +16 -0
  40. package/dist/css/token-inventory/parseStylesheet.js +155 -0
  41. package/dist/css/token-inventory/policy.d.ts +47 -0
  42. package/dist/css/token-inventory/policy.js +50 -0
  43. package/dist/css/token-inventory/types.d.ts +97 -0
  44. package/dist/css/token-inventory/types.js +1 -0
  45. package/dist/css/value-semantics/borderSemantics.d.ts +28 -0
  46. package/dist/css/value-semantics/borderSemantics.js +91 -0
  47. package/dist/css/value-semantics/boxSemantics.d.ts +37 -0
  48. package/dist/css/value-semantics/boxSemantics.js +71 -0
  49. package/dist/css/value-semantics/colorSemantics.d.ts +99 -0
  50. package/dist/css/value-semantics/colorSemantics.js +526 -0
  51. package/dist/css/value-semantics/cssSyntax.d.ts +19 -0
  52. package/dist/css/value-semantics/cssSyntax.js +111 -0
  53. package/dist/css/value-semantics/fontSemantics.d.ts +35 -0
  54. package/dist/css/value-semantics/fontSemantics.js +131 -0
  55. package/dist/css/value-semantics/index.d.ts +20 -0
  56. package/dist/css/value-semantics/index.js +15 -0
  57. package/dist/css/value-semantics/propertyPolicy.d.ts +118 -0
  58. package/dist/css/value-semantics/propertyPolicy.js +356 -0
  59. package/dist/css/value-semantics/stringMaps.d.ts +2 -0
  60. package/dist/css/value-semantics/stringMaps.js +1 -0
  61. package/dist/css/value-semantics/structuredValues.d.ts +64 -0
  62. package/dist/css/value-semantics/structuredValues.js +250 -0
  63. package/dist/css/value-semantics/tokenInterpretation.d.ts +90 -0
  64. package/dist/css/value-semantics/tokenInterpretation.js +193 -0
  65. package/dist/css/virtual-design-tokens.d.ts +17 -0
  66. package/dist/hosts/astro/astroRuntimeConfig.d.ts +12 -0
  67. package/dist/hosts/astro/astroRuntimeConfig.js +26 -0
  68. package/dist/hosts/astro/clientAsset.d.ts +12 -0
  69. package/dist/hosts/astro/clientAsset.js +51 -0
  70. package/dist/hosts/astro/clientTransport.d.ts +3 -0
  71. package/dist/hosts/astro/clientTransport.js +57 -0
  72. package/dist/hosts/astro/index.d.ts +3 -0
  73. package/dist/hosts/astro/index.js +2 -0
  74. package/dist/hosts/astro/integration.d.ts +35 -0
  75. package/dist/hosts/astro/integration.js +96 -0
  76. package/dist/hosts/astro/middleware.d.ts +13 -0
  77. package/dist/hosts/astro/middleware.js +22 -0
  78. package/dist/hosts/astro/projectContext.d.ts +11 -0
  79. package/dist/hosts/astro/projectContext.js +34 -0
  80. package/dist/hosts/astro/responseInstrumentation.d.ts +41 -0
  81. package/dist/hosts/astro/responseInstrumentation.js +80 -0
  82. package/dist/hosts/next/index.d.ts +4 -0
  83. package/dist/hosts/next/index.js +7 -0
  84. package/dist/hosts/next/loader.d.ts +66 -0
  85. package/dist/hosts/next/loader.js +346 -0
  86. package/dist/hosts/next/loaders/identity-loader.cjs +228257 -0
  87. package/dist/hosts/next/loaders/loader-plugin.cjs +228257 -0
  88. package/dist/hosts/next/manifest.d.ts +38 -0
  89. package/dist/hosts/next/manifest.js +30 -0
  90. package/dist/hosts/next/mount.d.ts +12 -0
  91. package/dist/hosts/next/mount.js +23 -0
  92. package/dist/hosts/next/repositoryScope.d.ts +20 -0
  93. package/dist/hosts/next/repositoryScope.js +33 -0
  94. package/dist/hosts/next/sidecar.d.ts +27 -0
  95. package/dist/hosts/next/sidecar.js +526 -0
  96. package/dist/hosts/next/wrapper.d.ts +67 -0
  97. package/dist/hosts/next/wrapper.js +310 -0
  98. package/dist/hosts/static/cli.d.ts +12 -0
  99. package/dist/hosts/static/cli.js +77 -0
  100. package/dist/hosts/static/html/bootstrap.d.ts +27 -0
  101. package/dist/hosts/static/html/bootstrap.js +93 -0
  102. package/dist/hosts/static/index.d.ts +4 -0
  103. package/dist/hosts/static/index.js +4 -0
  104. package/dist/hosts/static/manifest.d.ts +18 -0
  105. package/dist/hosts/static/manifest.js +51 -0
  106. package/dist/hosts/static/server.d.ts +72 -0
  107. package/dist/hosts/static/server.js +554 -0
  108. package/dist/hosts/vite/index.d.ts +20 -0
  109. package/dist/hosts/vite/index.js +48 -0
  110. package/dist/hosts/vite/react.d.ts +67 -0
  111. package/dist/hosts/vite/react.js +231 -0
  112. package/dist/hosts/vite/tokens/activeStylesheets.d.ts +28 -0
  113. package/dist/hosts/vite/tokens/activeStylesheets.js +70 -0
  114. package/dist/hosts/vite/tokens/fileMap.d.ts +2 -0
  115. package/dist/hosts/vite/tokens/fileMap.js +1 -0
  116. package/dist/hosts/vite/tokens/viteStylesheetArtifacts.d.ts +46 -0
  117. package/dist/hosts/vite/tokens/viteStylesheetArtifacts.js +104 -0
  118. package/dist/hosts/vite/virtual/design-tokens.d.ts +9 -0
  119. package/dist/hosts/vite/virtual/design-tokens.js +7 -0
  120. package/dist/hosts/vite/virtual-design-tokens.d.ts +1 -0
  121. package/dist/hosts/vite/vite.d.ts +62 -0
  122. package/dist/hosts/vite/vite.js +854 -0
  123. package/dist/html/dom.d.ts +13 -0
  124. package/dist/html/dom.js +46 -0
  125. package/dist/html/identity.d.ts +40 -0
  126. package/dist/html/identity.js +196 -0
  127. package/dist/html/insertions.d.ts +26 -0
  128. package/dist/html/insertions.js +59 -0
  129. package/dist/inspector/agent/McpConnectionDialog.d.ts +26 -0
  130. package/dist/inspector/agent/McpConnectionDialog.js +135 -0
  131. package/dist/inspector/agent/client.d.ts +98 -0
  132. package/dist/inspector/agent/client.js +728 -0
  133. package/dist/inspector/agent/connectionStatus.d.ts +13 -0
  134. package/dist/inspector/agent/connectionStatus.js +35 -0
  135. package/dist/inspector/agent/httpTransport.d.ts +21 -0
  136. package/dist/inspector/agent/httpTransport.js +347 -0
  137. package/dist/inspector/agent/protocol.d.ts +95 -0
  138. package/dist/inspector/agent/protocol.js +9 -0
  139. package/dist/inspector/agent/verification.d.ts +39 -0
  140. package/dist/inspector/agent/verification.js +207 -0
  141. package/dist/inspector/canvas/CanvasCard.d.ts +10 -0
  142. package/dist/inspector/canvas/CanvasCard.js +275 -0
  143. package/dist/inspector/canvas/CanvasElementOverlay.d.ts +2 -0
  144. package/dist/inspector/canvas/CanvasElementOverlay.js +301 -0
  145. package/dist/inspector/canvas/CanvasWorkspace.d.ts +2 -0
  146. package/dist/inspector/canvas/CanvasWorkspace.js +301 -0
  147. package/dist/inspector/canvas/LockedWorkspaceNotice.d.ts +6 -0
  148. package/dist/inspector/canvas/LockedWorkspaceNotice.js +17 -0
  149. package/dist/inspector/canvas/StaleChangeIndicator.d.ts +7 -0
  150. package/dist/inspector/canvas/StaleChangeIndicator.js +43 -0
  151. package/dist/inspector/canvas/agentPresentation.d.ts +87 -0
  152. package/dist/inspector/canvas/agentPresentation.js +421 -0
  153. package/dist/inspector/canvas/canvasGestures.d.ts +12 -0
  154. package/dist/inspector/canvas/canvasGestures.js +21 -0
  155. package/dist/inspector/canvas/canvasStore.d.ts +108 -0
  156. package/dist/inspector/canvas/canvasStore.js +448 -0
  157. package/dist/inspector/canvas/frameProtocol.d.ts +231 -0
  158. package/dist/inspector/canvas/frameProtocol.js +165 -0
  159. package/dist/inspector/canvas/linkEligibility.d.ts +8 -0
  160. package/dist/inspector/canvas/linkEligibility.js +68 -0
  161. package/dist/inspector/canvas/measurementProjection.d.ts +8 -0
  162. package/dist/inspector/canvas/measurementProjection.js +16 -0
  163. package/dist/inspector/canvas/normalizeUrl.d.ts +7 -0
  164. package/dist/inspector/canvas/normalizeUrl.js +27 -0
  165. package/dist/inspector/canvas/projection.d.ts +41 -0
  166. package/dist/inspector/canvas/projection.js +232 -0
  167. package/dist/inspector/canvas/rendererBootstrap.d.ts +4 -0
  168. package/dist/inspector/canvas/rendererBootstrap.js +410 -0
  169. package/dist/inspector/canvas/rendererCidIndex.d.ts +11 -0
  170. package/dist/inspector/canvas/rendererCidIndex.js +21 -0
  171. package/dist/inspector/canvas/rendererElementSelector.d.ts +2 -0
  172. package/dist/inspector/canvas/rendererElementSelector.js +378 -0
  173. package/dist/inspector/canvas/rendererSelectionProxy.d.ts +2 -0
  174. package/dist/inspector/canvas/rendererSelectionProxy.js +61 -0
  175. package/dist/inspector/canvas/rendererStylesheet.d.ts +16 -0
  176. package/dist/inspector/canvas/rendererStylesheet.js +221 -0
  177. package/dist/inspector/canvas/resizeHandleScale.d.ts +13 -0
  178. package/dist/inspector/canvas/resizeHandleScale.js +20 -0
  179. package/dist/inspector/canvas/roleDetection.d.ts +5 -0
  180. package/dist/inspector/canvas/roleDetection.js +21 -0
  181. package/dist/inspector/canvas/sessionStore.d.ts +71 -0
  182. package/dist/inspector/canvas/sessionStore.js +453 -0
  183. package/dist/inspector/canvas/staleChangeDetector.d.ts +11 -0
  184. package/dist/inspector/canvas/staleChangeDetector.js +217 -0
  185. package/dist/inspector/canvas/toolbarScale.d.ts +7 -0
  186. package/dist/inspector/canvas/toolbarScale.js +11 -0
  187. package/dist/inspector/canvas/workspaceLease.d.ts +26 -0
  188. package/dist/inspector/canvas/workspaceLease.js +214 -0
  189. package/dist/inspector/changes/changesLog.d.ts +46 -0
  190. package/dist/inspector/changes/changesLog.js +209 -0
  191. package/dist/inspector/changes/codecs.d.ts +98 -0
  192. package/dist/inspector/changes/codecs.js +389 -0
  193. package/dist/inspector/changes/editModel.d.ts +74 -0
  194. package/dist/inspector/changes/editModel.js +120 -0
  195. package/dist/inspector/changes/managedStyleProjection.d.ts +6 -0
  196. package/dist/inspector/changes/managedStyleProjection.js +109 -0
  197. package/dist/inspector/changes/model.d.ts +13 -0
  198. package/dist/inspector/changes/model.js +163 -0
  199. package/dist/inspector/changes/presentation.d.ts +14 -0
  200. package/dist/inspector/changes/presentation.js +81 -0
  201. package/dist/inspector/changes/previewDiagnostics.d.ts +39 -0
  202. package/dist/inspector/changes/previewDiagnostics.js +172 -0
  203. package/dist/inspector/changes/structuralTypes.d.ts +35 -0
  204. package/dist/inspector/changes/structuralTypes.js +1 -0
  205. package/dist/inspector/changes/types.d.ts +76 -0
  206. package/dist/inspector/changes/types.js +16 -0
  207. package/dist/inspector/changes/workspaceChanges.d.ts +43 -0
  208. package/dist/inspector/changes/workspaceChanges.js +239 -0
  209. package/dist/inspector/clientManifest.d.ts +24 -0
  210. package/dist/inspector/clientManifest.js +69 -0
  211. package/dist/inspector/componentSemantics/ComponentPropsSection.d.ts +5 -0
  212. package/dist/inspector/componentSemantics/ComponentPropsSection.js +44 -0
  213. package/dist/inspector/componentSemantics/adapterRegistry.d.ts +11 -0
  214. package/dist/inspector/componentSemantics/adapterRegistry.js +75 -0
  215. package/dist/inspector/componentSemantics/boundaries.d.ts +2 -0
  216. package/dist/inspector/componentSemantics/boundaries.js +10 -0
  217. package/dist/inspector/componentSemantics/changeAction.d.ts +3 -0
  218. package/dist/inspector/componentSemantics/changeAction.js +6 -0
  219. package/dist/inspector/componentSemantics/changeModel.d.ts +8 -0
  220. package/dist/inspector/componentSemantics/changeModel.js +60 -0
  221. package/dist/inspector/componentSemantics/index.d.ts +4 -0
  222. package/dist/inspector/componentSemantics/index.js +2 -0
  223. package/dist/inspector/componentSemantics/reactRuntime.d.ts +10 -0
  224. package/dist/inspector/componentSemantics/reactRuntime.js +186 -0
  225. package/dist/inspector/componentSemantics/runtimeBridge.d.ts +25 -0
  226. package/dist/inspector/componentSemantics/runtimeBridge.js +161 -0
  227. package/dist/inspector/componentSemantics/runtimeTypes.d.ts +2 -0
  228. package/dist/inspector/componentSemantics/runtimeTypes.js +1 -0
  229. package/dist/inspector/componentSemantics/textBinding.d.ts +69 -0
  230. package/dist/inspector/componentSemantics/textBinding.js +514 -0
  231. package/dist/inspector/componentSemantics/types.d.ts +96 -0
  232. package/dist/inspector/componentSemantics/types.js +5 -0
  233. package/dist/inspector/conformance/borderCases.d.ts +7 -0
  234. package/dist/inspector/conformance/borderCases.js +428 -0
  235. package/dist/inspector/conformance/colorCases.d.ts +8 -0
  236. package/dist/inspector/conformance/colorCases.js +470 -0
  237. package/dist/inspector/conformance/fixture.d.ts +68 -0
  238. package/dist/inspector/conformance/fixture.js +153 -0
  239. package/dist/inspector/conformance/projection.d.ts +2 -0
  240. package/dist/inspector/conformance/projection.js +3 -0
  241. package/dist/inspector/conformance/spacingCases.d.ts +6 -0
  242. package/dist/inspector/conformance/spacingCases.js +417 -0
  243. package/dist/inspector/conformance/typographyCases.d.ts +7 -0
  244. package/dist/inspector/conformance/typographyCases.js +174 -0
  245. package/dist/inspector/editScope.d.ts +4 -0
  246. package/dist/inspector/editScope.js +5 -0
  247. package/dist/inspector/index.d.ts +20 -0
  248. package/dist/inspector/index.js +236 -0
  249. package/dist/inspector/inline-text/inlineTextEditor.d.ts +74 -0
  250. package/dist/inspector/inline-text/inlineTextEditor.js +1207 -0
  251. package/dist/inspector/inline-text/inlineTextLifecycle.d.ts +2 -0
  252. package/dist/inspector/inline-text/inlineTextLifecycle.js +17 -0
  253. package/dist/inspector/inline-text/textChangeBoundary.d.ts +6 -0
  254. package/dist/inspector/inline-text/textChangeBoundary.js +1 -0
  255. package/dist/inspector/inspection/bridge.d.ts +72 -0
  256. package/dist/inspector/inspection/bridge.js +134 -0
  257. package/dist/inspector/inspection/browserCssInspection.d.ts +74 -0
  258. package/dist/inspector/inspection/browserCssInspection.js +317 -0
  259. package/dist/inspector/inspection/browserCssInspectionRegistry.d.ts +12 -0
  260. package/dist/inspector/inspection/browserCssInspectionRegistry.js +66 -0
  261. package/dist/inspector/inspection/selectionProperty.d.ts +32 -0
  262. package/dist/inspector/inspection/selectionProperty.js +33 -0
  263. package/dist/inspector/inspection/useBrowserCssInspection.d.ts +20 -0
  264. package/dist/inspector/inspection/useBrowserCssInspection.js +159 -0
  265. package/dist/inspector/overlay/DropGuideOverlay.d.ts +17 -0
  266. package/dist/inspector/overlay/DropGuideOverlay.js +17 -0
  267. package/dist/inspector/overlay/InspectorOverlay.d.ts +5 -0
  268. package/dist/inspector/overlay/InspectorOverlay.js +328 -0
  269. package/dist/inspector/overlay/MeasurementGuideOverlay.d.ts +19 -0
  270. package/dist/inspector/overlay/MeasurementGuideOverlay.js +40 -0
  271. package/dist/inspector/overlay/clickPolicy.d.ts +7 -0
  272. package/dist/inspector/overlay/clickPolicy.js +13 -0
  273. package/dist/inspector/overlay/dropGuide.d.ts +22 -0
  274. package/dist/inspector/overlay/dropGuide.js +48 -0
  275. package/dist/inspector/overlay/elementSelector.d.ts +1 -0
  276. package/dist/inspector/overlay/elementSelector.js +100 -0
  277. package/dist/inspector/overlay/frameThrottle.d.ts +10 -0
  278. package/dist/inspector/overlay/frameThrottle.js +38 -0
  279. package/dist/inspector/overlay/interactionStyles.d.ts +3 -0
  280. package/dist/inspector/overlay/interactionStyles.js +70 -0
  281. package/dist/inspector/overlay/measurementGeometry.d.ts +25 -0
  282. package/dist/inspector/overlay/measurementGeometry.js +104 -0
  283. package/dist/inspector/overlay/overlayGeometry.d.ts +40 -0
  284. package/dist/inspector/overlay/overlayGeometry.js +59 -0
  285. package/dist/inspector/overlay/selectedGeometry.d.ts +7 -0
  286. package/dist/inspector/overlay/selectedGeometry.js +51 -0
  287. package/dist/inspector/overlay/structuralGestures.d.ts +28 -0
  288. package/dist/inspector/overlay/structuralGestures.js +180 -0
  289. package/dist/inspector/projection/cssEscapes.d.ts +3 -0
  290. package/dist/inspector/projection/cssEscapes.js +20 -0
  291. package/dist/inspector/projection/managedStylesheet.d.ts +33 -0
  292. package/dist/inspector/projection/managedStylesheet.js +240 -0
  293. package/dist/inspector/projection/renderedInstance.d.ts +56 -0
  294. package/dist/inspector/projection/renderedInstance.js +306 -0
  295. package/dist/inspector/projection/structuralProjection.d.ts +93 -0
  296. package/dist/inspector/projection/structuralProjection.js +560 -0
  297. package/dist/inspector/projection/structuralProjectionBoundary.d.ts +5 -0
  298. package/dist/inspector/projection/structuralProjectionBoundary.js +65 -0
  299. package/dist/inspector/projection/textProjection.d.ts +53 -0
  300. package/dist/inspector/projection/textProjection.js +705 -0
  301. package/dist/inspector/projection/workspaceProjection.d.ts +43 -0
  302. package/dist/inspector/projection/workspaceProjection.js +58 -0
  303. package/dist/inspector/prompt/PromptSettingsDialog.d.ts +15 -0
  304. package/dist/inspector/prompt/PromptSettingsDialog.js +17 -0
  305. package/dist/inspector/prompt/clipboardHandoff.d.ts +34 -0
  306. package/dist/inspector/prompt/clipboardHandoff.js +212 -0
  307. package/dist/inspector/prompt/copyToClipboard.d.ts +1 -0
  308. package/dist/inspector/prompt/copyToClipboard.js +34 -0
  309. package/dist/inspector/prompt/detectFramework.d.ts +6 -0
  310. package/dist/inspector/prompt/detectFramework.js +4 -0
  311. package/dist/inspector/prompt/generatePrompt.d.ts +7 -0
  312. package/dist/inspector/prompt/generatePrompt.js +391 -0
  313. package/dist/inspector/prompt/promptSettings.d.ts +8 -0
  314. package/dist/inspector/prompt/promptSettings.js +28 -0
  315. package/dist/inspector/runtime/devFlag.d.ts +28 -0
  316. package/dist/inspector/runtime/devFlag.js +50 -0
  317. package/dist/inspector/runtime/documentStylesheetOrder.d.ts +19 -0
  318. package/dist/inspector/runtime/documentStylesheetOrder.js +89 -0
  319. package/dist/inspector/runtime/domRealm.d.ts +4 -0
  320. package/dist/inspector/runtime/domRealm.js +11 -0
  321. package/dist/inspector/runtime/runtimeConfig.d.ts +119 -0
  322. package/dist/inspector/runtime/runtimeConfig.js +276 -0
  323. package/dist/inspector/runtime/staticHtmlRuntimeIdentity.d.ts +32 -0
  324. package/dist/inspector/runtime/staticHtmlRuntimeIdentity.js +149 -0
  325. package/dist/inspector/runtime/useRuntimeConfig.d.ts +10 -0
  326. package/dist/inspector/runtime/useRuntimeConfig.js +13 -0
  327. package/dist/inspector/selection/editScope.d.ts +32 -0
  328. package/dist/inspector/selection/editScope.js +140 -0
  329. package/dist/inspector/selection/editTarget.d.ts +8 -0
  330. package/dist/inspector/selection/editTarget.js +11 -0
  331. package/dist/inspector/selection/hierarchy.d.ts +7 -0
  332. package/dist/inspector/selection/hierarchy.js +42 -0
  333. package/dist/inspector/selection/resolveSelection.d.ts +10 -0
  334. package/dist/inspector/selection/resolveSelection.js +60 -0
  335. package/dist/inspector/selection/selectionStore.d.ts +41 -0
  336. package/dist/inspector/selection/selectionStore.js +262 -0
  337. package/dist/inspector/selection/selectionTarget.d.ts +5 -0
  338. package/dist/inspector/selection/selectionTarget.js +50 -0
  339. package/dist/inspector/selection/sourceSite.d.ts +2 -0
  340. package/dist/inspector/selection/sourceSite.js +12 -0
  341. package/dist/inspector/selection/styleSelection.d.ts +22 -0
  342. package/dist/inspector/selection/styleSelection.js +104 -0
  343. package/dist/inspector/session/index.d.ts +3 -0
  344. package/dist/inspector/session/index.js +2 -0
  345. package/dist/inspector/session/lifecycle.d.ts +22 -0
  346. package/dist/inspector/session/lifecycle.js +63 -0
  347. package/dist/inspector/session/sessionContext.d.ts +21 -0
  348. package/dist/inspector/session/sessionContext.js +28 -0
  349. package/dist/inspector/session/sessionFactory.d.ts +29 -0
  350. package/dist/inspector/session/sessionFactory.js +73 -0
  351. package/dist/inspector/settings/SettingsDialog.d.ts +12 -0
  352. package/dist/inspector/settings/SettingsDialog.js +46 -0
  353. package/dist/inspector/shell/AppShell.d.ts +2 -0
  354. package/dist/inspector/shell/AppShell.js +9 -0
  355. package/dist/inspector/shell/ChangesLog.d.ts +6 -0
  356. package/dist/inspector/shell/ChangesLog.js +92 -0
  357. package/dist/inspector/shell/CopyPromptButton.d.ts +9 -0
  358. package/dist/inspector/shell/CopyPromptButton.js +159 -0
  359. package/dist/inspector/shell/DomNavigation.d.ts +8 -0
  360. package/dist/inspector/shell/DomNavigation.js +30 -0
  361. package/dist/inspector/shell/EmptyState.d.ts +2 -0
  362. package/dist/inspector/shell/EmptyState.js +15 -0
  363. package/dist/inspector/shell/InspectorShell.d.ts +11 -0
  364. package/dist/inspector/shell/InspectorShell.js +268 -0
  365. package/dist/inspector/shell/openStore.d.ts +6 -0
  366. package/dist/inspector/shell/openStore.js +29 -0
  367. package/dist/inspector/shell/panelLayout.d.ts +2 -0
  368. package/dist/inspector/shell/panelLayout.js +29 -0
  369. package/dist/inspector/shell/shortcuts.d.ts +3 -0
  370. package/dist/inspector/shell/shortcuts.js +25 -0
  371. package/dist/inspector/shell/stateValue.d.ts +3 -0
  372. package/dist/inspector/shell/stateValue.js +34 -0
  373. package/dist/inspector/shell/styleState.d.ts +7 -0
  374. package/dist/inspector/shell/styleState.js +13 -0
  375. package/dist/inspector/spacing/projection.d.ts +43 -0
  376. package/dist/inspector/spacing/projection.js +136 -0
  377. package/dist/inspector/styleEditors/AppearanceSection.d.ts +13 -0
  378. package/dist/inspector/styleEditors/AppearanceSection.js +6 -0
  379. package/dist/inspector/styleEditors/AspectRatioField.d.ts +17 -0
  380. package/dist/inspector/styleEditors/AspectRatioField.js +10 -0
  381. package/dist/inspector/styleEditors/BorderEditor.d.ts +13 -0
  382. package/dist/inspector/styleEditors/BorderEditor.js +295 -0
  383. package/dist/inspector/styleEditors/BorderRadiusEditor.d.ts +14 -0
  384. package/dist/inspector/styleEditors/BorderRadiusEditor.js +108 -0
  385. package/dist/inspector/styleEditors/BoxShadowEditor.d.ts +13 -0
  386. package/dist/inspector/styleEditors/BoxShadowEditor.js +13 -0
  387. package/dist/inspector/styleEditors/ColorPicker.d.ts +15 -0
  388. package/dist/inspector/styleEditors/ColorPicker.js +73 -0
  389. package/dist/inspector/styleEditors/GapField.d.ts +17 -0
  390. package/dist/inspector/styleEditors/GapField.js +12 -0
  391. package/dist/inspector/styleEditors/GridChildSection.d.ts +14 -0
  392. package/dist/inspector/styleEditors/GridChildSection.js +91 -0
  393. package/dist/inspector/styleEditors/GridPicker.d.ts +13 -0
  394. package/dist/inspector/styleEditors/GridPicker.js +179 -0
  395. package/dist/inspector/styleEditors/GridSection.d.ts +17 -0
  396. package/dist/inspector/styleEditors/GridSection.js +27 -0
  397. package/dist/inspector/styleEditors/GridValueField.d.ts +17 -0
  398. package/dist/inspector/styleEditors/GridValueField.js +70 -0
  399. package/dist/inspector/styleEditors/InsetSection.d.ts +15 -0
  400. package/dist/inspector/styleEditors/InsetSection.js +15 -0
  401. package/dist/inspector/styleEditors/LayoutBlockedIndicator.d.ts +6 -0
  402. package/dist/inspector/styleEditors/LayoutBlockedIndicator.js +6 -0
  403. package/dist/inspector/styleEditors/LayoutComboField.d.ts +18 -0
  404. package/dist/inspector/styleEditors/LayoutComboField.js +138 -0
  405. package/dist/inspector/styleEditors/LayoutDropdown.d.ts +14 -0
  406. package/dist/inspector/styleEditors/LayoutDropdown.js +34 -0
  407. package/dist/inspector/styleEditors/LayoutSection.d.ts +13 -0
  408. package/dist/inspector/styleEditors/LayoutSection.js +342 -0
  409. package/dist/inspector/styleEditors/OpacityEditor.d.ts +13 -0
  410. package/dist/inspector/styleEditors/OpacityEditor.js +34 -0
  411. package/dist/inspector/styleEditors/PositionInsets.d.ts +15 -0
  412. package/dist/inspector/styleEditors/PositionInsets.js +12 -0
  413. package/dist/inspector/styleEditors/SpacingBox.d.ts +29 -0
  414. package/dist/inspector/styleEditors/SpacingBox.js +189 -0
  415. package/dist/inspector/styleEditors/Typography.d.ts +13 -0
  416. package/dist/inspector/styleEditors/Typography.js +137 -0
  417. package/dist/inspector/styleEditors/completeCssValue.d.ts +8 -0
  418. package/dist/inspector/styleEditors/completeCssValue.js +34 -0
  419. package/dist/inspector/styleEditors/gridChildModel.d.ts +74 -0
  420. package/dist/inspector/styleEditors/gridChildModel.js +138 -0
  421. package/dist/inspector/styleEditors/layoutValue.d.ts +24 -0
  422. package/dist/inspector/styleEditors/layoutValue.js +103 -0
  423. package/dist/inspector/styleEditors/nudgeValue.d.ts +8 -0
  424. package/dist/inspector/styleEditors/nudgeValue.js +71 -0
  425. package/dist/inspector/styleEditors/rowLookup.d.ts +11 -0
  426. package/dist/inspector/styleEditors/rowLookup.js +13 -0
  427. package/dist/inspector/styleEditors/stringRecord.d.ts +4 -0
  428. package/dist/inspector/styleEditors/stringRecord.js +1 -0
  429. package/dist/inspector/styleEditors/valuePolicy.d.ts +20 -0
  430. package/dist/inspector/styleEditors/valuePolicy.js +82 -0
  431. package/dist/inspector/testing.d.ts +10 -0
  432. package/dist/inspector/testing.js +9 -0
  433. package/dist/inspector/tokens/TokenChip.d.ts +24 -0
  434. package/dist/inspector/tokens/TokenChip.js +23 -0
  435. package/dist/inspector/tokens/TokenDropdown.d.ts +13 -0
  436. package/dist/inspector/tokens/TokenDropdown.js +59 -0
  437. package/dist/inspector/tokens/TokenField.d.ts +68 -0
  438. package/dist/inspector/tokens/TokenField.js +485 -0
  439. package/dist/inspector/tokens/TokenLabel.d.ts +7 -0
  440. package/dist/inspector/tokens/TokenLabel.js +23 -0
  441. package/dist/inspector/tokens/TokensPanel.d.ts +5 -0
  442. package/dist/inspector/tokens/TokensPanel.js +47 -0
  443. package/dist/inspector/tokens/catalog.d.ts +51 -0
  444. package/dist/inspector/tokens/catalog.js +184 -0
  445. package/dist/inspector/tokens/editActions.d.ts +35 -0
  446. package/dist/inspector/tokens/editActions.js +164 -0
  447. package/dist/inspector/tokens/resolution/cascade.d.ts +14 -0
  448. package/dist/inspector/tokens/resolution/cascade.js +31 -0
  449. package/dist/inspector/tokens/resolution/cssomCollector.d.ts +43 -0
  450. package/dist/inspector/tokens/resolution/cssomCollector.js +528 -0
  451. package/dist/inspector/tokens/resolution/selectorSemantics.d.ts +12 -0
  452. package/dist/inspector/tokens/resolution/selectorSemantics.js +106 -0
  453. package/dist/inspector/tokens/resolution.d.ts +56 -0
  454. package/dist/inspector/tokens/resolution.js +1401 -0
  455. package/dist/inspector/tokens/tokenEdits.d.ts +3 -0
  456. package/dist/inspector/tokens/tokenEdits.js +22 -0
  457. package/dist/inspector/tokens/valueSemanticsAdapter.d.ts +6 -0
  458. package/dist/inspector/tokens/valueSemanticsAdapter.js +68 -0
  459. package/dist/inspector/ui/AtRuleContext.d.ts +18 -0
  460. package/dist/inspector/ui/AtRuleContext.js +54 -0
  461. package/dist/inspector/ui/Button.d.ts +9 -0
  462. package/dist/inspector/ui/Button.js +4 -0
  463. package/dist/inspector/ui/ColorSwatch.d.ts +7 -0
  464. package/dist/inspector/ui/ColorSwatch.js +6 -0
  465. package/dist/inspector/ui/ControlSurface.d.ts +14 -0
  466. package/dist/inspector/ui/ControlSurface.js +10 -0
  467. package/dist/inspector/ui/FieldRow.d.ts +14 -0
  468. package/dist/inspector/ui/FieldRow.js +15 -0
  469. package/dist/inspector/ui/IconButton.d.ts +14 -0
  470. package/dist/inspector/ui/IconButton.js +5 -0
  471. package/dist/inspector/ui/InspectorPopover.d.ts +17 -0
  472. package/dist/inspector/ui/InspectorPopover.js +13 -0
  473. package/dist/inspector/ui/PopoverListbox.d.ts +37 -0
  474. package/dist/inspector/ui/PopoverListbox.js +21 -0
  475. package/dist/inspector/ui/SegmentedControl.d.ts +24 -0
  476. package/dist/inspector/ui/SegmentedControl.js +16 -0
  477. package/dist/inspector/ui/Select.d.ts +25 -0
  478. package/dist/inspector/ui/Select.js +56 -0
  479. package/dist/inspector/ui/SideValuesField.d.ts +44 -0
  480. package/dist/inspector/ui/SideValuesField.js +76 -0
  481. package/dist/inspector/ui/StatusCallout.d.ts +9 -0
  482. package/dist/inspector/ui/StatusCallout.js +4 -0
  483. package/dist/inspector/ui/TextInput.d.ts +12 -0
  484. package/dist/inspector/ui/TextInput.js +5 -0
  485. package/dist/inspector/ui/ToggleButton.d.ts +11 -0
  486. package/dist/inspector/ui/ToggleButton.js +6 -0
  487. package/dist/inspector/ui/assets/grid.svg +14 -0
  488. package/dist/inspector/ui/css.d.ts +9 -0
  489. package/dist/inspector/ui/labels.d.ts +1 -0
  490. package/dist/inspector/ui/labels.js +7 -0
  491. package/dist/inspector/ui/styles.d.ts +1 -0
  492. package/dist/inspector/ui/styles.js +68 -0
  493. package/dist/inspector/virtual-modules.d.ts +7 -0
  494. package/dist/inspector/vite-env.d.ts +10 -0
  495. package/dist/internal/agent-protocol.d.ts +232 -0
  496. package/dist/internal/agent-protocol.js +237 -0
  497. package/dist/nudge-ui.mjs +15722 -0
  498. package/dist/project/files.d.ts +19 -0
  499. package/dist/project/files.js +226 -0
  500. package/dist/project/identity.d.ts +6 -0
  501. package/dist/project/identity.js +19 -0
  502. package/dist/project/pathPolicy.d.ts +8 -0
  503. package/dist/project/pathPolicy.js +12 -0
  504. package/dist/project/tokens.d.ts +36 -0
  505. package/dist/project/tokens.js +223 -0
  506. package/dist/transport/index.d.ts +8 -0
  507. package/dist/transport/index.js +8 -0
  508. package/dist/transport/routes.d.ts +13 -0
  509. package/dist/transport/routes.js +16 -0
  510. package/package.json +137 -0
@@ -0,0 +1,1401 @@
1
+ import { readTailwindV4AlphaUtility, tailwindV4AlphaExpression } from "../../css/dialects/index.js";
2
+ import { INTERACTION_STATES } from "../shell/styleState.js";
3
+ import { getElementComputedStyle } from "../runtime/domRealm.js";
4
+ import { collectRules as collectCssomRules, documentRevisions as getDocumentRevisions, registerResolutionElement, } from "./resolution/cssomCollector.js";
5
+ import { computeSpecificity } from "./resolution/selectorSemantics.js";
6
+ import { compareAuthorCascade } from "./resolution/cascade.js";
7
+ export { invalidateStyleResolutionCache } from "./resolution/cssomCollector.js";
8
+ import { interpretValue, normalizeOpacityPercent, } from "../../css/value-semantics/index.js";
9
+ import { createInspectorValueContext, inspectorTokenOrigin } from "./valueSemanticsAdapter.js";
10
+ import { getNudgeUiRuntimeConfig } from "../runtime/runtimeConfig.js";
11
+ /**
12
+ * Builds (or reuses) the document's CSSOM rule snapshot ahead of a resolution
13
+ * sweep. Idempotent: the walk runs once per stylesheet revision and is a cache
14
+ * hit afterwards, so a scheduler can warm it in its own frame to keep the
15
+ * subsequent resolution sweep's blocking time small.
16
+ */
17
+ export function prewarmCssomRuleSnapshot(doc) {
18
+ collectCssomRules(doc);
19
+ }
20
+ const MAX_PROPERTIES = 100;
21
+ const EMPTY_LOCAL_ALIASES = new Map();
22
+ const tokenTableMemo = new WeakMap();
23
+ export function buildTokenTable(entries) {
24
+ const cached = tokenTableMemo.get(entries);
25
+ if (cached)
26
+ return cached;
27
+ const table = {};
28
+ for (const entry of entries) {
29
+ table[entry.name] = entry;
30
+ if (entry.cssName)
31
+ table[entry.cssName] = entry;
32
+ }
33
+ tokenTableMemo.set(entries, table);
34
+ return table;
35
+ }
36
+ /**
37
+ * Returns true when a `calc()` expression is safe to treat as a simple
38
+ * numeric value. We exclude percentages, viewport units, and font-relative
39
+ * units because those depend on context the browser cannot freeze into a
40
+ * single pixel value safely.
41
+ */
42
+ function canBecomeNumeric(value) {
43
+ const v = value.trim();
44
+ if (/\b(?:min|max|clamp|env|anchor-size)\s*\(/i.test(v))
45
+ return false;
46
+ const m = /^calc\s*\(/i.exec(v);
47
+ if (!m)
48
+ return false;
49
+ const inner = v.slice(m[0].length, -1).trim();
50
+ const withoutVars = inner.replace(/var\([^)]+\)/g, "");
51
+ return !/\b\d+(?:\.\d+)?(?:%|vw|vh|vmin|vmax|dvw|dvh|sv[lw]h|lv[lw]h|[ce]m|ex|ch)\b/i.test(withoutVars);
52
+ }
53
+ let tableCache = null;
54
+ let tableSource = null;
55
+ export function getTokenTable() {
56
+ const { tokens } = getNudgeUiRuntimeConfig();
57
+ if (tableCache !== null && tableSource === tokens)
58
+ return tableCache;
59
+ tableCache = buildTokenTable(tokens);
60
+ tableSource = tokens;
61
+ return tableCache;
62
+ }
63
+ function isCustomPropertyToken(definition) {
64
+ return definition.cssName.startsWith("--");
65
+ }
66
+ function entryFromDefinition(definition, value) {
67
+ return {
68
+ name: definition.name,
69
+ cssName: definition.cssName,
70
+ value,
71
+ source: definition.declarations[0]?.source ?? "",
72
+ cssValue: definition.cssValue,
73
+ adapter: definition.adapter,
74
+ origin: definition.origin,
75
+ editable: definition.editable,
76
+ };
77
+ }
78
+ const tokenEntriesCache = new WeakMap();
79
+ function registerWithAncestors(el) {
80
+ let current = el;
81
+ while (current) {
82
+ registerResolutionElement(current);
83
+ current = current.parentElement;
84
+ }
85
+ }
86
+ /**
87
+ * The build-time catalog is intentionally an inventory of every project token.
88
+ * Element edits must instead use only custom properties resolved in that
89
+ * element's cascade; a token defined by a lazy stylesheet is not usable until
90
+ * that stylesheet is attached to the document. Entries are cached per element
91
+ * until the element or stylesheet revision changes; the derived table reuses
92
+ * `buildTokenTable`'s input-identity memo.
93
+ */
94
+ export function getAvailableTokenEntriesForElement(el, definitions = getNudgeUiRuntimeConfig().tokenCatalog) {
95
+ const revisions = getDocumentRevisions(el.ownerDocument ?? document);
96
+ const cached = tokenEntriesCache.get(el);
97
+ if (cached && cached.elementRevision === revisions.element
98
+ && cached.stylesheetRevision === revisions.stylesheet
99
+ && cached.definitions === definitions) {
100
+ return cached.entries;
101
+ }
102
+ registerWithAncestors(el);
103
+ const computed = getElementComputedStyle(el);
104
+ const available = definitions.flatMap((definition) => {
105
+ if (!isCustomPropertyToken(definition)) {
106
+ // Literal adapters (for example Tailwind v3) do not have a browser
107
+ // custom property to probe. Their adapter owns their availability.
108
+ return [entryFromDefinition(definition, definition.declarations[0]?.value ?? "")];
109
+ }
110
+ const value = computed.getPropertyValue(definition.cssName).trim();
111
+ return value ? [entryFromDefinition(definition, value)] : [];
112
+ });
113
+ const intermediateTable = buildTokenTable(available);
114
+ const entries = available.map((entry) => ({
115
+ ...entry,
116
+ value: resolveTokenValue(entry.value, intermediateTable).resolvedValue,
117
+ }));
118
+ tokenEntriesCache.set(el, {
119
+ elementRevision: revisions.element,
120
+ stylesheetRevision: revisions.stylesheet,
121
+ definitions,
122
+ entries,
123
+ });
124
+ return entries;
125
+ }
126
+ /**
127
+ * Replaces build-time token declaration hints with declarations serialized by
128
+ * the browser from the stylesheets currently attached to this document.
129
+ */
130
+ function hydrateTokenCatalogFromCssom(definitions, doc = document) {
131
+ const needsHydration = (definition) => definition.declarations.length === 0
132
+ || (definition.adapter === "vanilla-extract" && definition.declarations.every((declaration) => declaration.value.trim() === `var(${definition.cssName})`
133
+ && !declaration.context.selector
134
+ && !declaration.context.wrappers?.length));
135
+ const known = new Set(definitions.filter(needsHydration).map((definition) => definition.cssName));
136
+ const declarations = new Map();
137
+ for (const rule of collectCssomRules(doc).rules) {
138
+ if (rule.source === "#nudge-ui-styles")
139
+ continue;
140
+ for (const declaration of rule.declarations) {
141
+ if (!known.has(declaration.property))
142
+ continue;
143
+ const wrappers = [
144
+ ...(rule.layer ? [{ kind: "layer", params: rule.layer }] : []),
145
+ ...(rule.atRules ?? []).flatMap((atRule) => atRule.kind === "media" || atRule.kind === "supports"
146
+ ? [{ kind: atRule.kind, params: atRule.params }]
147
+ : []),
148
+ ];
149
+ const list = declarations.get(declaration.property) ?? [];
150
+ list.push({
151
+ id: `${declaration.property}\u0000${rule.source ?? "cssom"}\u0000${rule.sourceOrder ?? list.length}`,
152
+ order: rule.sourceOrder,
153
+ value: declaration.value,
154
+ source: rule.source ?? "cssom",
155
+ important: Boolean(declaration.important),
156
+ context: {
157
+ selector: rule.selectorText,
158
+ ...(wrappers.length > 0 ? { wrappers } : {}),
159
+ },
160
+ });
161
+ declarations.set(declaration.property, list);
162
+ }
163
+ }
164
+ return definitions.map((definition) => {
165
+ if (!needsHydration(definition))
166
+ return definition;
167
+ const accepted = declarations.get(definition.cssName);
168
+ return accepted?.length ? { ...definition, declarations: accepted } : definition;
169
+ });
170
+ }
171
+ function sourceFile(source) {
172
+ return source.replace(/:\d+$/, "").split(/[?#]/, 1)[0] ?? source;
173
+ }
174
+ function normalizedPath(value) {
175
+ return decodeURIComponent(value).replace(/\\/g, "/").replace(/^file:\/\//, "").replace(/\/+$/, "");
176
+ }
177
+ function loadedStylesheetSources(doc) {
178
+ const sourceIdentityByPath = new Map();
179
+ for (const node of doc.querySelectorAll('style[data-vite-dev-id], link[rel~="stylesheet"][href]')) {
180
+ const providesAuthoredIdentity = node.tagName === "STYLE";
181
+ const source = providesAuthoredIdentity
182
+ ? node.dataset.viteDevId
183
+ : node.getAttribute("href");
184
+ if (!source)
185
+ continue;
186
+ const path = normalizedPath(source.split(/[?#]/, 1)[0] ?? source);
187
+ sourceIdentityByPath.set(path, providesAuthoredIdentity || sourceIdentityByPath.get(path) === true);
188
+ }
189
+ return Array.from(sourceIdentityByPath, ([path, providesAuthoredIdentity]) => ({
190
+ path,
191
+ providesAuthoredIdentity,
192
+ }));
193
+ }
194
+ function isLoadedCssSource(source, loadedSources) {
195
+ const file = sourceFile(source);
196
+ if (!/\.css$/i.test(file) || loadedSources.length === 0)
197
+ return true;
198
+ const normalizedFile = normalizedPath(file);
199
+ return loadedSources.some((loaded) => loaded === normalizedFile
200
+ || loaded.endsWith(`/${normalizedFile}`)
201
+ || normalizedFile.endsWith(`/${loaded}`));
202
+ }
203
+ /**
204
+ * Returns stylesheet identities only when the browser gave us a complete,
205
+ * authored-source mapping. A compiled host can expose a mixture of source-like
206
+ * and opaque CSS URLs; treating the mapped subset as complete would make
207
+ * declarations behind the opaque URLs look lazy even while their variables are
208
+ * live in the document.
209
+ */
210
+ function confidentlyLoadedStylesheetSources(definitions, loadedSources) {
211
+ const cssSources = definitions.flatMap((definition) => definition.declarations
212
+ .map((declaration) => declaration.source)
213
+ .filter((source) => /\.css$/i.test(sourceFile(source))));
214
+ const known = new Set();
215
+ for (const loaded of loadedSources) {
216
+ if (loaded.providesAuthoredIdentity
217
+ || cssSources.some((source) => isLoadedCssSource(source, [loaded.path]))) {
218
+ known.add(loaded.path);
219
+ continue;
220
+ }
221
+ // One opaque compiled URL can contain any authored declaration, so the
222
+ // document does not provide enough evidence to remove unloaded sources.
223
+ return [];
224
+ }
225
+ return [...known];
226
+ }
227
+ /**
228
+ * Produces the page catalog used by the global Tokens settings section. It retains the
229
+ * build-time inventory separately, while removing declarations from CSS files
230
+ * that have not loaded when the document exposes mappable source identities
231
+ * (such as Vite's lazy route stylesheets). Opaque compiled URLs do not narrow
232
+ * the adapter-supplied catalog.
233
+ */
234
+ export function getAvailableTokenCatalog(root = document.documentElement, definitions = getNudgeUiRuntimeConfig().tokenCatalog) {
235
+ const computed = getElementComputedStyle(root);
236
+ const hydrated = hydrateTokenCatalogFromCssom(definitions, root.ownerDocument ?? document);
237
+ const loadedSources = confidentlyLoadedStylesheetSources(hydrated, loadedStylesheetSources(root.ownerDocument ?? document));
238
+ return hydrated.flatMap((definition) => {
239
+ if (!isCustomPropertyToken(definition))
240
+ return [definition];
241
+ if (!computed.getPropertyValue(definition.cssName).trim())
242
+ return [];
243
+ const declarations = definition.declarations.filter((declaration) => isLoadedCssSource(declaration.source, loadedSources));
244
+ return declarations.length > 0 ? [{ ...definition, declarations }] : [];
245
+ });
246
+ }
247
+ function normalizeInElementContext(el, property, value) {
248
+ const doc = el.ownerDocument;
249
+ const probe = doc.createElement(el.tagName.toLowerCase());
250
+ probe.setAttribute("data-nudge-ui", "attribution-probe");
251
+ probe.style.setProperty(property, value, "important");
252
+ probe.style.setProperty("position", "fixed", "important");
253
+ probe.style.setProperty("visibility", "hidden", "important");
254
+ el.parentElement?.insertBefore(probe, el.nextSibling);
255
+ if (!probe.isConnected)
256
+ doc.body.appendChild(probe);
257
+ const normalized = getElementComputedStyle(probe).getPropertyValue(property).trim();
258
+ probe.remove();
259
+ return normalized;
260
+ }
261
+ function candidateMatchesPainted(el, row, painted) {
262
+ if (!row.tokenName || !/^var\(\s*--[\w-]+\s*\)$/.test(row.declaredValue))
263
+ return false;
264
+ return normalizeInElementContext(el, row.property, row.declaredValue) === painted.trim();
265
+ }
266
+ /**
267
+ * Resolves one authored value through the value-semantics Module using the
268
+ * inspector's integration context. Used by the token-availability path; the
269
+ * value Module is the sole interpretation authority.
270
+ */
271
+ function resolveTokenValue(value, tokenTable, localAliases = EMPTY_LOCAL_ALIASES) {
272
+ return interpretValue("--nudge-ui-token", value, createInspectorValueContext(tokenTable, localAliases))[0];
273
+ }
274
+ function directionalityFromComputed(el, computed) {
275
+ return {
276
+ direction: computed?.direction || el?.dir || "ltr",
277
+ writingMode: computed?.getPropertyValue("writing-mode").trim() || "horizontal-tb",
278
+ };
279
+ }
280
+ function elementDirectionality(el) {
281
+ return directionalityFromComputed(el, getElementComputedStyle(el));
282
+ }
283
+ function isLogicalBoxProperty(property) {
284
+ return /^(?:margin|padding|inset)-(?:inline|block)(?:-(?:start|end))?$/i.test(property);
285
+ }
286
+ /**
287
+ * Coordinates cascade facts with the value-semantics Module. All property-family
288
+ * decomposition (logical sides, border, font, radius corners, physical spacing)
289
+ * lives in `interpretValue`; this function only supplies the token
290
+ * context and directionality facts, then projects the Module's fields onto the
291
+ * `ResolvedDeclaration` shape.
292
+ */
293
+ function resolveDeclaration(declaration, tokenTable, localAliases = EMPTY_LOCAL_ALIASES, directionality) {
294
+ const fields = interpretValue(declaration.property, declaration.value, createInspectorValueContext(tokenTable, localAliases, directionality));
295
+ return fields.map((field) => ({
296
+ property: field.property,
297
+ declaredValue: field.declaredValue,
298
+ sourceProperty: field.sourceProperty,
299
+ tokenName: field.tokenName,
300
+ resolvedValue: field.resolvedValue,
301
+ important: declaration.important,
302
+ tokens: field.tokens,
303
+ opacity: field.opacity,
304
+ propertyOpacity: field.propertyOpacity,
305
+ color: field.color,
306
+ modifiers: field.modifiers,
307
+ capability: field.capability,
308
+ resolvedTokenValue: field.resolvedValue,
309
+ ...(field.structure ? { structure: field.structure } : {}),
310
+ ...(field.diagnostic ? { diagnostic: field.diagnostic } : {}),
311
+ }));
312
+ }
313
+ function hydratePropertyOpacity(row, computedValue) {
314
+ if (row.property.toLowerCase() !== "opacity")
315
+ return;
316
+ const value = normalizeOpacityPercent(computedValue);
317
+ if (value === null)
318
+ return;
319
+ const existing = row.propertyOpacity;
320
+ const token = existing?.token
321
+ ?? (row.tokenName ? row.tokens?.find((reference) => reference.name === row.tokenName) : undefined);
322
+ row.propertyOpacity = {
323
+ value,
324
+ authoredValue: existing?.authoredValue ?? row.authored ?? row.declaredValue,
325
+ tokenName: existing?.tokenName ?? row.tokenName,
326
+ ...(token ? { token } : {}),
327
+ editable: existing?.editable ?? false,
328
+ };
329
+ }
330
+ function hydratePropertyOpacityRows(rows, computed) {
331
+ for (const row of rows)
332
+ hydratePropertyOpacity(row, computed.getPropertyValue(row.property));
333
+ }
334
+ function capabilityFor(property, value, tokenTable) {
335
+ return interpretValue(property, value, createInspectorValueContext(tokenTable))[0].capability;
336
+ }
337
+ let containerProbeSequence = 0;
338
+ /**
339
+ * Container conditions are element-relative. CSSOM exposes their text but has
340
+ * no `matches` API, so ask the browser by applying an inert custom property to
341
+ * the selected element inside an equivalent temporary @container wrapper.
342
+ */
343
+ function matchesContainerQuery(el, params) {
344
+ const doc = el.ownerDocument;
345
+ if (!doc.head || !params)
346
+ return false;
347
+ const id = ++containerProbeSequence;
348
+ const marker = `data-container-probe-${id}`;
349
+ const property = `--container-probe-${id}`;
350
+ const style = doc.createElement("style");
351
+ style.setAttribute("data-nudge-ui", "container-probe");
352
+ style.textContent = `@container ${params} { [${marker}] { ${property}: 1; } }`;
353
+ el.setAttribute(marker, "");
354
+ doc.head.appendChild(style);
355
+ try {
356
+ return getElementComputedStyle(el).getPropertyValue(property).trim() === "1";
357
+ }
358
+ catch {
359
+ return false;
360
+ }
361
+ finally {
362
+ style.remove();
363
+ el.removeAttribute(marker);
364
+ }
365
+ }
366
+ function atRulesApplyToElement(el, atRules) {
367
+ const view = el.ownerDocument.defaultView;
368
+ return (atRules ?? []).every((atRule) => {
369
+ if (atRule.kind === "container")
370
+ return matchesContainerQuery(el, atRule.params);
371
+ if (atRule.kind === "supports")
372
+ return view?.CSS?.supports(atRule.params) ?? false;
373
+ return true;
374
+ });
375
+ }
376
+ function specificityForBranch(rule, branch) {
377
+ // Single-branch selectors reuse the specificity collected from CSSOM; the
378
+ // matched branch is the whole selector. Multi-branch selectors need the
379
+ // matched branch's own weight, so recompute per branch.
380
+ return rule.selectorText.includes(",") ? computeSpecificity(branch) : rule.specificity;
381
+ }
382
+ function collectLocalAliases(el, rules, ruleApplies) {
383
+ // Custom properties inherit independently of the property being resolved.
384
+ // Resolve the winning declaration separately for each element in the
385
+ // ancestor chain, then let the nearest declaration override inherited ones.
386
+ // This covers local aliases such as --color-error and inherited page tokens
387
+ // such as --color-ink without widening the build-time global catalog.
388
+ const lineage = [];
389
+ let current = el;
390
+ while (current) {
391
+ lineage.push(current);
392
+ current = current.parentElement;
393
+ }
394
+ const aliases = new Map();
395
+ for (const element of lineage.reverse()) {
396
+ const candidates = new Map();
397
+ rules.forEach((rule, index) => {
398
+ if (rule.active === false)
399
+ return;
400
+ if (!ruleApplies(rule))
401
+ return;
402
+ const branch = matchingSelectorBranch(element, rule.selectorText);
403
+ if (!branch)
404
+ return;
405
+ const sourceOrder = rule.sourceOrder ?? index;
406
+ const specificity = specificityForBranch(rule, branch);
407
+ for (const declaration of rule.declarations) {
408
+ if (!declaration.property.startsWith("--"))
409
+ continue;
410
+ const candidate = {
411
+ value: declaration.value.trim(),
412
+ important: declaration.important,
413
+ layer: rule.layer,
414
+ layerOrder: rule.layerOrder,
415
+ specificity,
416
+ sourceOrder,
417
+ };
418
+ const previous = candidates.get(declaration.property);
419
+ if (!previous || compareAuthorCascade(candidate, previous) >= 0) {
420
+ candidates.set(declaration.property, candidate);
421
+ }
422
+ }
423
+ });
424
+ // Inline custom properties are also inherited by descendants. They are
425
+ // explicit cascade winners for their element, so include them at inline
426
+ // specificity without changing the managed-style rule contract.
427
+ for (const property of Array.from(element.style)) {
428
+ if (!property.startsWith("--"))
429
+ continue;
430
+ const candidate = {
431
+ value: element.style.getPropertyValue(property).trim(),
432
+ important: element.style.getPropertyPriority(property) === "important",
433
+ inline: true,
434
+ specificity: 100000000,
435
+ sourceOrder: Number.MAX_SAFE_INTEGER,
436
+ };
437
+ const previous = candidates.get(property);
438
+ if (!previous || compareAuthorCascade(candidate, previous) >= 0) {
439
+ candidates.set(property, candidate);
440
+ }
441
+ }
442
+ for (const [name, candidate] of candidates)
443
+ aliases.set(name, candidate.value);
444
+ }
445
+ return aliases;
446
+ }
447
+ function makeRuleApplies(el) {
448
+ const matchingContexts = new Map();
449
+ return (rule) => {
450
+ const atRules = rule.atRules;
451
+ if (!atRules || atRules.length === 0)
452
+ return true;
453
+ const key = JSON.stringify(atRules);
454
+ const cached = matchingContexts.get(key);
455
+ if (cached !== undefined)
456
+ return cached;
457
+ const result = atRulesApplyToElement(el, atRules);
458
+ matchingContexts.set(key, result);
459
+ return result;
460
+ };
461
+ }
462
+ const TRANSIENT_SELECTOR = /:(?:hover|active|focus|focus-visible|focus-within|visited|target)(?:\b|\()/;
463
+ const transformedRulesMemo = new WeakMap();
464
+ function rulesForTransform(rules, transform) {
465
+ let byTransform = transformedRulesMemo.get(rules);
466
+ if (!byTransform) {
467
+ byTransform = new Map();
468
+ transformedRulesMemo.set(rules, byTransform);
469
+ }
470
+ const cached = byTransform.get(transform);
471
+ if (cached)
472
+ return cached;
473
+ let transformed;
474
+ if (transform === "live") {
475
+ transformed = rules.map((rule) => ({ rule, selectorText: rule.selectorText }));
476
+ }
477
+ else if (transform === "stable") {
478
+ transformed = rules
479
+ .filter((rule) => !TRANSIENT_SELECTOR.test(rule.selectorText))
480
+ .map((rule) => ({ rule, selectorText: rule.selectorText }));
481
+ }
482
+ else {
483
+ transformed = rules.flatMap((rule) => {
484
+ const selectorText = selectorForState(rule.selectorText, transform);
485
+ return selectorText ? [{ rule, selectorText }] : [];
486
+ });
487
+ }
488
+ byTransform.set(transform, transformed);
489
+ return transformed;
490
+ }
491
+ function isElementSensitiveSelector(selector) {
492
+ let attributeDepth = 0;
493
+ let quote = null;
494
+ let escaped = false;
495
+ for (let index = 0; index < selector.length; index++) {
496
+ const character = selector[index];
497
+ if (quote) {
498
+ if (escaped)
499
+ escaped = false;
500
+ else if (character === "\\")
501
+ escaped = true;
502
+ else if (character === quote)
503
+ quote = null;
504
+ continue;
505
+ }
506
+ if (attributeDepth > 0) {
507
+ if (character === '"' || character === "'")
508
+ quote = character;
509
+ else if (character === "[")
510
+ attributeDepth++;
511
+ else if (character === "]")
512
+ attributeDepth--;
513
+ continue;
514
+ }
515
+ if (character === "[") {
516
+ attributeDepth = 1;
517
+ continue;
518
+ }
519
+ if (character === "+" || character === "~")
520
+ return true;
521
+ if (character !== ":")
522
+ continue;
523
+ if (selector[index + 1] === ":")
524
+ return true;
525
+ const pseudo = /^[A-Za-z-]+/.exec(selector.slice(index + 1))?.[0];
526
+ // :root is represented by the complete ancestor lineage. Other
527
+ // pseudo-classes can vary per concrete element without an attribute or
528
+ // sibling mutation (for example :checked, :visited, and :target).
529
+ if (pseudo && pseudo.toLowerCase() !== "root")
530
+ return true;
531
+ }
532
+ return false;
533
+ }
534
+ const sourceSiteMatchBucketsMemo = new WeakMap();
535
+ function sourceSiteMatchBuckets(rules, transform) {
536
+ let byTransform = sourceSiteMatchBucketsMemo.get(rules);
537
+ if (!byTransform) {
538
+ byTransform = new Map();
539
+ sourceSiteMatchBucketsMemo.set(rules, byTransform);
540
+ }
541
+ const cached = byTransform.get(transform);
542
+ if (cached)
543
+ return cached;
544
+ const cacheable = [];
545
+ const elementSensitive = [];
546
+ for (const entry of rulesForTransform(rules, transform)) {
547
+ (isElementSensitiveSelector(entry.selectorText) ? elementSensitive : cacheable).push(entry);
548
+ }
549
+ const buckets = { cacheable, elementSensitive };
550
+ byTransform.set(transform, buckets);
551
+ return buckets;
552
+ }
553
+ const SOURCE_SITE_CACHE_MAX = 4096;
554
+ let sourceSiteMatchCaches = new WeakMap();
555
+ let sourceSiteMatchCacheEntries = 0;
556
+ const concreteElementMatchCaches = new WeakMap();
557
+ // The "all matched" set (inactive rules included) is matched fresh against
558
+ // every lineage element on every resolution otherwise, duplicating the
559
+ // cached sweep's cost. State-independent selectors use the same revision-keyed
560
+ // memo shape as the active sweep. Element-sensitive selectors stay fresh: a
561
+ // checked state, sibling relationship, or similar browser state can change
562
+ // without a DOM mutation that this registry observes.
563
+ const allMatchesMemo = new WeakMap();
564
+ /** Test hook: clears the per-source-site matched-rule cache. */
565
+ export function resetSourceSiteMatchCache() {
566
+ sourceSiteMatchCaches = new WeakMap();
567
+ sourceSiteMatchCacheEntries = 0;
568
+ }
569
+ /** Test hook: number of distinct cached source-site match sets. */
570
+ export function sourceSiteMatchCacheSize() {
571
+ return sourceSiteMatchCacheEntries;
572
+ }
573
+ /**
574
+ * Captures selector-relevant state without serializing the whole document.
575
+ * Element and ancestor attributes cover the common source-site selectors while
576
+ * child/sibling-sensitive selectors are handled conservatively below.
577
+ */
578
+ function sourceSiteContextKey(el) {
579
+ const lineage = [];
580
+ let current = el;
581
+ while (current) {
582
+ const attributes = Array.from(current.attributes)
583
+ .filter((attribute) => attribute.name !== "data-renderer-id")
584
+ .sort((a, b) => a.name.localeCompare(b.name))
585
+ .map((attribute) => `${attribute.name}=${attribute.value}`)
586
+ .join("\u0002");
587
+ lineage.push(`${current.tagName}\u0003${attributes}`);
588
+ current = current.parentElement;
589
+ }
590
+ return lineage.join("\u0001");
591
+ }
592
+ /**
593
+ * Source-site identity key for the matched-rule cache. The element's class is
594
+ * part of the key because sibling instances of a source site can carry
595
+ * different classes (for example rows in a large list), which changes which
596
+ * rules match even though their `data-cid`/`data-src` are identical.
597
+ */
598
+ function sourceSiteKey(el, transform) {
599
+ const cid = el.getAttribute("data-cid") ?? "";
600
+ const src = el.getAttribute("data-src") ?? "";
601
+ const instance = el.getAttribute("data-projection-instance") ?? "";
602
+ const className = typeof el.className === "string" ? el.className : "";
603
+ return `${cid}\u0000${src}\u0000${instance}\u0000${className}\u0000${transform}`;
604
+ }
605
+ function matchRuleForElement(el, entry) {
606
+ const branch = matchingSelectorBranch(el, entry.selectorText);
607
+ if (!branch)
608
+ return null;
609
+ return {
610
+ rule: entry.rule,
611
+ selectorText: entry.selectorText,
612
+ branch,
613
+ specificity: specificityForBranch({ ...entry.rule, selectorText: entry.selectorText }, branch),
614
+ };
615
+ }
616
+ /**
617
+ * Captures the current match outcome for selectors whose truth can change
618
+ * without a document revision. This keeps the expensive resolved-row cache
619
+ * usable while invalidating it when states such as `checked` actually change.
620
+ */
621
+ function elementSensitiveMatchKey(el, rules, transform) {
622
+ const entries = sourceSiteMatchBuckets(rules, transform).elementSensitive;
623
+ if (entries.length === 0)
624
+ return "";
625
+ const matches = [];
626
+ let current = el;
627
+ let depth = 0;
628
+ while (current) {
629
+ for (const entry of entries) {
630
+ const branch = matchingSelectorBranch(current, entry.selectorText);
631
+ if (branch)
632
+ matches.push(`${depth}:${entry.rule.sourceOrder ?? 0}:${branch}`);
633
+ }
634
+ current = current.parentElement;
635
+ depth++;
636
+ }
637
+ return matches.join("\u0001");
638
+ }
639
+ /**
640
+ * Matches every transformed rule against one element. For elements carrying a
641
+ * source-site identity (`data-cid`) the selector-match result is cached per
642
+ * `(document, data-cid, data-src, data-projection-instance, transform, element and
643
+ * stylesheet revision, context)` so repeated selections and equivalent sibling instances of the
644
+ * same source site reuse the matched rule set. Elements without a stable
645
+ * identity, or selectors that depend on unsupported relationships, are matched
646
+ * fresh on every call.
647
+ */
648
+ function getCachedElementMatches(el, rules, transform) {
649
+ const { cacheable, elementSensitive } = sourceSiteMatchBuckets(rules, transform);
650
+ const collect = (entries) => {
651
+ const matched = [];
652
+ for (const entry of entries) {
653
+ if (entry.rule.active === false)
654
+ continue;
655
+ const match = matchRuleForElement(el, entry);
656
+ if (match)
657
+ matched.push(match);
658
+ }
659
+ return matched;
660
+ };
661
+ const cid = el.getAttribute("data-cid");
662
+ const doc = el.ownerDocument ?? document;
663
+ const revisions = getDocumentRevisions(doc);
664
+ if (!cid || cacheable.length === 0) {
665
+ let cachedMatches = [];
666
+ if (cacheable.length > 0) {
667
+ let cache = concreteElementMatchCaches.get(el);
668
+ if (!cache) {
669
+ cache = new Map();
670
+ concreteElementMatchCaches.set(el, cache);
671
+ }
672
+ const cached = cache.get(transform);
673
+ if (cached
674
+ && cached.elementRevision === revisions.element
675
+ && cached.stylesheetRevision === revisions.stylesheet) {
676
+ cachedMatches = cached.matched;
677
+ }
678
+ else {
679
+ cachedMatches = collect(cacheable);
680
+ cache.set(transform, {
681
+ elementRevision: revisions.element,
682
+ stylesheetRevision: revisions.stylesheet,
683
+ matched: cachedMatches,
684
+ });
685
+ }
686
+ }
687
+ const sensitiveMatches = elementSensitive.length > 0 ? collect(elementSensitive) : [];
688
+ return sensitiveMatches.length === 0 ? cachedMatches : [...cachedMatches, ...sensitiveMatches];
689
+ }
690
+ const key = `${sourceSiteKey(el, transform)}\u0000${sourceSiteContextKey(el)}`;
691
+ let cache = sourceSiteMatchCaches.get(doc);
692
+ if (!cache) {
693
+ cache = new Map();
694
+ sourceSiteMatchCaches.set(doc, cache);
695
+ }
696
+ const cached = cache.get(key);
697
+ let cachedMatches;
698
+ if (cached
699
+ && cached.elementRevision === revisions.element
700
+ && cached.stylesheetRevision === revisions.stylesheet) {
701
+ cachedMatches = cached.matched;
702
+ }
703
+ else {
704
+ cachedMatches = collect(cacheable);
705
+ if (sourceSiteMatchCacheEntries >= SOURCE_SITE_CACHE_MAX) {
706
+ sourceSiteMatchCaches = new WeakMap();
707
+ sourceSiteMatchCacheEntries = 0;
708
+ cache = new Map();
709
+ sourceSiteMatchCaches.set(doc, cache);
710
+ }
711
+ if (!cache.has(key))
712
+ sourceSiteMatchCacheEntries++;
713
+ cache.set(key, {
714
+ elementRevision: revisions.element,
715
+ stylesheetRevision: revisions.stylesheet,
716
+ matched: cachedMatches,
717
+ });
718
+ }
719
+ // Match element-sensitive selectors on every resolution. Browser state such
720
+ // as `checked`, `target`, or a sibling relationship can change without a DOM
721
+ // or stylesheet revision, so a revision-keyed entry can return stale rows.
722
+ const elementMatches = elementSensitive.length > 0 ? collect(elementSensitive) : [];
723
+ return elementMatches.length === 0 ? cachedMatches : [...cachedMatches, ...elementMatches];
724
+ }
725
+ /**
726
+ * Matches selectors without applying conditional wrappers. Resolution still
727
+ * uses the active-only set for cascade decisions; this set preserves inactive
728
+ * media-query alternatives for property attribution in the inspector.
729
+ * Memoized per (element, transform, revisions) like the cached sweep for
730
+ * state-independent selectors. Element-sensitive selectors stay fresh because
731
+ * their state can change without a revision bump (for example, `:checked`),
732
+ * and the "live" transform always keeps its raw selector set fresh.
733
+ */
734
+ function getAllElementMatches(el, rules, transform) {
735
+ if (transform === "live") {
736
+ return rulesForTransform(rules, transform).flatMap((entry) => {
737
+ const match = matchRuleForElement(el, entry);
738
+ return match ? [match] : [];
739
+ });
740
+ }
741
+ const { cacheable, elementSensitive } = sourceSiteMatchBuckets(rules, transform);
742
+ const collect = (entries) => entries.flatMap((entry) => {
743
+ const match = matchRuleForElement(el, entry);
744
+ return match ? [match] : [];
745
+ });
746
+ const doc = el.ownerDocument ?? document;
747
+ const revisions = getDocumentRevisions(doc);
748
+ let cachedMatches = [];
749
+ if (cacheable.length > 0) {
750
+ let byTransform = allMatchesMemo.get(el);
751
+ if (!byTransform) {
752
+ byTransform = new Map();
753
+ allMatchesMemo.set(el, byTransform);
754
+ }
755
+ const cached = byTransform.get(transform);
756
+ if (cached
757
+ && cached.elementRevision === revisions.element
758
+ && cached.stylesheetRevision === revisions.stylesheet) {
759
+ cachedMatches = cached.matched;
760
+ }
761
+ else {
762
+ cachedMatches = collect(cacheable);
763
+ byTransform.set(transform, {
764
+ elementRevision: revisions.element,
765
+ stylesheetRevision: revisions.stylesheet,
766
+ matched: cachedMatches,
767
+ });
768
+ }
769
+ }
770
+ const sensitiveMatches = elementSensitive.length > 0 ? collect(elementSensitive) : [];
771
+ return sensitiveMatches.length === 0 ? cachedMatches : [...cachedMatches, ...sensitiveMatches];
772
+ }
773
+ /**
774
+ * One matching pass over the rules for the element and its ancestors, with the
775
+ * selector-match results shared between the element's own resolution and the
776
+ * inherited phase. Local aliases are collected per element so no ancestor
777
+ * re-walks the lineage × rules.
778
+ */
779
+ function resolveLineage(el, rules, transform) {
780
+ const lineage = [];
781
+ let current = el;
782
+ while (current) {
783
+ lineage.push(current);
784
+ current = current.parentElement;
785
+ }
786
+ lineage.reverse();
787
+ const selectorMatches = new Map();
788
+ const allSelectorMatches = new Map();
789
+ for (const element of lineage) {
790
+ selectorMatches.set(element, getCachedElementMatches(element, rules, transform));
791
+ allSelectorMatches.set(element, getAllElementMatches(element, rules, transform));
792
+ }
793
+ const byElement = new Map();
794
+ for (let index = 0; index < lineage.length; index++) {
795
+ const element = lineage[index];
796
+ const ruleApplies = makeRuleApplies(element);
797
+ const aliases = new Map();
798
+ for (const lineageElement of lineage.slice(0, index + 1)) {
799
+ const candidates = new Map();
800
+ for (const match of selectorMatches.get(lineageElement) ?? []) {
801
+ if (!ruleApplies(match.rule))
802
+ continue;
803
+ const sourceOrder = match.rule.sourceOrder ?? 0;
804
+ for (const declaration of match.rule.declarations) {
805
+ if (!declaration.property.startsWith("--"))
806
+ continue;
807
+ const candidate = {
808
+ value: declaration.value.trim(),
809
+ important: declaration.important,
810
+ layer: match.rule.layer,
811
+ layerOrder: match.rule.layerOrder,
812
+ specificity: match.specificity,
813
+ sourceOrder,
814
+ };
815
+ const previous = candidates.get(declaration.property);
816
+ if (!previous || compareAuthorCascade(candidate, previous) >= 0) {
817
+ candidates.set(declaration.property, candidate);
818
+ }
819
+ }
820
+ }
821
+ for (const property of Array.from(lineageElement.style)) {
822
+ if (!property.startsWith("--"))
823
+ continue;
824
+ const candidate = {
825
+ value: lineageElement.style.getPropertyValue(property).trim(),
826
+ important: lineageElement.style.getPropertyPriority(property) === "important",
827
+ inline: true,
828
+ specificity: 100000000,
829
+ sourceOrder: Number.MAX_SAFE_INTEGER,
830
+ };
831
+ const previous = candidates.get(property);
832
+ if (!previous || compareAuthorCascade(candidate, previous) >= 0) {
833
+ candidates.set(property, candidate);
834
+ }
835
+ }
836
+ for (const [name, candidate] of candidates)
837
+ aliases.set(name, candidate.value);
838
+ }
839
+ const matched = [];
840
+ for (const match of selectorMatches.get(element) ?? []) {
841
+ if (!ruleApplies(match.rule))
842
+ continue;
843
+ matched.push(match);
844
+ }
845
+ byElement.set(element, {
846
+ element,
847
+ matched,
848
+ allMatched: allSelectorMatches.get(element) ?? matched,
849
+ aliases,
850
+ });
851
+ }
852
+ return { lineage, byElement };
853
+ }
854
+ function rowsFromMatches(el, matched, aliases, tokenTable, allMatched = matched) {
855
+ const map = new Map();
856
+ const mediaCandidatesByProperty = new Map();
857
+ // Sort by source order ascending so rules are processed lowest-first.
858
+ // Map.set() naturally overwrites: higher specificity rules processed later win,
859
+ // and equal-specificity rules get "last in stylesheet order wins" (stable sort).
860
+ const sorted = [...matched].sort((a, b) => (a.rule.sourceOrder ?? 0) - (b.rule.sourceOrder ?? 0));
861
+ const needsDirectionality = sorted.some(({ rule }) => rule.declarations.some(({ property }) => isLogicalBoxProperty(property)));
862
+ const directionality = needsDirectionality ? elementDirectionality(el) : undefined;
863
+ for (const match of allMatched) {
864
+ const mediaAtRules = match.rule.atRules?.filter((atRule) => atRule.kind === "media") ?? [];
865
+ if (mediaAtRules.length === 0)
866
+ continue;
867
+ for (const declaration of match.rule.declarations) {
868
+ for (const resolved of resolveDeclaration(declaration, tokenTable, aliases, directionality)) {
869
+ let candidates = mediaCandidatesByProperty.get(resolved.property);
870
+ if (!candidates) {
871
+ candidates = new Map();
872
+ mediaCandidatesByProperty.set(resolved.property, candidates);
873
+ }
874
+ for (const atRule of mediaAtRules) {
875
+ candidates.set(`${atRule.kind}\u0000${atRule.params}`, atRule);
876
+ }
877
+ }
878
+ }
879
+ }
880
+ for (const m of sorted) {
881
+ const { rule, branch, specificity } = m;
882
+ for (const decl of rule.declarations) {
883
+ for (const resolved of resolveDeclaration(decl, tokenTable, aliases, directionality)) {
884
+ const candidate = {
885
+ property: resolved.property,
886
+ tokenName: resolved.tokenName,
887
+ declaredValue: resolved.declaredValue,
888
+ sourceProperty: resolved.sourceProperty,
889
+ resolvedValue: resolved.resolvedValue,
890
+ authored: resolved.declaredValue,
891
+ computed: "",
892
+ tokens: resolved.tokens,
893
+ opacity: resolved.opacity,
894
+ propertyOpacity: resolved.propertyOpacity,
895
+ color: resolved.color,
896
+ modifiers: resolved.modifiers,
897
+ capability: resolved.capability,
898
+ resolvedTokenValue: resolved.resolvedTokenValue,
899
+ diagnostic: resolved.diagnostic,
900
+ structure: resolved.structure,
901
+ atRules: rule.atRules,
902
+ confidence: resolved.tokenName ? "probable" : "unknown",
903
+ evidence: {
904
+ selector: branch,
905
+ sourceOrder: rule.sourceOrder,
906
+ specificity,
907
+ important: Boolean(resolved.important),
908
+ layer: rule.layer,
909
+ layerOrder: rule.layerOrder,
910
+ reason: resolved.tokenName ? "authored declaration references a catalog token" : "no catalog token reference",
911
+ },
912
+ };
913
+ const previous = map.get(resolved.property);
914
+ if (!previous || compareCandidate(candidate, previous) >= 0)
915
+ map.set(resolved.property, candidate);
916
+ }
917
+ }
918
+ }
919
+ const rows = Array.from(map.values()).slice(0, MAX_PROPERTIES);
920
+ for (const row of rows) {
921
+ const candidates = mediaCandidatesByProperty.get(row.property);
922
+ if (!candidates || candidates.size === 0)
923
+ continue;
924
+ const winningMedia = (row.atRules ?? []).filter((atRule) => atRule.kind === "media");
925
+ const winningKeys = new Set(winningMedia.map((atRule) => `${atRule.kind}\u0000${atRule.params}`));
926
+ const allCandidates = [];
927
+ let insertedWinningStack = false;
928
+ for (const atRule of candidates.values()) {
929
+ const key = `${atRule.kind}\u0000${atRule.params}`;
930
+ if (winningKeys.has(key)) {
931
+ if (!insertedWinningStack) {
932
+ allCandidates.push(...winningMedia.map((winningAtRule) => ({ ...winningAtRule, active: true })));
933
+ insertedWinningStack = true;
934
+ }
935
+ }
936
+ else {
937
+ allCandidates.push({ ...atRule, active: false });
938
+ }
939
+ }
940
+ if (!insertedWinningStack) {
941
+ allCandidates.push(...winningMedia.map((winningAtRule) => ({ ...winningAtRule, active: true })));
942
+ }
943
+ row.atRuleCandidates = allCandidates;
944
+ }
945
+ inferTailwindV4ColorOpacity(el, tokenTable, rows);
946
+ for (const row of rows) {
947
+ if (row.capability !== "raw" || row.diagnostic)
948
+ continue;
949
+ const value = row.authored ?? row.declaredValue ?? "";
950
+ if (!canBecomeNumeric(value))
951
+ continue;
952
+ const numeric = row.resolvedValue ?? row.computed ?? "";
953
+ if (!numeric)
954
+ continue;
955
+ row.capability = capabilityFor(row.property, numeric, tokenTable);
956
+ }
957
+ return rows;
958
+ }
959
+ /**
960
+ * Package-private cascade fixture seam. This exercises selector, layer,
961
+ * importance, and interaction-state coordination while still crossing the
962
+ * public value-semantics Interface through `resolveDeclaration`.
963
+ * It is intentionally absent from the package exports.
964
+ */
965
+ export function resolveRuleFixture(el, rules, tokenTable) {
966
+ const ruleApplies = makeRuleApplies(el);
967
+ const matched = [];
968
+ const allMatched = [];
969
+ for (const rule of rules) {
970
+ const match = matchRuleForElement(el, { rule, selectorText: rule.selectorText });
971
+ if (!match)
972
+ continue;
973
+ allMatched.push(match);
974
+ if (rule.active === false)
975
+ continue;
976
+ if (!ruleApplies(rule))
977
+ continue;
978
+ matched.push(match);
979
+ }
980
+ const localAliases = collectLocalAliases(el, rules, ruleApplies);
981
+ return rowsFromMatches(el, matched, localAliases, tokenTable, allMatched);
982
+ }
983
+ // Selector branch splits are pure functions of the selector text and repeat
984
+ // for every element and resolution sweep. Memoize them so repeated matching
985
+ // passes skip re-scanning the same selector strings. Bounded like the other
986
+ // match caches; the snapshot's selector set is finite per stylesheet revision.
987
+ const SELECTOR_SPLIT_CACHE_MAX = 8192;
988
+ const selectorSplitMemo = new Map();
989
+ // The matched branch for one (element, selector) pair is a pure function of
990
+ // the element's selector-relevant state and the CSSOM snapshot — except for
991
+ // selectors whose match depends on transient state the revisions cannot see
992
+ // (`:hover`, `:checked`, sibling combinators, …). Those keep the freshness
993
+ // contract of the element-sensitive bucket and are matched uncached.
994
+ // Resolution sweeps re-match the same state-independent selector strings
995
+ // against the same lineage elements across cascades (authored base, stable,
996
+ // interaction states) and across the active/all rule sets, so memoizing the
997
+ // branch turns repeat sweeps into cache hits. Invalidation follows the
998
+ // document revisions, the same strategy as the per-element match caches.
999
+ const ELEMENT_BRANCH_CACHE_MAX = 16384;
1000
+ const elementBranchMemo = new WeakMap();
1001
+ function isBranchMemoizable(selectorText) {
1002
+ return !TRANSIENT_SELECTOR.test(selectorText) && !isElementSensitiveSelector(selectorText);
1003
+ }
1004
+ function matchingSelectorBranch(el, selectorText) {
1005
+ const doc = el.ownerDocument ?? document;
1006
+ const revisions = getDocumentRevisions(doc);
1007
+ let bySelector = elementBranchMemo.get(el);
1008
+ const memoizable = isBranchMemoizable(selectorText);
1009
+ if (memoizable) {
1010
+ if (!bySelector) {
1011
+ bySelector = new Map();
1012
+ elementBranchMemo.set(el, bySelector);
1013
+ }
1014
+ const cached = bySelector.get(selectorText);
1015
+ if (cached
1016
+ && cached.elementRevision === revisions.element
1017
+ && cached.stylesheetRevision === revisions.stylesheet) {
1018
+ return cached.branch;
1019
+ }
1020
+ }
1021
+ let branches = selectorSplitMemo.get(selectorText);
1022
+ if (!branches) {
1023
+ branches = splitTopLevel(selectorText, ",");
1024
+ if (selectorSplitMemo.size >= SELECTOR_SPLIT_CACHE_MAX)
1025
+ selectorSplitMemo.clear();
1026
+ selectorSplitMemo.set(selectorText, branches);
1027
+ }
1028
+ let branch = null;
1029
+ for (const candidate of branches) {
1030
+ try {
1031
+ if (el.matches(candidate.trim())) {
1032
+ branch = candidate.trim();
1033
+ break;
1034
+ }
1035
+ }
1036
+ catch { /* invalid/unsupported selector */ }
1037
+ }
1038
+ if (memoizable) {
1039
+ if (bySelector.size >= ELEMENT_BRANCH_CACHE_MAX)
1040
+ bySelector.clear();
1041
+ bySelector.set(selectorText, {
1042
+ elementRevision: revisions.element,
1043
+ stylesheetRevision: revisions.stylesheet,
1044
+ branch,
1045
+ });
1046
+ }
1047
+ return branch;
1048
+ }
1049
+ function compareCandidate(a, b) {
1050
+ return compareAuthorCascade({
1051
+ important: a.evidence.important,
1052
+ inline: a.evidence.selector === "[style]",
1053
+ layer: a.evidence.layer,
1054
+ layerOrder: a.evidence.layerOrder,
1055
+ specificity: a.evidence.specificity ?? 0,
1056
+ sourceOrder: a.evidence.sourceOrder ?? 0,
1057
+ }, {
1058
+ important: b.evidence.important,
1059
+ inline: b.evidence.selector === "[style]",
1060
+ layer: b.evidence.layer,
1061
+ layerOrder: b.evidence.layerOrder,
1062
+ specificity: b.evidence.specificity ?? 0,
1063
+ sourceOrder: b.evidence.sourceOrder ?? 0,
1064
+ });
1065
+ }
1066
+ function inferTailwindV4ColorOpacity(el, tokenTable, rows) {
1067
+ const row = rows.find((candidate) => candidate.property === "background-color" || candidate.property === "background");
1068
+ if (!row || row.tokenName)
1069
+ return;
1070
+ for (const className of Array.from(el.classList)) {
1071
+ const utility = readTailwindV4AlphaUtility(className);
1072
+ if (!utility)
1073
+ continue;
1074
+ const { baseName, alpha } = utility;
1075
+ const entry = tokenTable[baseName];
1076
+ if (!entry || entry.adapter !== "tailwind-v4")
1077
+ continue;
1078
+ const authored = tailwindV4AlphaExpression(baseName, alpha);
1079
+ row.tokenName = baseName;
1080
+ row.declaredValue = authored;
1081
+ row.authored = authored;
1082
+ row.tokens = [{ name: baseName, origin: inspectorTokenOrigin(entry) }];
1083
+ const colorInterpretation = resolveTokenValue(authored, tokenTable, EMPTY_LOCAL_ALIASES);
1084
+ row.opacity = colorInterpretation.opacity;
1085
+ row.color = colorInterpretation.color;
1086
+ row.modifiers = [{ kind: "alpha", value: alpha }];
1087
+ row.capability = "color";
1088
+ row.resolvedTokenValue = entry.value;
1089
+ row.evidence.reason = "Tailwind v4 opacity utility mapped to its base catalog token";
1090
+ row.confidence = "probable";
1091
+ return;
1092
+ }
1093
+ }
1094
+ // Splits CSS values at top-level combinators or an optional delimiter.
1095
+ function splitTopLevel(s, sep) {
1096
+ const parts = [];
1097
+ let depth = 0;
1098
+ let start = 0;
1099
+ for (let i = 0; i < s.length; i++) {
1100
+ if (s[i] === "(")
1101
+ depth++;
1102
+ else if (s[i] === ")")
1103
+ depth--;
1104
+ else if (depth === 0 && sep && s[i] === sep) {
1105
+ parts.push(s.slice(start, i));
1106
+ start = i + 1;
1107
+ }
1108
+ else if (depth === 0 && !sep && (s[i] === " " || s[i] === ">" || s[i] === "+" || s[i] === "~")) {
1109
+ // Only split on combinators that have non-space around them
1110
+ // If previous char was also a combinator, skip
1111
+ if (i > start) {
1112
+ parts.push(s.slice(start, i).trim());
1113
+ }
1114
+ start = i + 1;
1115
+ }
1116
+ }
1117
+ const last = s.slice(start).trim();
1118
+ if (last)
1119
+ parts.push(last);
1120
+ return parts;
1121
+ }
1122
+ const stateResolutionSnapshots = new WeakMap();
1123
+ const INHERITED_PROPERTIES = new Set([
1124
+ "color", "font", "font-family", "font-size", "font-style", "font-variant", "font-weight",
1125
+ "letter-spacing", "line-height", "text-align", "text-indent", "text-transform", "visibility",
1126
+ "white-space", "word-spacing", "cursor",
1127
+ ]);
1128
+ function resolveInheritedProperties(el, tokenTable, lineage, result, inaccessible) {
1129
+ const computed = getElementComputedStyle(el);
1130
+ const seenProperties = new Set(result.map((p) => p.property));
1131
+ let ancestor = el.parentElement;
1132
+ while (ancestor) {
1133
+ const entry = lineage.byElement.get(ancestor);
1134
+ if (entry) {
1135
+ const ancestorComputed = getElementComputedStyle(ancestor);
1136
+ for (const candidate of rowsFromMatches(ancestor, entry.matched, entry.aliases, tokenTable, entry.allMatched)) {
1137
+ if (seenProperties.has(candidate.property))
1138
+ continue;
1139
+ if (!INHERITED_PROPERTIES.has(candidate.property) && !candidate.property.startsWith("--"))
1140
+ continue;
1141
+ const ancestorVal = ancestorComputed.getPropertyValue(candidate.property).trim();
1142
+ const elVal = computed.getPropertyValue(candidate.property).trim();
1143
+ if (ancestorVal && ancestorVal === elVal) {
1144
+ hydratePropertyOpacity(candidate, ancestorVal);
1145
+ result.push({
1146
+ ...candidate,
1147
+ resolvedValue: elVal,
1148
+ confidence: candidate.tokenName && candidateMatchesPainted(ancestor, candidate, ancestorVal) && !inaccessible && !candidate.evidence.layer ? "exact" : candidate.tokenName ? "probable" : "unknown",
1149
+ evidence: { ...candidate.evidence, inheritedFrom: ancestor.tagName.toLowerCase(), inaccessibleStylesheet: inaccessible || undefined, reason: "inherited property traced through the ancestor cascade" },
1150
+ });
1151
+ seenProperties.add(candidate.property);
1152
+ }
1153
+ }
1154
+ }
1155
+ ancestor = ancestor.parentElement;
1156
+ }
1157
+ return result;
1158
+ }
1159
+ export function getResolvedProperties(el, tokenTable) {
1160
+ const doc = el.ownerDocument ?? document;
1161
+ const { rules, inaccessible } = collectCssomRules(doc);
1162
+ const lineage = resolveLineage(el, rules, "live");
1163
+ const entry = lineage.byElement.get(el);
1164
+ const result = rowsFromMatches(el, entry.matched, entry.aliases, tokenTable, entry.allMatched);
1165
+ const computed = getElementComputedStyle(el);
1166
+ for (const prop of result) {
1167
+ const cv = computed.getPropertyValue(prop.property);
1168
+ if (cv && !/\b(?:var|calc)\s*\(/.test(cv)) {
1169
+ prop.resolvedValue = cv;
1170
+ prop.computed = cv;
1171
+ hydratePropertyOpacity(prop, cv);
1172
+ const validated = candidateMatchesPainted(el, prop, cv);
1173
+ prop.confidence = validated && !inaccessible && !prop.evidence.layer ? "exact" : prop.tokenName ? "probable" : "unknown";
1174
+ prop.evidence.inaccessibleStylesheet = inaccessible || undefined;
1175
+ prop.evidence.reason = prop.tokenName
1176
+ ? (validated ? "authored token declaration validated against computed style" : "authored token candidate could not be proven uniquely")
1177
+ : "painted value has no attributable catalog token";
1178
+ }
1179
+ }
1180
+ applyInlineDeclarations(el, result, tokenTable, computed, inaccessible);
1181
+ hydratePropertyOpacityRows(result, computed);
1182
+ promoteNumericCalcRows(result, tokenTable);
1183
+ return resolveInheritedProperties(el, tokenTable, lineage, result, inaccessible);
1184
+ }
1185
+ function applyInlineDeclarations(el, result, tokenTable, computed, inaccessible) {
1186
+ // Inline declarations participate in the cascade and are explicit evidence,
1187
+ // but token attribution is only exact when the authored inline value uses a known token.
1188
+ const inlineProperties = Array.from(el.style);
1189
+ const directionality = inlineProperties.some(isLogicalBoxProperty)
1190
+ ? directionalityFromComputed(el, computed)
1191
+ : undefined;
1192
+ for (const property of inlineProperties) {
1193
+ const value = el.style.getPropertyValue(property);
1194
+ const declarations = resolveDeclaration({
1195
+ property,
1196
+ value,
1197
+ important: el.style.getPropertyPriority(property) === "important",
1198
+ }, tokenTable, EMPTY_LOCAL_ALIASES, directionality);
1199
+ for (const declaration of declarations) {
1200
+ const painted = computed.getPropertyValue(declaration.property);
1201
+ const row = {
1202
+ property: declaration.property,
1203
+ tokenName: declaration.tokenName,
1204
+ declaredValue: declaration.declaredValue,
1205
+ sourceProperty: declaration.sourceProperty,
1206
+ resolvedValue: painted,
1207
+ authored: declaration.declaredValue,
1208
+ computed: painted,
1209
+ tokens: declaration.tokens,
1210
+ opacity: declaration.opacity,
1211
+ propertyOpacity: declaration.propertyOpacity,
1212
+ color: declaration.color,
1213
+ modifiers: declaration.modifiers,
1214
+ capability: declaration.capability,
1215
+ resolvedTokenValue: declaration.resolvedValue,
1216
+ diagnostic: declaration.diagnostic,
1217
+ structure: declaration.structure,
1218
+ confidence: "unknown",
1219
+ evidence: { selector: "[style]", specificity: 100000000, important: Boolean(declaration.important), inaccessibleStylesheet: inaccessible || undefined, reason: declaration.tokenName ? "inline token declaration validated against computed style" : "inline declaration contains no catalog token" },
1220
+ };
1221
+ if (declaration.tokenName && candidateMatchesPainted(el, row, painted)) {
1222
+ row.confidence = inaccessible ? "probable" : "exact";
1223
+ row.evidence.reason = "inline token declaration validated against computed style";
1224
+ }
1225
+ const index = result.findIndex((item) => item.property === declaration.property);
1226
+ if (index < 0)
1227
+ result.push(row);
1228
+ else if (compareCandidate(row, result[index]) >= 0)
1229
+ result[index] = row;
1230
+ }
1231
+ }
1232
+ }
1233
+ function promoteNumericCalcRows(result, tokenTable) {
1234
+ // When a calc() expression only references static tokens the browser has
1235
+ // already resolved it to a pixel value. Reclassify the row so the UI
1236
+ // shows the pixel value instead of the raw calc() string and allows
1237
+ // numeric editing (nudge / token swap).
1238
+ for (const prop of result) {
1239
+ if (prop.capability !== "raw" || prop.diagnostic)
1240
+ continue;
1241
+ const value = prop.authored ?? prop.declaredValue ?? "";
1242
+ if (!canBecomeNumeric(value))
1243
+ continue;
1244
+ const numeric = prop.computed ?? prop.resolvedValue ?? "";
1245
+ if (!numeric)
1246
+ continue;
1247
+ prop.capability = capabilityFor(prop.property, numeric, tokenTable);
1248
+ }
1249
+ }
1250
+ const INTERACTION_SELECTOR = /:(hover|active|focus-visible|focus|disabled)(?:\b|\()/g;
1251
+ function selectorForState(selector, state) {
1252
+ const states = new Set();
1253
+ INTERACTION_SELECTOR.lastIndex = 0;
1254
+ let match;
1255
+ while ((match = INTERACTION_SELECTOR.exec(selector)) !== null)
1256
+ states.add(match[1]);
1257
+ if (state === "base")
1258
+ return states.size === 0 ? selector : null;
1259
+ if (!states.has(state))
1260
+ return states.size === 0 ? selector : null;
1261
+ // CSSOM cannot ask the browser whether a hypothetical pseudo-class matches.
1262
+ // Removing interaction pseudo-classes gives the authored rule a stable
1263
+ // element match for inspection. The real rule remains untouched.
1264
+ return selector.replace(INTERACTION_SELECTOR, "");
1265
+ }
1266
+ /**
1267
+ * Resolve the authored cascade for a chosen interaction state without relying
1268
+ * on the pointer's current location. This is intentionally attribution-first:
1269
+ * values with no authored declaration still fall back to the browser's live
1270
+ * computed value in the field layer.
1271
+ */
1272
+ export function getResolvedPropertiesForState(el, tokenTable, state) {
1273
+ const doc = el.ownerDocument ?? document;
1274
+ const revisions = getDocumentRevisions(doc);
1275
+ const { rules, inaccessible } = collectCssomRules(doc);
1276
+ const dynamicMatchKey = elementSensitiveMatchKey(el, rules, state);
1277
+ let snapshots = stateResolutionSnapshots.get(el);
1278
+ if (!snapshots) {
1279
+ snapshots = new Map();
1280
+ stateResolutionSnapshots.set(el, snapshots);
1281
+ }
1282
+ const cached = snapshots.get(state);
1283
+ if (cached
1284
+ && cached.elementRevision === revisions.element
1285
+ && cached.stylesheetRevision === revisions.stylesheet
1286
+ && cached.tokenTable === tokenTable
1287
+ && cached.dynamicMatchKey === dynamicMatchKey) {
1288
+ return cached.rows;
1289
+ }
1290
+ const lineage = resolveLineage(el, rules, state);
1291
+ const entry = lineage.byElement.get(el);
1292
+ const result = rowsFromMatches(el, entry.matched, entry.aliases, tokenTable, entry.allMatched);
1293
+ const computed = getElementComputedStyle(el);
1294
+ for (const prop of result) {
1295
+ const cv = computed.getPropertyValue(prop.property);
1296
+ if (cv && !/\b(?:var|calc)\s*\(/.test(cv)) {
1297
+ // A selected interaction state is hypothetical: the element may still
1298
+ // be painting its Base styles. `rowsFromMatches` has already resolved
1299
+ // the authored declaration for the requested state, so preserve that
1300
+ // value for editor controls and keep the live CSSOM value in `computed`.
1301
+ if (state === "base" || !prop.resolvedValue)
1302
+ prop.resolvedValue = cv;
1303
+ prop.computed = cv;
1304
+ const validated = candidateMatchesPainted(el, prop, cv);
1305
+ prop.confidence = validated && !inaccessible && !prop.evidence.layer ? "exact" : prop.tokenName ? "probable" : "unknown";
1306
+ prop.evidence.inaccessibleStylesheet = inaccessible || undefined;
1307
+ prop.evidence.reason = prop.tokenName
1308
+ ? (validated ? "authored token declaration validated against computed style" : "authored token candidate could not be proven uniquely")
1309
+ : "painted value has no attributable catalog token";
1310
+ }
1311
+ }
1312
+ applyInlineDeclarations(el, result, tokenTable, computed, inaccessible);
1313
+ hydratePropertyOpacityRows(result, computed);
1314
+ promoteNumericCalcRows(result, tokenTable);
1315
+ const rows = resolveInheritedProperties(el, tokenTable, lineage, result, inaccessible);
1316
+ registerWithAncestors(el);
1317
+ snapshots.set(state, {
1318
+ elementRevision: revisions.element,
1319
+ stylesheetRevision: revisions.stylesheet,
1320
+ tokenTable,
1321
+ dynamicMatchKey,
1322
+ rows,
1323
+ });
1324
+ return rows;
1325
+ }
1326
+ /**
1327
+ * Interaction states whose pseudo-class substring appears in at least one
1328
+ * snapshot selector, memoized per CSSOM snapshot. The availability check for a
1329
+ * state is `matched.some((m) => m.rule.selectorText.includes(":state"))`, so a
1330
+ * state whose substring appears nowhere can never become available for any
1331
+ * element; skipping its per-state match sweep is exactly equivalent and
1332
+ * removes the dominant cost of re-scanning interaction states after every
1333
+ * stylesheet revision.
1334
+ */
1335
+ const statesWithPseudoInSnapshot = new WeakMap();
1336
+ function statesWithPseudoInSelectors(rules) {
1337
+ let present = statesWithPseudoInSnapshot.get(rules);
1338
+ if (!present) {
1339
+ present = new Set();
1340
+ for (const rule of rules) {
1341
+ for (const state of INTERACTION_STATES) {
1342
+ if (!present.has(state) && rule.selectorText.includes(`:${state}`)) {
1343
+ present.add(state);
1344
+ }
1345
+ }
1346
+ }
1347
+ statesWithPseudoInSnapshot.set(rules, present);
1348
+ }
1349
+ return present;
1350
+ }
1351
+ export function getAvailableInteractionStates(el) {
1352
+ const doc = el.ownerDocument ?? document;
1353
+ const { rules } = collectCssomRules(doc);
1354
+ const present = statesWithPseudoInSelectors(rules);
1355
+ const available = ["base"];
1356
+ for (const state of INTERACTION_STATES) {
1357
+ if (!present.has(state))
1358
+ continue;
1359
+ const matched = getCachedElementMatches(el, rules, state);
1360
+ const relevant = matched.some((m) => m.rule.selectorText.includes(`:${state}`));
1361
+ if (relevant)
1362
+ available.push(state);
1363
+ }
1364
+ return available;
1365
+ }
1366
+ const stableTokenCache = new WeakMap();
1367
+ /**
1368
+ * Resolves the cascade with transient interaction selectors removed. Used when
1369
+ * an editor must stay linked to the stable token beneath a live :hover/:focus
1370
+ * paint. Memoized per (element, revisions, tokenTable).
1371
+ */
1372
+ export function getResolvedPropertiesStable(el, tokenTable) {
1373
+ const doc = el.ownerDocument ?? document;
1374
+ const revisions = getDocumentRevisions(doc);
1375
+ const { rules, inaccessible } = collectCssomRules(doc);
1376
+ const dynamicMatchKey = elementSensitiveMatchKey(el, rules, "stable");
1377
+ const cached = stableTokenCache.get(el);
1378
+ if (cached
1379
+ && cached.elementRevision === revisions.element
1380
+ && cached.stylesheetRevision === revisions.stylesheet
1381
+ && cached.tokenTable === tokenTable
1382
+ && cached.dynamicMatchKey === dynamicMatchKey) {
1383
+ return cached.rows;
1384
+ }
1385
+ const lineage = resolveLineage(el, rules, "stable");
1386
+ const entry = lineage.byElement.get(el);
1387
+ const result = rowsFromMatches(el, entry.matched, entry.aliases, tokenTable, entry.allMatched);
1388
+ const computed = getElementComputedStyle(el);
1389
+ applyInlineDeclarations(el, result, tokenTable, computed, inaccessible);
1390
+ hydratePropertyOpacityRows(result, computed);
1391
+ promoteNumericCalcRows(result, tokenTable);
1392
+ const rows = resolveInheritedProperties(el, tokenTable, lineage, result, inaccessible);
1393
+ stableTokenCache.set(el, {
1394
+ elementRevision: revisions.element,
1395
+ stylesheetRevision: revisions.stylesheet,
1396
+ tokenTable,
1397
+ dynamicMatchKey,
1398
+ rows,
1399
+ });
1400
+ return rows;
1401
+ }