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,1207 @@
1
+ import { useSyncExternalStore } from "react";
2
+ import { appendChange } from "../changes/changesLog.js";
3
+ import { registerInlineTextClearHandler } from "./inlineTextLifecycle.js";
4
+ import { isNudgeUiDev } from "../runtime/devFlag.js";
5
+ import { createComponentPropChange, } from "../componentSemantics/changeModel.js";
6
+ import { resolveTextBinding, } from "../componentSemantics/textBinding.js";
7
+ import { captureTextProjectionTarget, EMPTY_TEXT_PROJECTION_ATTR, EMPTY_TEXT_PROJECTION_PATH_ATTR, getTextContentChangeById, resolveTextProjectionTarget, resolveTextProjectionTextNode, textProjectionSelector, } from "../projection/textProjection.js";
8
+ const listeners = new Set();
9
+ let activeSession = null;
10
+ let activeSessionDocument = null;
11
+ let pendingEditIntent = null;
12
+ // This remains armed if blur replaces the DOM between the second pointer-down
13
+ // and dblclick; only the next handoff attempt or explicit teardown consumes it.
14
+ let handoffPointerArmed = false;
15
+ let pendingReplayScheduled = false;
16
+ let sessionRevision = 0;
17
+ let inlineTextDiagnostics = [];
18
+ const diagnosticListeners = new Set();
19
+ function discardPendingInlineTextEdit(ownerDocument) {
20
+ if (!ownerDocument || pendingEditIntent?.ownerDocument === ownerDocument) {
21
+ pendingEditIntent = null;
22
+ }
23
+ if (!pendingEditIntent)
24
+ handoffPointerArmed = false;
25
+ }
26
+ function subscribe(listener) {
27
+ listeners.add(listener);
28
+ return () => listeners.delete(listener);
29
+ }
30
+ function notify() {
31
+ sessionRevision += 1;
32
+ listeners.forEach((listener) => listener());
33
+ }
34
+ function notifyDiagnostics() {
35
+ for (const listener of diagnosticListeners)
36
+ listener();
37
+ }
38
+ function recordDiagnostic(diagnostic) {
39
+ inlineTextDiagnostics = [...inlineTextDiagnostics.slice(-31), diagnostic];
40
+ notifyDiagnostics();
41
+ }
42
+ export function getInlineTextDiagnostics() {
43
+ return inlineTextDiagnostics;
44
+ }
45
+ export function getInlineTextDiagnostic() {
46
+ return inlineTextDiagnostics[inlineTextDiagnostics.length - 1] ?? null;
47
+ }
48
+ export function subscribeInlineTextDiagnostics(listener) {
49
+ diagnosticListeners.add(listener);
50
+ return () => diagnosticListeners.delete(listener);
51
+ }
52
+ export function getInlineTextSession() {
53
+ return activeSession;
54
+ }
55
+ export function useInlineTextSession() {
56
+ useSyncExternalStore(subscribe, () => sessionRevision, () => sessionRevision);
57
+ return activeSession;
58
+ }
59
+ export function isInlineTextEditingActive() {
60
+ return activeSession !== null;
61
+ }
62
+ export function cancelInlineTextEdit() {
63
+ discardPendingInlineTextEdit();
64
+ activeSession?.cancel("cancel");
65
+ }
66
+ /** End a session owned by a document/frame that is about to be disposed. */
67
+ export function disposeInlineTextEdit(reason = "frame-disposed", ownerDocument) {
68
+ if (!ownerDocument) {
69
+ discardPendingInlineTextEdit();
70
+ activeSession?.cancel(reason);
71
+ return;
72
+ }
73
+ discardPendingInlineTextEdit(ownerDocument);
74
+ if (activeSessionDocument === ownerDocument)
75
+ activeSession?.cancel(reason);
76
+ }
77
+ function ownerHTMLElement(element) {
78
+ const OwnerHTMLElement = element.ownerDocument.defaultView?.HTMLElement;
79
+ // SAFETY: The owning realm's HTMLElement constructor proves that this DOM
80
+ // element satisfies the HTMLElement interface, including iframe elements.
81
+ return OwnerHTMLElement && element instanceof OwnerHTMLElement
82
+ ? element
83
+ : null;
84
+ }
85
+ function currentIntentTarget(intent) {
86
+ if (intent.target.isConnected)
87
+ return intent.target;
88
+ return intent.ownerDocument.elementFromPoint?.(intent.point.x, intent.point.y) ?? null;
89
+ }
90
+ function resolveInlineTextEditIntent(intent) {
91
+ const eventTarget = currentIntentTarget(intent);
92
+ if (!eventTarget)
93
+ return null;
94
+ const marker = eventTarget.closest(`[${EMPTY_TEXT_PROJECTION_ATTR}]`);
95
+ if (marker) {
96
+ const htmlMarker = ownerHTMLElement(marker);
97
+ if (htmlMarker)
98
+ return { kind: "empty-projection", marker: htmlMarker };
99
+ }
100
+ let current = eventTarget;
101
+ while (current) {
102
+ const htmlElement = ownerHTMLElement(current);
103
+ if (htmlElement?.hasAttribute("data-cid")) {
104
+ return { kind: "element", target: htmlElement };
105
+ }
106
+ current = current.parentElement;
107
+ }
108
+ return null;
109
+ }
110
+ function beginInlineTextEditIntent(intent) {
111
+ const resolved = resolveInlineTextEditIntent(intent);
112
+ if (!resolved)
113
+ return null;
114
+ return resolved.kind === "empty-projection"
115
+ ? beginInlineTextEditFromEmptyProjection(resolved.marker)
116
+ : beginInlineTextEdit(resolved.target, intent.point);
117
+ }
118
+ function drainPendingInlineTextEdit() {
119
+ if (activeSession || !pendingEditIntent)
120
+ return null;
121
+ const intent = pendingEditIntent;
122
+ pendingEditIntent = null;
123
+ return beginInlineTextEditIntent(intent);
124
+ }
125
+ function schedulePendingInlineTextEdit() {
126
+ if (!pendingEditIntent || pendingReplayScheduled)
127
+ return;
128
+ pendingReplayScheduled = true;
129
+ queueMicrotask(() => {
130
+ pendingReplayScheduled = false;
131
+ drainPendingInlineTextEdit();
132
+ });
133
+ }
134
+ /**
135
+ * Request inline editing from a document gesture. This is the interaction
136
+ * seam: it owns active-session handoff so gesture routers never discard a
137
+ * valid target switch merely because another draft is settling.
138
+ */
139
+ function requestInlineTextEdit(target, point) {
140
+ if (activeSession) {
141
+ const hitTarget = target.ownerDocument.elementFromPoint?.(point.x, point.y);
142
+ if (activeSession.host.contains(target)
143
+ || (hitTarget && activeSession.host.contains(hitTarget))) {
144
+ return "stop-propagation";
145
+ }
146
+ }
147
+ const intent = {
148
+ ownerDocument: target.ownerDocument,
149
+ target,
150
+ point,
151
+ };
152
+ if (!resolveInlineTextEditIntent(intent))
153
+ return activeSession ? "suppress" : "pass-through";
154
+ if (!activeSession) {
155
+ const result = beginInlineTextEditIntent(intent);
156
+ return result && !("kind" in result) ? "suppress" : "pass-through";
157
+ }
158
+ pendingEditIntent = intent;
159
+ activeSession.commit("blur");
160
+ if (!activeSession)
161
+ drainPendingInlineTextEdit();
162
+ return "suppress";
163
+ }
164
+ /**
165
+ * Handle one native interaction while keeping session-transition policy
166
+ * local. Pointer-down preserves double-click intent across the first click's
167
+ * blur commit, even when canonical projection replaces the target DOM.
168
+ */
169
+ export function handleInlineTextEditIntent(intent) {
170
+ if (intent.kind === "double-click") {
171
+ return requestInlineTextEdit(intent.target, intent.point);
172
+ }
173
+ if (intent.clickCount <= 1) {
174
+ handoffPointerArmed = activeSession !== null;
175
+ return activeSession ? "stop-propagation" : "pass-through";
176
+ }
177
+ if (!activeSession && !handoffPointerArmed)
178
+ return "pass-through";
179
+ handoffPointerArmed = false;
180
+ return requestInlineTextEdit(intent.target, intent.point);
181
+ }
182
+ function isTextEditRejection(value) {
183
+ return "kind" in value && value.kind === "rejected";
184
+ }
185
+ function captureSelection(doc) {
186
+ const selection = doc.getSelection?.();
187
+ if (!selection)
188
+ return { ranges: [] };
189
+ const ranges = [];
190
+ for (let index = 0; index < selection.rangeCount; index += 1) {
191
+ ranges.push(selection.getRangeAt(index).cloneRange());
192
+ }
193
+ return { ranges };
194
+ }
195
+ function restoreSelection(doc, snapshot) {
196
+ const selection = doc.getSelection?.();
197
+ if (!selection)
198
+ return;
199
+ selection.removeAllRanges();
200
+ for (const range of snapshot.ranges) {
201
+ if (range.startContainer.isConnected && range.endContainer.isConnected) {
202
+ try {
203
+ selection.addRange(range);
204
+ }
205
+ catch {
206
+ // A framework rerender can invalidate a saved range between cleanup
207
+ // and restoration. Removing the transient selection is safer than
208
+ // retaining a range in a detached editing wrapper.
209
+ selection.removeAllRanges();
210
+ }
211
+ }
212
+ }
213
+ }
214
+ function hostIsOwned(candidate, host, ownership) {
215
+ return host.isConnected
216
+ && candidate.element.isConnected
217
+ && candidate.element.contains(host)
218
+ && host.parentNode === ownership.parent
219
+ && host.nextSibling === ownership.nextSibling;
220
+ }
221
+ function restoreDraft(candidate, host, text, ownership) {
222
+ if (!hostIsOwned(candidate, host, ownership))
223
+ return false;
224
+ const original = candidate.textNode;
225
+ // Normal typing replaces the original node inside the wrapper, leaving it
226
+ // detached. If reconciliation moved that node into another live tree,
227
+ // never move it back into the captured position.
228
+ if (original.isConnected && original.parentNode !== host)
229
+ return false;
230
+ original.nodeValue = text;
231
+ // Keep the original Text node and replace only the transient wrapper. This
232
+ // preserves every sibling/descendant of an icon-plus-label host.
233
+ host.replaceWith(original);
234
+ return true;
235
+ }
236
+ function selectAll(host) {
237
+ const doc = host.ownerDocument;
238
+ const selection = doc.getSelection?.();
239
+ if (!selection)
240
+ return;
241
+ const range = doc.createRange();
242
+ range.selectNodeContents(host);
243
+ selection.removeAllRanges();
244
+ selection.addRange(range);
245
+ }
246
+ function isNodeInsideHost(host, node) {
247
+ return node === host || host.contains(node);
248
+ }
249
+ function rangeInsideHost(host, range) {
250
+ if (!isNodeInsideHost(host, range.startContainer)
251
+ || !isNodeInsideHost(host, range.endContainer))
252
+ return false;
253
+ // A host ancestor contains the common ancestor whenever both endpoints are
254
+ // inside it; StaticRange does not expose commonAncestorContainer.
255
+ return true;
256
+ }
257
+ function selectionInsideHost(host) {
258
+ const selection = host.ownerDocument.getSelection?.();
259
+ if (!selection || selection.rangeCount === 0)
260
+ return false;
261
+ for (let index = 0; index < selection.rangeCount; index += 1) {
262
+ if (!rangeInsideHost(host, selection.getRangeAt(index)))
263
+ return false;
264
+ }
265
+ return true;
266
+ }
267
+ const ALLOWED_INPUT_TYPES = new Set([
268
+ "insertText",
269
+ "insertReplacementText",
270
+ "insertCompositionText",
271
+ "insertFromComposition",
272
+ "insertFromPaste",
273
+ "deleteContentBackward",
274
+ "deleteContentForward",
275
+ "deleteByCut",
276
+ "deleteByDrag",
277
+ ]);
278
+ function isParagraphInputType(inputType) {
279
+ return inputType === "insertParagraph" || inputType === "insertLineBreak";
280
+ }
281
+ function isAllowedInputType(inputType) {
282
+ return ALLOWED_INPUT_TYPES.has(inputType);
283
+ }
284
+ function plainTextFromPaste(event) {
285
+ try {
286
+ const value = event.clipboardData?.getData("text/plain");
287
+ return typeof value === "string" ? value : null;
288
+ }
289
+ catch {
290
+ return null;
291
+ }
292
+ }
293
+ function hasParagraphBreak(value) {
294
+ return /[\r\n]/.test(value);
295
+ }
296
+ function replaceSelectionWithPlainText(host, value) {
297
+ if (hasParagraphBreak(value) || !selectionInsideHost(host))
298
+ return false;
299
+ const selection = host.ownerDocument.getSelection?.();
300
+ if (!selection || selection.rangeCount === 0)
301
+ return false;
302
+ const range = selection.getRangeAt(0);
303
+ range.deleteContents();
304
+ const node = host.ownerDocument.createTextNode(value);
305
+ range.insertNode(node);
306
+ range.setStartAfter(node);
307
+ range.collapse(true);
308
+ selection.removeAllRanges();
309
+ selection.addRange(range);
310
+ return true;
311
+ }
312
+ function flattenHostText(host) {
313
+ const text = host.textContent ?? "";
314
+ if (host.childNodes.length === 1 && host.firstChild?.nodeType === 3)
315
+ return text;
316
+ host.replaceChildren(host.ownerDocument.createTextNode(text));
317
+ return text;
318
+ }
319
+ function sourceForChoice(candidate, choice) {
320
+ if (choice?.renderedSource)
321
+ return choice.renderedSource;
322
+ if (candidate.renderedSource
323
+ && (!choice || candidate.renderedSource.evidence?.callsiteId === choice.binding.target.callsiteId
324
+ && candidate.renderedSource.evidence.property === choice.binding.property)) {
325
+ return candidate.renderedSource;
326
+ }
327
+ const parsed = /^(.*):(\d+):(\d+)$/.exec(candidate.element.getAttribute("data-src") ?? "");
328
+ const target = choice?.binding.target;
329
+ const authoredAs = choice?.authoredAs === "literal"
330
+ ? "literal"
331
+ : choice?.authoredAs === "expression" || choice?.authoredAs === "spread"
332
+ ? "expression"
333
+ : "unknown";
334
+ return {
335
+ file: target?.file ?? parsed?.[1] ?? candidate.element.getAttribute("data-src") ?? "",
336
+ line: target?.line ?? Number(parsed?.[2] ?? 0),
337
+ column: target?.column ?? Number(parsed?.[3] ?? 0),
338
+ component: target?.componentName ?? candidate.element.getAttribute("data-cid") ?? "Rendered text",
339
+ selector: candidate.binding.kind === "rendered-text"
340
+ ? textProjectionSelector(candidate.binding.target) ?? ""
341
+ : "",
342
+ authoredAs,
343
+ evidence: choice ? {
344
+ callsiteId: choice.binding.target.callsiteId,
345
+ componentName: choice.binding.target.componentName,
346
+ property: choice.binding.property,
347
+ mountedCount: choice.mountedCount,
348
+ } : undefined,
349
+ };
350
+ }
351
+ function componentEvidence(candidate, choice) {
352
+ const target = choice.renderedTarget
353
+ ?? candidate.renderedTarget
354
+ ?? captureTextProjectionTarget(candidate.element, candidate.before, candidate.textNode);
355
+ return {
356
+ occurrence: target?.occurrence ?? 0,
357
+ props: target?.props ?? candidate.element.getAttribute("data-cprops"),
358
+ ariaLabel: target?.ariaLabel ?? candidate.element.getAttribute("aria-label"),
359
+ beforeText: candidate.before,
360
+ mountedCount: choice.mountedCount,
361
+ };
362
+ }
363
+ function textTargetFor(candidate, binding, choice) {
364
+ if (choice?.renderedTarget)
365
+ return choice.renderedTarget;
366
+ if (candidate.renderedTarget)
367
+ return candidate.renderedTarget;
368
+ if (binding.kind === "rendered-text")
369
+ return binding.target;
370
+ return captureTextProjectionTarget(candidate.element, candidate.before, candidate.textNode);
371
+ }
372
+ function resolveEmptyProjectionCandidate(marker) {
373
+ if (!marker.isConnected) {
374
+ return {
375
+ kind: "rejected",
376
+ reason: "no-binding",
377
+ message: "The empty rendered-text affordance is no longer connected.",
378
+ };
379
+ }
380
+ const changeId = marker.getAttribute(EMPTY_TEXT_PROJECTION_ATTR);
381
+ if (!changeId) {
382
+ return {
383
+ kind: "rejected",
384
+ reason: "no-binding",
385
+ message: "The empty rendered-text affordance has no canonical change.",
386
+ };
387
+ }
388
+ const change = getTextContentChangeById(changeId);
389
+ if (!change || change.after.length !== 0) {
390
+ return {
391
+ kind: "rejected",
392
+ reason: "no-binding",
393
+ message: "The empty rendered-text affordance is stale.",
394
+ };
395
+ }
396
+ if (marker.getAttribute(EMPTY_TEXT_PROJECTION_PATH_ATTR)
397
+ !== (change.target.textNodePath ? `path:${change.target.textNodePath.join(",")}` : "root")) {
398
+ return {
399
+ kind: "rejected",
400
+ reason: "no-binding",
401
+ message: "The empty rendered-text affordance no longer identifies its text node.",
402
+ };
403
+ }
404
+ const resolved = resolveTextProjectionTarget(marker.ownerDocument, change.target, "");
405
+ if (resolved.status !== "resolved" || !resolved.element.contains(marker)) {
406
+ return {
407
+ kind: "rejected",
408
+ reason: resolved.status === "ambiguous" ? "ambiguous-binding" : "no-binding",
409
+ message: "The empty rendered text no longer has a unique source projection.",
410
+ };
411
+ }
412
+ const textNode = resolveTextProjectionTextNode(resolved.element, change.target, "");
413
+ if (!textNode || textNode.nodeValue !== "") {
414
+ return {
415
+ kind: "rejected",
416
+ reason: "no-text",
417
+ message: "The empty rendered text is no longer available for editing.",
418
+ };
419
+ }
420
+ return {
421
+ binding: { kind: "rendered-text", target: change.target },
422
+ element: resolved.element,
423
+ textNode,
424
+ before: "",
425
+ scope: change.scope ?? "rendered-instance",
426
+ renderedTarget: change.target,
427
+ renderedSource: {
428
+ file: change.source.file,
429
+ line: change.source.line,
430
+ column: change.source.column,
431
+ component: change.source.component,
432
+ selector: change.selector,
433
+ authoredAs: change.authoredAs,
434
+ evidence: change.evidence,
435
+ },
436
+ emptyProjectionMarker: marker,
437
+ };
438
+ }
439
+ function makeSession(candidate) {
440
+ const doc = candidate.element.ownerDocument;
441
+ const originalSelection = captureSelection(doc);
442
+ const previousActiveElement = doc.activeElement instanceof HTMLElement
443
+ ? doc.activeElement
444
+ : null;
445
+ const originalParent = candidate.textNode.parentNode;
446
+ const originalNextSibling = candidate.textNode.nextSibling;
447
+ if (!originalParent) {
448
+ // `resolveTextBinding` only returns connected text nodes, but keep this
449
+ // boundary defensive if a framework mutates between resolution and wrap.
450
+ throw new Error("Inline text target lost its parent before editing began.");
451
+ }
452
+ const ownership = { parent: originalParent, nextSibling: originalNextSibling };
453
+ const capturedTarget = candidate.renderedTarget
454
+ ?? captureTextProjectionTarget(candidate.element, candidate.before, candidate.textNode);
455
+ const host = doc.createElement("span");
456
+ host.setAttribute("data-inline-editor", "true");
457
+ host.setAttribute("contenteditable", "plaintext-only");
458
+ host.contentEditable = "plaintext-only";
459
+ candidate.textNode.replaceWith(host);
460
+ // An empty Text node is retained for exact restoration, but leaving it as
461
+ // the first child of a native contenteditable makes Chromium insert the
462
+ // first character beside it. The input handler then has to coalesce two
463
+ // text nodes and the browser resets the caret to the start, reversing the
464
+ // visible draft. Let the empty editor start childless; restoreDraft still
465
+ // puts the captured node back at the owned insertion point on exit.
466
+ if (candidate.before.length > 0)
467
+ host.append(candidate.textNode);
468
+ let finished = false;
469
+ let blurCommitHandle = null;
470
+ let compositionFinalizeHandle = null;
471
+ let composing = false;
472
+ let blurPending = false;
473
+ let lastSafeText = candidate.before;
474
+ let rejectedNextInput = null;
475
+ let observer = null;
476
+ let session;
477
+ let unregisterClearHandler = null;
478
+ const ownerWindow = doc.defaultView;
479
+ const history = ownerWindow?.history;
480
+ const originalPushState = history?.pushState;
481
+ const originalReplaceState = history?.replaceState;
482
+ let patchedPushState = null;
483
+ let patchedReplaceState = null;
484
+ let selectedChoice = candidate.bindingChoices?.length === 1
485
+ ? candidate.bindingChoices[0]
486
+ : null;
487
+ let selectedScope = candidate.scope
488
+ ?? (candidate.binding.kind === "rendered-text" ? "rendered-instance" : "source-site");
489
+ function currentBinding() {
490
+ if (!selectedChoice)
491
+ return candidate.binding;
492
+ if (selectedChoice.mountedCount > 1 && selectedChoice.authoredAs !== "literal") {
493
+ const target = selectedChoice.renderedTarget
494
+ ?? candidate.renderedTarget
495
+ ?? capturedTarget;
496
+ return target ? { kind: "rendered-text", target } : selectedChoice.binding;
497
+ }
498
+ return selectedChoice.binding;
499
+ }
500
+ function currentScopeChoices() {
501
+ if (selectedChoice) {
502
+ if (selectedChoice.mountedCount > 1 && selectedChoice.authoredAs === "literal") {
503
+ return ["rendered-instance", "source-site"];
504
+ }
505
+ return [];
506
+ }
507
+ return candidate.scopeChoices ?? [];
508
+ }
509
+ function choiceForCommit() {
510
+ const choice = selectedChoice ?? candidate.bindingChoices?.[0];
511
+ const target = candidate.editableTarget;
512
+ if (choice || !target || candidate.mountedCount === undefined)
513
+ return choice ?? null;
514
+ const property = candidate.binding.kind === "component-prop"
515
+ ? candidate.binding.property
516
+ : "children";
517
+ return {
518
+ binding: candidate.binding.kind === "component-prop"
519
+ ? candidate.binding
520
+ : {
521
+ kind: "component-prop",
522
+ property,
523
+ target: {
524
+ framework: target.framework,
525
+ componentId: target.contract.componentId,
526
+ callsiteId: target.meta.callsiteId,
527
+ componentName: target.meta.componentName,
528
+ file: target.meta.file,
529
+ line: target.meta.line,
530
+ column: target.meta.column,
531
+ },
532
+ },
533
+ editableTarget: target,
534
+ mountedCount: candidate.mountedCount,
535
+ authoredAs: target.meta.authoredProps[property] ?? "default",
536
+ renderedTarget: candidate.renderedTarget ?? null,
537
+ renderedSource: candidate.renderedSource,
538
+ };
539
+ }
540
+ function prepareChange(after, binding, choice) {
541
+ if (binding.kind === "component-prop" && selectedScope === "source-site") {
542
+ const editableTarget = choice?.editableTarget ?? candidate.editableTarget;
543
+ const prop = editableTarget?.contract.props.find((item) => item.name === binding.property && item.control === "text");
544
+ if (!editableTarget || !prop)
545
+ return null;
546
+ return createComponentPropChange(editableTarget, prop, after, {
547
+ scope: "source-site",
548
+ evidence: choice && choice.mountedCount > 1
549
+ ? componentEvidence(candidate, choice)
550
+ : undefined,
551
+ });
552
+ }
553
+ const textTarget = textTargetFor(candidate, binding, choice);
554
+ const source = sourceForChoice(candidate, choice);
555
+ const renderedSource = source.selector || !textTarget
556
+ ? source
557
+ : { ...source, selector: textProjectionSelector(textTarget) ?? "" };
558
+ if (!textTarget || !renderedSource.selector)
559
+ return null;
560
+ return {
561
+ kind: "text-content",
562
+ id: `text-${globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`}`,
563
+ target: textTarget,
564
+ source: {
565
+ file: renderedSource.file,
566
+ line: renderedSource.line,
567
+ column: renderedSource.column,
568
+ component: renderedSource.component,
569
+ },
570
+ selector: renderedSource.selector,
571
+ before: candidate.before,
572
+ after,
573
+ authoredAs: renderedSource.authoredAs,
574
+ scope: selectedScope,
575
+ evidence: renderedSource.evidence,
576
+ };
577
+ }
578
+ function restoreHostText(text) {
579
+ host.replaceChildren(doc.createTextNode(text));
580
+ lastSafeText = text;
581
+ }
582
+ function resumeDraft(text) {
583
+ const original = candidate.textNode;
584
+ if (original.parentNode !== ownership.parent
585
+ || original.nextSibling !== ownership.nextSibling)
586
+ return false;
587
+ original.replaceWith(host);
588
+ restoreHostText(text);
589
+ try {
590
+ host.focus({ preventScroll: true });
591
+ }
592
+ catch {
593
+ host.focus();
594
+ }
595
+ selectAll(host);
596
+ return true;
597
+ }
598
+ function rejectInput(reason) {
599
+ recordDiagnostic({
600
+ kind: "inline-text",
601
+ status: "rejected",
602
+ reason,
603
+ before: candidate.before,
604
+ after: host.textContent ?? "",
605
+ });
606
+ }
607
+ function editorOwnsFocus() {
608
+ const active = doc.activeElement;
609
+ return active === host || (active instanceof Node && host.contains(active));
610
+ }
611
+ function cancelForReconciliation(discardedDraft) {
612
+ if (finished)
613
+ return;
614
+ const restoreFocus = editorOwnsFocus();
615
+ // A moved/reordered host has no safe insertion point. Remove only the
616
+ // temporary wrapper; never reinsert the original node into a new tree.
617
+ if (host.isConnected)
618
+ host.remove();
619
+ finish("app-reconciled", "cancelled", discardedDraft, restoreFocus);
620
+ }
621
+ function finish(reason, status, after, restoreFocus = false) {
622
+ if (finished)
623
+ return;
624
+ finished = true;
625
+ host.removeEventListener("keydown", onKeyDown);
626
+ host.removeEventListener("blur", onBlur);
627
+ host.removeEventListener("beforeinput", onBeforeInput);
628
+ host.removeEventListener("input", onInput);
629
+ host.removeEventListener("paste", onPaste);
630
+ host.removeEventListener("compositionstart", onCompositionStart);
631
+ host.removeEventListener("compositionend", onCompositionEnd);
632
+ host.removeEventListener("mousedown", suppressHostPointer);
633
+ host.removeEventListener("mouseup", suppressHostPointer);
634
+ host.removeEventListener("pointerdown", suppressHostPointer);
635
+ host.removeEventListener("pointerup", suppressHostPointer);
636
+ doc.removeEventListener("selectionchange", onSelectionChange);
637
+ doc.removeEventListener("click", suppressInteractiveAction, true);
638
+ doc.removeEventListener("mousedown", suppressInteractiveAction, true);
639
+ doc.removeEventListener("mouseup", suppressInteractiveAction, true);
640
+ doc.removeEventListener("pointerdown", suppressInteractiveAction, true);
641
+ doc.removeEventListener("pointerup", suppressInteractiveAction, true);
642
+ doc.removeEventListener("submit", suppressInteractiveAction, true);
643
+ ownerWindow?.removeEventListener("pagehide", onFrameDisposed);
644
+ ownerWindow?.removeEventListener("beforeunload", onFrameDisposed);
645
+ ownerWindow?.removeEventListener("unload", onFrameDisposed);
646
+ ownerWindow?.removeEventListener("popstate", onRouteDisposed);
647
+ ownerWindow?.removeEventListener("hashchange", onRouteDisposed);
648
+ if (history && originalPushState && history.pushState === patchedPushState) {
649
+ history.pushState = originalPushState;
650
+ }
651
+ if (history && originalReplaceState && history.replaceState === patchedReplaceState) {
652
+ history.replaceState = originalReplaceState;
653
+ }
654
+ observer?.disconnect();
655
+ observer = null;
656
+ if (blurCommitHandle !== null) {
657
+ clearTimeout(blurCommitHandle);
658
+ blurCommitHandle = null;
659
+ }
660
+ if (compositionFinalizeHandle !== null) {
661
+ clearTimeout(compositionFinalizeHandle);
662
+ compositionFinalizeHandle = null;
663
+ }
664
+ unregisterClearHandler?.();
665
+ unregisterClearHandler = null;
666
+ if (activeSession === session) {
667
+ activeSession = null;
668
+ activeSessionDocument = null;
669
+ notify();
670
+ }
671
+ if (restoreFocus) {
672
+ restoreSelection(doc, originalSelection);
673
+ if (previousActiveElement && previousActiveElement.isConnected) {
674
+ try {
675
+ previousActiveElement.focus({ preventScroll: true });
676
+ }
677
+ catch {
678
+ previousActiveElement.focus();
679
+ }
680
+ }
681
+ }
682
+ // A cancelled/unchanged re-entry keeps the same affordance. A committed
683
+ // non-empty value is synchronously reconciled by the text projection,
684
+ // which removes it after this session cleanup.
685
+ if (candidate.emptyProjectionMarker?.isConnected) {
686
+ candidate.emptyProjectionMarker.hidden = false;
687
+ }
688
+ recordDiagnostic({ kind: "inline-text", status, reason, before: candidate.before, after });
689
+ schedulePendingInlineTextEdit();
690
+ }
691
+ function onKeyDown(event) {
692
+ if (finished)
693
+ return;
694
+ if (event.isComposing || composing) {
695
+ // Enter/Escape belong to the IME until compositionend. Keeping the
696
+ // session alive makes the composition one canonical edit.
697
+ event.stopPropagation();
698
+ if (event.key === "Enter" || event.key === "Escape" || event.key === "Esc") {
699
+ event.preventDefault();
700
+ }
701
+ return;
702
+ }
703
+ if (event.key === "Enter") {
704
+ if (blurCommitHandle !== null)
705
+ clearTimeout(blurCommitHandle);
706
+ blurCommitHandle = null;
707
+ event.preventDefault();
708
+ event.stopPropagation();
709
+ session.commit();
710
+ return;
711
+ }
712
+ if (event.key === "Escape" || event.key === "Esc") {
713
+ if (blurCommitHandle !== null)
714
+ clearTimeout(blurCommitHandle);
715
+ blurCommitHandle = null;
716
+ event.preventDefault();
717
+ event.stopPropagation();
718
+ session.cancel();
719
+ return;
720
+ }
721
+ // Keep inspector keyboard authority out of the draft while allowing the
722
+ // browser to handle ordinary typing and caret movement natively. The
723
+ // listener is scoped to this host so it does not intercept native input
724
+ // before the contenteditable target sees it.
725
+ event.stopPropagation();
726
+ }
727
+ function onBlur() {
728
+ if (finished)
729
+ return;
730
+ blurPending = true;
731
+ if (composing)
732
+ return;
733
+ // Deferring one macrotask lets Escape cancel a browser blur that occurs
734
+ // while a contenteditable host is handling the key event.
735
+ blurCommitHandle = setTimeout(() => {
736
+ blurCommitHandle = null;
737
+ if (!finished) {
738
+ blurPending = false;
739
+ session.commit("blur");
740
+ }
741
+ }, 0);
742
+ }
743
+ function onBeforeInput(event) {
744
+ if (finished)
745
+ return;
746
+ const rejectBeforeInput = (reason) => {
747
+ // Some browsers still deliver input after a non-cancelable beforeinput.
748
+ // Remember the safe plain draft so that onInput can undo that mutation.
749
+ if (!event.cancelable)
750
+ rejectedNextInput = reason;
751
+ if (event.cancelable)
752
+ event.preventDefault();
753
+ event.stopPropagation();
754
+ rejectInput(reason);
755
+ };
756
+ const ranges = typeof event.getTargetRanges === "function"
757
+ ? event.getTargetRanges()
758
+ : [];
759
+ const inHost = ranges.length > 0
760
+ ? ranges.every((range) => rangeInsideHost(host, range))
761
+ : selectionInsideHost(host);
762
+ if (!inHost) {
763
+ rejectBeforeInput("cross-host-range");
764
+ return;
765
+ }
766
+ const inputType = event.inputType ?? "";
767
+ if (isParagraphInputType(inputType)) {
768
+ rejectBeforeInput("paragraph-input");
769
+ return;
770
+ }
771
+ if (!inputType) {
772
+ rejectBeforeInput("invalid-input-type");
773
+ return;
774
+ }
775
+ if (!isAllowedInputType(inputType)) {
776
+ rejectBeforeInput("rich-input");
777
+ return;
778
+ }
779
+ rejectedNextInput = null;
780
+ lastSafeText = host.textContent ?? "";
781
+ event.stopPropagation();
782
+ }
783
+ function onInput(event) {
784
+ if (finished)
785
+ return;
786
+ if (rejectedNextInput !== null) {
787
+ const reason = rejectedNextInput;
788
+ rejectedNextInput = null;
789
+ event.preventDefault();
790
+ event.stopPropagation();
791
+ restoreHostText(lastSafeText);
792
+ rejectInput(reason);
793
+ return;
794
+ }
795
+ if (hasParagraphBreak(host.textContent ?? "")) {
796
+ event.preventDefault();
797
+ restoreHostText(lastSafeText);
798
+ rejectInput("paragraph-input");
799
+ return;
800
+ }
801
+ lastSafeText = flattenHostText(host);
802
+ event.stopPropagation();
803
+ }
804
+ function onPaste(event) {
805
+ if (finished)
806
+ return;
807
+ event.preventDefault();
808
+ event.stopPropagation();
809
+ const value = plainTextFromPaste(event);
810
+ if (value === null) {
811
+ const clipboard = ownerWindow?.navigator.clipboard;
812
+ const readText = clipboard?.readText;
813
+ if (typeof readText !== "function") {
814
+ rejectInput("clipboard-unavailable");
815
+ return;
816
+ }
817
+ let clipboardResult;
818
+ try {
819
+ clipboardResult = readText.call(clipboard);
820
+ }
821
+ catch {
822
+ rejectInput("clipboard-unavailable");
823
+ return;
824
+ }
825
+ void Promise.resolve(clipboardResult)
826
+ .then((clipboardText) => {
827
+ if (finished || activeSession !== session || typeof clipboardText !== "string")
828
+ return;
829
+ if (hasParagraphBreak(clipboardText)) {
830
+ rejectInput("multiline-paste");
831
+ return;
832
+ }
833
+ if (!replaceSelectionWithPlainText(host, clipboardText)) {
834
+ rejectInput("invalid-selection");
835
+ return;
836
+ }
837
+ lastSafeText = flattenHostText(host);
838
+ })
839
+ .catch(() => {
840
+ if (!finished && activeSession === session)
841
+ rejectInput("clipboard-unavailable");
842
+ });
843
+ return;
844
+ }
845
+ if (hasParagraphBreak(value)) {
846
+ rejectInput("multiline-paste");
847
+ return;
848
+ }
849
+ if (!replaceSelectionWithPlainText(host, value)) {
850
+ rejectInput("invalid-selection");
851
+ return;
852
+ }
853
+ lastSafeText = flattenHostText(host);
854
+ }
855
+ function onCompositionStart(event) {
856
+ composing = true;
857
+ blurPending = false;
858
+ event.stopPropagation();
859
+ }
860
+ function onCompositionEnd(event) {
861
+ composing = false;
862
+ lastSafeText = flattenHostText(host);
863
+ event.stopPropagation();
864
+ if (blurPending && !finished) {
865
+ blurPending = false;
866
+ // Browsers may dispatch the final insertCompositionText/input after
867
+ // compositionend. Commit on the next macrotask so those final chars are
868
+ // part of this one canonical edit.
869
+ compositionFinalizeHandle = setTimeout(() => {
870
+ compositionFinalizeHandle = null;
871
+ if (!finished && !composing)
872
+ session.commit("blur");
873
+ }, 0);
874
+ }
875
+ }
876
+ function onSelectionChange() {
877
+ if (finished)
878
+ return;
879
+ const selection = doc.getSelection?.();
880
+ if (!selection || selection.rangeCount === 0) {
881
+ // A panel click can clear the page selection before blur; let blur own
882
+ // the normal commit path unless the editing host still owns focus.
883
+ if (doc.activeElement === host)
884
+ endLifecycle("selection-removed");
885
+ return;
886
+ }
887
+ if (selection && selection.rangeCount > 0 && selectionInsideHost(host))
888
+ return;
889
+ // A removed selection/host is a lifecycle end, not a text operation. The
890
+ // original node is restored only while its owning host is still connected.
891
+ if (!host.isConnected || !candidate.element.isConnected) {
892
+ endLifecycle(!host.isConnected ? "host-removed" : "selection-removed");
893
+ return;
894
+ }
895
+ if (doc.activeElement === host)
896
+ endLifecycle("selection-removed");
897
+ }
898
+ function suppressInteractiveAction(event) {
899
+ if (finished)
900
+ return;
901
+ const target = event.target;
902
+ if (!(target instanceof Node))
903
+ return;
904
+ if (host.contains(target)) {
905
+ // All down/up events must reach the native editing host so caret and
906
+ // drag-selection behavior remains intact. The click itself is held so
907
+ // the app cannot activate the surrounding button/link.
908
+ if (event.type === "mousedown" || event.type === "mouseup"
909
+ || event.type === "pointerdown" || event.type === "pointerup")
910
+ return;
911
+ event.preventDefault();
912
+ event.stopPropagation();
913
+ return;
914
+ }
915
+ const inspectorRoot = doc.getElementById("nudge-ui-root");
916
+ if (inspectorRoot && (target === inspectorRoot || inspectorRoot.contains(target)))
917
+ return;
918
+ // At the document boundary, application actions are suspended for the
919
+ // duration of the draft. Inspector controls live in the scoped shadow
920
+ // host above and remain usable.
921
+ if (event.type !== "mousedown" && event.type !== "mouseup"
922
+ && event.type !== "pointerdown" && event.type !== "pointerup") {
923
+ event.preventDefault();
924
+ }
925
+ event.stopPropagation();
926
+ }
927
+ function suppressHostPointer(event) {
928
+ // Keep the native default (focus transfer, caret placement, and drag
929
+ // selection) while preventing an application ancestor from observing the
930
+ // temporary host's pointer sequence.
931
+ event.stopPropagation();
932
+ }
933
+ function onFrameDisposed() {
934
+ endLifecycle("frame-disposed");
935
+ }
936
+ function onRouteDisposed() {
937
+ endLifecycle("route-disposed");
938
+ }
939
+ function patchRouteHistory() {
940
+ if (!history || !originalPushState || !originalReplaceState)
941
+ return;
942
+ try {
943
+ // SAFETY: the wrapper has the same History.pushState parameter/return contract;
944
+ // assignment is guarded by the captured native method and restored on finish.
945
+ patchedPushState = function (...args) {
946
+ if (!finished)
947
+ endLifecycle("route-disposed");
948
+ return originalPushState.apply(this, args);
949
+ };
950
+ // SAFETY: the wrapper has the same History.replaceState parameter/return contract;
951
+ // assignment is guarded by the captured native method and restored on finish.
952
+ patchedReplaceState = function (...args) {
953
+ if (!finished)
954
+ endLifecycle("route-disposed");
955
+ return originalReplaceState.apply(this, args);
956
+ };
957
+ history.pushState = patchedPushState;
958
+ history.replaceState = patchedReplaceState;
959
+ }
960
+ catch {
961
+ patchedPushState = null;
962
+ patchedReplaceState = null;
963
+ }
964
+ }
965
+ function endLifecycle(reason, discardedDraft) {
966
+ if (finished)
967
+ return;
968
+ discardPendingInlineTextEdit(doc);
969
+ const restoreFocus = editorOwnsFocus();
970
+ if (hostIsOwned(candidate, host, ownership)) {
971
+ if (!restoreDraft(candidate, host, candidate.before, ownership)) {
972
+ cancelForReconciliation();
973
+ return;
974
+ }
975
+ }
976
+ else if (host.isConnected) {
977
+ // A reconciliation can move the temporary host before removing the
978
+ // original root. It no longer has an owned insertion point, so remove
979
+ // the wrapper rather than leaking an editor into the new tree.
980
+ host.remove();
981
+ }
982
+ finish(reason, "cancelled", discardedDraft, restoreFocus);
983
+ }
984
+ session = {
985
+ get binding() {
986
+ return currentBinding();
987
+ },
988
+ get bindingChoices() {
989
+ return candidate.bindingChoices ?? [];
990
+ },
991
+ get selectedBindingIndex() {
992
+ if (!selectedChoice)
993
+ return null;
994
+ return candidate.bindingChoices?.indexOf(selectedChoice) ?? null;
995
+ },
996
+ get scope() {
997
+ return selectedScope;
998
+ },
999
+ get scopeChoices() {
1000
+ return currentScopeChoices();
1001
+ },
1002
+ host,
1003
+ before: candidate.before,
1004
+ chooseBinding(index) {
1005
+ if (finished)
1006
+ return;
1007
+ const choice = candidate.bindingChoices?.[index];
1008
+ if (!choice)
1009
+ return;
1010
+ selectedChoice = choice;
1011
+ selectedScope = choice.mountedCount > 1 && choice.authoredAs === "literal"
1012
+ ? "rendered-instance"
1013
+ : choice.mountedCount > 1 ? "rendered-instance" : "source-site";
1014
+ notify();
1015
+ },
1016
+ chooseScope(scope) {
1017
+ if (finished || !currentScopeChoices().includes(scope))
1018
+ return;
1019
+ selectedScope = scope;
1020
+ notify();
1021
+ },
1022
+ commit(reason = "commit") {
1023
+ if (finished)
1024
+ return null;
1025
+ if (composing) {
1026
+ blurPending = true;
1027
+ return null;
1028
+ }
1029
+ if ((candidate.bindingChoices?.length ?? 0) > 1 && !selectedChoice)
1030
+ return null;
1031
+ if (!hostIsOwned(candidate, host, ownership)) {
1032
+ endLifecycle(!candidate.element.isConnected ? "app-reconciled" : "host-removed");
1033
+ return null;
1034
+ }
1035
+ const after = flattenHostText(host);
1036
+ if (hasParagraphBreak(after)) {
1037
+ rejectInput("paragraph-input");
1038
+ restoreHostText(lastSafeText);
1039
+ return null;
1040
+ }
1041
+ const binding = currentBinding();
1042
+ const choice = choiceForCommit();
1043
+ const unchanged = after === candidate.before;
1044
+ const change = unchanged ? null : prepareChange(after, binding, choice);
1045
+ if (!unchanged && !change) {
1046
+ endLifecycle("app-reconciled", after);
1047
+ return null;
1048
+ }
1049
+ // Always remove the temporary host before appending the canonical
1050
+ // change. The React Adapter must own the permanent preview.
1051
+ const restoreFocus = editorOwnsFocus();
1052
+ if (!restoreDraft(candidate, host, candidate.before, ownership)) {
1053
+ cancelForReconciliation();
1054
+ return null;
1055
+ }
1056
+ if (change?.kind === "text-content" && selectedScope === "rendered-instance") {
1057
+ // The second text value is alternate evidence for re-entry after a
1058
+ // previous projection. Validation happens after unwrapping because a
1059
+ // mounted draft can make another identical root look unique.
1060
+ const resolved = resolveTextProjectionTarget(doc, change.target, candidate.before);
1061
+ if (resolved.status !== "resolved") {
1062
+ if (!resumeDraft(after))
1063
+ cancelForReconciliation(after);
1064
+ return null;
1065
+ }
1066
+ }
1067
+ if (change) {
1068
+ try {
1069
+ if (appendChange(change) === "blocked") {
1070
+ if (!resumeDraft(after))
1071
+ cancelForReconciliation(after);
1072
+ return null;
1073
+ }
1074
+ }
1075
+ catch (error) {
1076
+ if (!resumeDraft(after))
1077
+ cancelForReconciliation(after);
1078
+ throw error;
1079
+ }
1080
+ }
1081
+ finish(reason, "committed", after, restoreFocus);
1082
+ return change;
1083
+ },
1084
+ cancel(reason = "cancel") {
1085
+ if (finished)
1086
+ return;
1087
+ if (!hostIsOwned(candidate, host, ownership)) {
1088
+ endLifecycle("app-reconciled");
1089
+ return;
1090
+ }
1091
+ const restoreFocus = editorOwnsFocus();
1092
+ if (!restoreDraft(candidate, host, candidate.before, ownership)) {
1093
+ cancelForReconciliation();
1094
+ return;
1095
+ }
1096
+ finish(reason, "cancelled", candidate.before, restoreFocus);
1097
+ },
1098
+ };
1099
+ host.addEventListener("keydown", onKeyDown);
1100
+ host.addEventListener("blur", onBlur);
1101
+ host.addEventListener("beforeinput", onBeforeInput);
1102
+ host.addEventListener("input", onInput);
1103
+ host.addEventListener("paste", onPaste);
1104
+ host.addEventListener("compositionstart", onCompositionStart);
1105
+ host.addEventListener("compositionend", onCompositionEnd);
1106
+ host.addEventListener("mousedown", suppressHostPointer);
1107
+ host.addEventListener("mouseup", suppressHostPointer);
1108
+ host.addEventListener("pointerdown", suppressHostPointer);
1109
+ host.addEventListener("pointerup", suppressHostPointer);
1110
+ doc.addEventListener("selectionchange", onSelectionChange);
1111
+ for (const eventName of ["click", "mousedown", "mouseup", "pointerdown", "pointerup", "submit"]) {
1112
+ doc.addEventListener(eventName, suppressInteractiveAction, true);
1113
+ }
1114
+ patchRouteHistory();
1115
+ ownerWindow?.addEventListener("pagehide", onFrameDisposed);
1116
+ ownerWindow?.addEventListener("beforeunload", onFrameDisposed);
1117
+ ownerWindow?.addEventListener("unload", onFrameDisposed);
1118
+ ownerWindow?.addEventListener("popstate", onRouteDisposed);
1119
+ ownerWindow?.addEventListener("hashchange", onRouteDisposed);
1120
+ const OwnerMutationObserver = ownerWindow?.MutationObserver;
1121
+ if (OwnerMutationObserver && doc.documentElement) {
1122
+ observer = new OwnerMutationObserver(() => {
1123
+ if (finished)
1124
+ return;
1125
+ if (!hostIsOwned(candidate, host, ownership))
1126
+ endLifecycle("app-reconciled");
1127
+ });
1128
+ observer.observe(doc.documentElement, { childList: true, subtree: true });
1129
+ }
1130
+ activeSession = session;
1131
+ activeSessionDocument = doc;
1132
+ unregisterClearHandler = registerInlineTextClearHandler(cancelInlineTextEdit);
1133
+ notify();
1134
+ recordDiagnostic({ kind: "inline-text", status: "started", reason: "start", before: candidate.before });
1135
+ host.focus();
1136
+ selectAll(host);
1137
+ return session;
1138
+ }
1139
+ export const inlineTextEditor = {
1140
+ begin(element, point) {
1141
+ if (!isNudgeUiDev()) {
1142
+ return {
1143
+ kind: "rejected",
1144
+ reason: "no-binding",
1145
+ message: "Inline text editing is available only in development.",
1146
+ };
1147
+ }
1148
+ if (activeSession) {
1149
+ return {
1150
+ kind: "rejected",
1151
+ reason: "editing-active",
1152
+ message: "Finish the current inline text edit first.",
1153
+ };
1154
+ }
1155
+ const candidate = resolveTextBinding(element, point);
1156
+ if (isTextEditRejection(candidate))
1157
+ return candidate;
1158
+ return makeSession(candidate);
1159
+ },
1160
+ };
1161
+ /** Re-enter an existing canonical rendered-text projection through its empty
1162
+ * inspector affordance. This never guesses a new DOM target or source node. */
1163
+ export function beginInlineTextEditFromEmptyProjection(marker) {
1164
+ if (!isNudgeUiDev()) {
1165
+ return {
1166
+ kind: "rejected",
1167
+ reason: "no-binding",
1168
+ message: "Inline text editing is available only in development.",
1169
+ };
1170
+ }
1171
+ if (activeSession) {
1172
+ return {
1173
+ kind: "rejected",
1174
+ reason: "editing-active",
1175
+ message: "Finish the current inline text edit first.",
1176
+ };
1177
+ }
1178
+ const candidate = resolveEmptyProjectionCandidate(marker);
1179
+ if (isTextEditRejection(candidate))
1180
+ return candidate;
1181
+ // Hide the affordance while its retained empty Text node is wrapped by the
1182
+ // native editor. The marker is restored on cancel and removed by projection
1183
+ // reconciliation on a successful non-empty commit.
1184
+ marker.hidden = true;
1185
+ try {
1186
+ return makeSession(candidate);
1187
+ }
1188
+ catch {
1189
+ marker.hidden = false;
1190
+ return {
1191
+ kind: "rejected",
1192
+ reason: "no-binding",
1193
+ message: "The empty rendered text could not be reopened safely.",
1194
+ };
1195
+ }
1196
+ }
1197
+ export function beginInlineTextEdit(element, point) {
1198
+ if (!isNudgeUiDev()) {
1199
+ return {
1200
+ kind: "rejected",
1201
+ reason: "no-binding",
1202
+ message: "Inline text editing is available only in development.",
1203
+ };
1204
+ }
1205
+ return inlineTextEditor.begin(element, point);
1206
+ }
1207
+ export { resolveTextBinding } from "../componentSemantics/textBinding.js";