donobu 2.15.0 → 2.16.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 (402) hide show
  1. package/dist/apis/FlowsFilesApi.d.ts.map +1 -1
  2. package/dist/apis/FlowsFilesApi.js +5 -2
  3. package/dist/apis/FlowsFilesApi.js.map +1 -1
  4. package/dist/assets/control-panel.js +30 -3
  5. package/dist/assets/generated/parameter-schemas.json +118 -17
  6. package/dist/assets/generated/version +1 -1
  7. package/dist/assets/interactive-elements-tracker.js +351 -0
  8. package/dist/assets/page-interactions-tracker.js +39 -20
  9. package/dist/assets/smart-selector-generator.js +38 -15
  10. package/dist/bindings/FocusPage.d.ts +6 -1
  11. package/dist/bindings/FocusPage.d.ts.map +1 -1
  12. package/dist/bindings/FocusPage.js +2 -8
  13. package/dist/bindings/FocusPage.js.map +1 -1
  14. package/dist/bindings/PageInteractionTracker.d.ts +9 -2
  15. package/dist/bindings/PageInteractionTracker.d.ts.map +1 -1
  16. package/dist/bindings/PageInteractionTracker.js +29 -5
  17. package/dist/bindings/PageInteractionTracker.js.map +1 -1
  18. package/dist/bindings/ProposeToolCall.d.ts +20 -0
  19. package/dist/bindings/ProposeToolCall.d.ts.map +1 -0
  20. package/dist/bindings/ProposeToolCall.js +29 -0
  21. package/dist/bindings/ProposeToolCall.js.map +1 -0
  22. package/dist/bindings/ToggleDonobuAnnotations.d.ts +5 -2
  23. package/dist/bindings/ToggleDonobuAnnotations.d.ts.map +1 -1
  24. package/dist/bindings/ToggleDonobuAnnotations.js +12 -6
  25. package/dist/bindings/ToggleDonobuAnnotations.js.map +1 -1
  26. package/dist/clients/AnthropicAwsBedrockGptClient.d.ts +1 -20
  27. package/dist/clients/AnthropicAwsBedrockGptClient.d.ts.map +1 -1
  28. package/dist/clients/AnthropicAwsBedrockGptClient.js +12 -329
  29. package/dist/clients/AnthropicAwsBedrockGptClient.js.map +1 -1
  30. package/dist/clients/AnthropicGptClient.d.ts +0 -8
  31. package/dist/clients/AnthropicGptClient.d.ts.map +1 -1
  32. package/dist/clients/AnthropicGptClient.js +8 -22
  33. package/dist/clients/AnthropicGptClient.js.map +1 -1
  34. package/dist/clients/GoogleGptClient.d.ts +4 -20
  35. package/dist/clients/GoogleGptClient.d.ts.map +1 -1
  36. package/dist/clients/GoogleGptClient.js +23 -299
  37. package/dist/clients/GoogleGptClient.js.map +1 -1
  38. package/dist/clients/OpenAiGptClient.d.ts +0 -6
  39. package/dist/clients/OpenAiGptClient.d.ts.map +1 -1
  40. package/dist/clients/OpenAiGptClient.js +4 -8
  41. package/dist/clients/OpenAiGptClient.js.map +1 -1
  42. package/dist/clients/VercelAiGptClient.d.ts +3 -1
  43. package/dist/clients/VercelAiGptClient.d.ts.map +1 -1
  44. package/dist/clients/VercelAiGptClient.js +18 -14
  45. package/dist/clients/VercelAiGptClient.js.map +1 -1
  46. package/dist/esm/apis/FlowsFilesApi.d.ts.map +1 -1
  47. package/dist/esm/apis/FlowsFilesApi.js +5 -2
  48. package/dist/esm/apis/FlowsFilesApi.js.map +1 -1
  49. package/dist/esm/assets/control-panel.js +30 -3
  50. package/dist/esm/assets/generated/parameter-schemas.json +118 -17
  51. package/dist/esm/assets/generated/version +1 -1
  52. package/dist/esm/assets/interactive-elements-tracker.js +351 -0
  53. package/dist/esm/assets/page-interactions-tracker.js +39 -20
  54. package/dist/esm/assets/smart-selector-generator.js +38 -15
  55. package/dist/esm/bindings/FocusPage.d.ts +6 -1
  56. package/dist/esm/bindings/FocusPage.d.ts.map +1 -1
  57. package/dist/esm/bindings/FocusPage.js +2 -8
  58. package/dist/esm/bindings/FocusPage.js.map +1 -1
  59. package/dist/esm/bindings/PageInteractionTracker.d.ts +9 -2
  60. package/dist/esm/bindings/PageInteractionTracker.d.ts.map +1 -1
  61. package/dist/esm/bindings/PageInteractionTracker.js +29 -5
  62. package/dist/esm/bindings/PageInteractionTracker.js.map +1 -1
  63. package/dist/esm/bindings/ProposeToolCall.d.ts +20 -0
  64. package/dist/esm/bindings/ProposeToolCall.d.ts.map +1 -0
  65. package/dist/esm/bindings/ProposeToolCall.js +29 -0
  66. package/dist/esm/bindings/ProposeToolCall.js.map +1 -0
  67. package/dist/esm/bindings/ToggleDonobuAnnotations.d.ts +5 -2
  68. package/dist/esm/bindings/ToggleDonobuAnnotations.d.ts.map +1 -1
  69. package/dist/esm/bindings/ToggleDonobuAnnotations.js +12 -6
  70. package/dist/esm/bindings/ToggleDonobuAnnotations.js.map +1 -1
  71. package/dist/esm/clients/AnthropicAwsBedrockGptClient.d.ts +1 -20
  72. package/dist/esm/clients/AnthropicAwsBedrockGptClient.d.ts.map +1 -1
  73. package/dist/esm/clients/AnthropicAwsBedrockGptClient.js +12 -329
  74. package/dist/esm/clients/AnthropicAwsBedrockGptClient.js.map +1 -1
  75. package/dist/esm/clients/AnthropicGptClient.d.ts +0 -8
  76. package/dist/esm/clients/AnthropicGptClient.d.ts.map +1 -1
  77. package/dist/esm/clients/AnthropicGptClient.js +8 -22
  78. package/dist/esm/clients/AnthropicGptClient.js.map +1 -1
  79. package/dist/esm/clients/GoogleGptClient.d.ts +4 -20
  80. package/dist/esm/clients/GoogleGptClient.d.ts.map +1 -1
  81. package/dist/esm/clients/GoogleGptClient.js +23 -299
  82. package/dist/esm/clients/GoogleGptClient.js.map +1 -1
  83. package/dist/esm/clients/OpenAiGptClient.d.ts +0 -6
  84. package/dist/esm/clients/OpenAiGptClient.d.ts.map +1 -1
  85. package/dist/esm/clients/OpenAiGptClient.js +4 -8
  86. package/dist/esm/clients/OpenAiGptClient.js.map +1 -1
  87. package/dist/esm/clients/VercelAiGptClient.d.ts +3 -1
  88. package/dist/esm/clients/VercelAiGptClient.d.ts.map +1 -1
  89. package/dist/esm/clients/VercelAiGptClient.js +18 -14
  90. package/dist/esm/clients/VercelAiGptClient.js.map +1 -1
  91. package/dist/esm/managers/CodeGenerator.d.ts.map +1 -1
  92. package/dist/esm/managers/CodeGenerator.js +2 -1
  93. package/dist/esm/managers/CodeGenerator.js.map +1 -1
  94. package/dist/esm/managers/ControlPanel.d.ts +124 -0
  95. package/dist/esm/managers/ControlPanel.d.ts.map +1 -0
  96. package/dist/esm/managers/ControlPanel.js +282 -0
  97. package/dist/esm/managers/ControlPanel.js.map +1 -0
  98. package/dist/esm/managers/DonobuFlow.d.ts +9 -13
  99. package/dist/esm/managers/DonobuFlow.d.ts.map +1 -1
  100. package/dist/esm/managers/DonobuFlow.js +123 -172
  101. package/dist/esm/managers/DonobuFlow.js.map +1 -1
  102. package/dist/esm/managers/InteractionVisualizer.d.ts +9 -15
  103. package/dist/esm/managers/InteractionVisualizer.d.ts.map +1 -1
  104. package/dist/esm/managers/InteractionVisualizer.js +44 -44
  105. package/dist/esm/managers/InteractionVisualizer.js.map +1 -1
  106. package/dist/esm/managers/PageInspector.d.ts +242 -0
  107. package/dist/esm/managers/PageInspector.d.ts.map +1 -0
  108. package/dist/esm/managers/PageInspector.js +783 -0
  109. package/dist/esm/managers/PageInspector.js.map +1 -0
  110. package/dist/esm/managers/ToolManager.d.ts.map +1 -1
  111. package/dist/esm/managers/ToolManager.js +4 -6
  112. package/dist/esm/managers/ToolManager.js.map +1 -1
  113. package/dist/esm/models/GptMessage.d.ts +3 -3
  114. package/dist/esm/models/GptMessage.d.ts.map +1 -1
  115. package/dist/esm/models/InteractableElement.d.ts +2 -2
  116. package/dist/esm/models/ToolCallContext.d.ts +6 -2
  117. package/dist/esm/models/ToolCallContext.d.ts.map +1 -1
  118. package/dist/esm/persistence/FlowsPersistence.d.ts +4 -4
  119. package/dist/esm/persistence/FlowsPersistence.d.ts.map +1 -1
  120. package/dist/esm/persistence/FlowsPersistenceAwsS3.d.ts +2 -3
  121. package/dist/esm/persistence/FlowsPersistenceAwsS3.d.ts.map +1 -1
  122. package/dist/esm/persistence/FlowsPersistenceAwsS3.js +8 -6
  123. package/dist/esm/persistence/FlowsPersistenceAwsS3.js.map +1 -1
  124. package/dist/esm/persistence/FlowsPersistenceFilesystem.d.ts +2 -3
  125. package/dist/esm/persistence/FlowsPersistenceFilesystem.d.ts.map +1 -1
  126. package/dist/esm/persistence/FlowsPersistenceFilesystem.js +5 -4
  127. package/dist/esm/persistence/FlowsPersistenceFilesystem.js.map +1 -1
  128. package/dist/esm/persistence/FlowsPersistenceGoogleCloudStorage.d.ts +2 -3
  129. package/dist/esm/persistence/FlowsPersistenceGoogleCloudStorage.d.ts.map +1 -1
  130. package/dist/esm/persistence/FlowsPersistenceGoogleCloudStorage.js +7 -5
  131. package/dist/esm/persistence/FlowsPersistenceGoogleCloudStorage.js.map +1 -1
  132. package/dist/esm/persistence/FlowsPersistenceSqlite.d.ts +2 -3
  133. package/dist/esm/persistence/FlowsPersistenceSqlite.d.ts.map +1 -1
  134. package/dist/esm/persistence/FlowsPersistenceSqlite.js +8 -6
  135. package/dist/esm/persistence/FlowsPersistenceSqlite.js.map +1 -1
  136. package/dist/esm/persistence/FlowsPersistenceSupabase.d.ts +2 -2
  137. package/dist/esm/persistence/FlowsPersistenceSupabase.d.ts.map +1 -1
  138. package/dist/esm/persistence/FlowsPersistenceSupabase.js +5 -3
  139. package/dist/esm/persistence/FlowsPersistenceSupabase.js.map +1 -1
  140. package/dist/esm/persistence/FlowsPersistenceVolatile.d.ts +2 -2
  141. package/dist/esm/persistence/FlowsPersistenceVolatile.d.ts.map +1 -1
  142. package/dist/esm/persistence/FlowsPersistenceVolatile.js +5 -3
  143. package/dist/esm/persistence/FlowsPersistenceVolatile.js.map +1 -1
  144. package/dist/esm/playwrightTestExtensions.d.ts +5 -0
  145. package/dist/esm/playwrightTestExtensions.d.ts.map +1 -1
  146. package/dist/esm/playwrightTestExtensions.js +56 -17
  147. package/dist/esm/playwrightTestExtensions.js.map +1 -1
  148. package/dist/esm/tools/AnalyzePageTextTool.js +1 -1
  149. package/dist/esm/tools/AnalyzePageTextTool.js.map +1 -1
  150. package/dist/esm/tools/AssertPageTextTool.js +1 -1
  151. package/dist/esm/tools/AssertPageTextTool.js.map +1 -1
  152. package/dist/esm/tools/AssertTool.d.ts.map +1 -1
  153. package/dist/esm/tools/AssertTool.js +5 -5
  154. package/dist/esm/tools/AssertTool.js.map +1 -1
  155. package/dist/esm/tools/ChangeWebBrowserTabTool.d.ts.map +1 -1
  156. package/dist/esm/tools/ChangeWebBrowserTabTool.js +8 -7
  157. package/dist/esm/tools/ChangeWebBrowserTabTool.js.map +1 -1
  158. package/dist/esm/tools/ClickTool.js +1 -1
  159. package/dist/esm/tools/ClickTool.js.map +1 -1
  160. package/dist/esm/tools/CreateBrowserCookieReportTool.js +1 -1
  161. package/dist/esm/tools/CreateBrowserCookieReportTool.js.map +1 -1
  162. package/dist/esm/tools/CustomToolRunnerTool.d.ts.map +1 -1
  163. package/dist/esm/tools/CustomToolRunnerTool.js +1 -1
  164. package/dist/esm/tools/CustomToolRunnerTool.js.map +1 -1
  165. package/dist/esm/tools/DetectBrokenLinksTool.d.ts.map +1 -1
  166. package/dist/esm/tools/DetectBrokenLinksTool.js +5 -3
  167. package/dist/esm/tools/DetectBrokenLinksTool.js.map +1 -1
  168. package/dist/esm/tools/ExtractGoogleStreetviewEntityDataTool.js +4 -4
  169. package/dist/esm/tools/ExtractGoogleStreetviewEntityDataTool.js.map +1 -1
  170. package/dist/esm/tools/ExtractPaymentProviderKeyTool.js +1 -1
  171. package/dist/esm/tools/ExtractPaymentProviderKeyTool.js.map +1 -1
  172. package/dist/esm/tools/ExtractPublicFacebookEntityDataTool.js +1 -1
  173. package/dist/esm/tools/ExtractPublicFacebookEntityDataTool.js.map +1 -1
  174. package/dist/esm/tools/GoForwardOrBackTool.js +1 -1
  175. package/dist/esm/tools/GoForwardOrBackTool.js.map +1 -1
  176. package/dist/esm/tools/GoToGoogleMapsStreetViewTool.js +1 -1
  177. package/dist/esm/tools/GoToGoogleMapsStreetViewTool.js.map +1 -1
  178. package/dist/esm/tools/GoToWebpageTool.js +1 -1
  179. package/dist/esm/tools/GoToWebpageTool.js.map +1 -1
  180. package/dist/esm/tools/HoverOverElementTool.d.ts.map +1 -1
  181. package/dist/esm/tools/HoverOverElementTool.js +1 -1
  182. package/dist/esm/tools/HoverOverElementTool.js.map +1 -1
  183. package/dist/esm/tools/NavigateWithinStreetView.js +1 -1
  184. package/dist/esm/tools/NavigateWithinStreetView.js.map +1 -1
  185. package/dist/esm/tools/PressKeyTool.js +1 -1
  186. package/dist/esm/tools/PressKeyTool.js.map +1 -1
  187. package/dist/esm/tools/ReloadPageTool.js +1 -1
  188. package/dist/esm/tools/ReloadPageTool.js.map +1 -1
  189. package/dist/esm/tools/ReplayableInteraction.d.ts +16 -1
  190. package/dist/esm/tools/ReplayableInteraction.d.ts.map +1 -1
  191. package/dist/esm/tools/ReplayableInteraction.js +169 -16
  192. package/dist/esm/tools/ReplayableInteraction.js.map +1 -1
  193. package/dist/esm/tools/RunAccessibilityTestTool.d.ts +8 -0
  194. package/dist/esm/tools/RunAccessibilityTestTool.d.ts.map +1 -1
  195. package/dist/esm/tools/RunAccessibilityTestTool.js +15 -2
  196. package/dist/esm/tools/RunAccessibilityTestTool.js.map +1 -1
  197. package/dist/esm/tools/RunInlineJavaScriptCodeTool.d.ts.map +1 -1
  198. package/dist/esm/tools/RunInlineJavaScriptCodeTool.js +1 -1
  199. package/dist/esm/tools/RunInlineJavaScriptCodeTool.js.map +1 -1
  200. package/dist/esm/tools/SaveWebpageAsPdfTool.js +1 -1
  201. package/dist/esm/tools/SaveWebpageAsPdfTool.js.map +1 -1
  202. package/dist/esm/tools/ScrollPageTool.d.ts +1 -1
  203. package/dist/esm/tools/ScrollPageTool.d.ts.map +1 -1
  204. package/dist/esm/tools/ScrollPageTool.js +47 -4
  205. package/dist/esm/tools/ScrollPageTool.js.map +1 -1
  206. package/dist/esm/tools/WaitTool.js +1 -1
  207. package/dist/esm/tools/WaitTool.js.map +1 -1
  208. package/dist/esm/utils/MiscUtils.d.ts +10 -13
  209. package/dist/esm/utils/MiscUtils.d.ts.map +1 -1
  210. package/dist/esm/utils/MiscUtils.js +92 -56
  211. package/dist/esm/utils/MiscUtils.js.map +1 -1
  212. package/dist/esm/utils/PlaywrightUtils.d.ts +32 -130
  213. package/dist/esm/utils/PlaywrightUtils.d.ts.map +1 -1
  214. package/dist/esm/utils/PlaywrightUtils.js +140 -938
  215. package/dist/esm/utils/PlaywrightUtils.js.map +1 -1
  216. package/dist/managers/CodeGenerator.d.ts.map +1 -1
  217. package/dist/managers/CodeGenerator.js +2 -1
  218. package/dist/managers/CodeGenerator.js.map +1 -1
  219. package/dist/managers/ControlPanel.d.ts +124 -0
  220. package/dist/managers/ControlPanel.d.ts.map +1 -0
  221. package/dist/managers/ControlPanel.js +282 -0
  222. package/dist/managers/ControlPanel.js.map +1 -0
  223. package/dist/managers/DonobuFlow.d.ts +9 -13
  224. package/dist/managers/DonobuFlow.d.ts.map +1 -1
  225. package/dist/managers/DonobuFlow.js +123 -172
  226. package/dist/managers/DonobuFlow.js.map +1 -1
  227. package/dist/managers/InteractionVisualizer.d.ts +9 -15
  228. package/dist/managers/InteractionVisualizer.d.ts.map +1 -1
  229. package/dist/managers/InteractionVisualizer.js +44 -44
  230. package/dist/managers/InteractionVisualizer.js.map +1 -1
  231. package/dist/managers/PageInspector.d.ts +242 -0
  232. package/dist/managers/PageInspector.d.ts.map +1 -0
  233. package/dist/managers/PageInspector.js +783 -0
  234. package/dist/managers/PageInspector.js.map +1 -0
  235. package/dist/managers/ToolManager.d.ts.map +1 -1
  236. package/dist/managers/ToolManager.js +4 -6
  237. package/dist/managers/ToolManager.js.map +1 -1
  238. package/dist/models/GptMessage.d.ts +3 -3
  239. package/dist/models/GptMessage.d.ts.map +1 -1
  240. package/dist/models/InteractableElement.d.ts +2 -2
  241. package/dist/models/ToolCallContext.d.ts +6 -2
  242. package/dist/models/ToolCallContext.d.ts.map +1 -1
  243. package/dist/persistence/FlowsPersistence.d.ts +4 -4
  244. package/dist/persistence/FlowsPersistence.d.ts.map +1 -1
  245. package/dist/persistence/FlowsPersistenceAwsS3.d.ts +2 -3
  246. package/dist/persistence/FlowsPersistenceAwsS3.d.ts.map +1 -1
  247. package/dist/persistence/FlowsPersistenceAwsS3.js +8 -6
  248. package/dist/persistence/FlowsPersistenceAwsS3.js.map +1 -1
  249. package/dist/persistence/FlowsPersistenceFilesystem.d.ts +2 -3
  250. package/dist/persistence/FlowsPersistenceFilesystem.d.ts.map +1 -1
  251. package/dist/persistence/FlowsPersistenceFilesystem.js +5 -4
  252. package/dist/persistence/FlowsPersistenceFilesystem.js.map +1 -1
  253. package/dist/persistence/FlowsPersistenceGoogleCloudStorage.d.ts +2 -3
  254. package/dist/persistence/FlowsPersistenceGoogleCloudStorage.d.ts.map +1 -1
  255. package/dist/persistence/FlowsPersistenceGoogleCloudStorage.js +7 -5
  256. package/dist/persistence/FlowsPersistenceGoogleCloudStorage.js.map +1 -1
  257. package/dist/persistence/FlowsPersistenceSqlite.d.ts +2 -3
  258. package/dist/persistence/FlowsPersistenceSqlite.d.ts.map +1 -1
  259. package/dist/persistence/FlowsPersistenceSqlite.js +8 -6
  260. package/dist/persistence/FlowsPersistenceSqlite.js.map +1 -1
  261. package/dist/persistence/FlowsPersistenceSupabase.d.ts +2 -2
  262. package/dist/persistence/FlowsPersistenceSupabase.d.ts.map +1 -1
  263. package/dist/persistence/FlowsPersistenceSupabase.js +5 -3
  264. package/dist/persistence/FlowsPersistenceSupabase.js.map +1 -1
  265. package/dist/persistence/FlowsPersistenceVolatile.d.ts +2 -2
  266. package/dist/persistence/FlowsPersistenceVolatile.d.ts.map +1 -1
  267. package/dist/persistence/FlowsPersistenceVolatile.js +5 -3
  268. package/dist/persistence/FlowsPersistenceVolatile.js.map +1 -1
  269. package/dist/playwrightTestExtensions.d.ts +5 -0
  270. package/dist/playwrightTestExtensions.d.ts.map +1 -1
  271. package/dist/playwrightTestExtensions.js +56 -17
  272. package/dist/playwrightTestExtensions.js.map +1 -1
  273. package/dist/tools/AnalyzePageTextTool.js +1 -1
  274. package/dist/tools/AnalyzePageTextTool.js.map +1 -1
  275. package/dist/tools/AssertPageTextTool.js +1 -1
  276. package/dist/tools/AssertPageTextTool.js.map +1 -1
  277. package/dist/tools/AssertTool.d.ts.map +1 -1
  278. package/dist/tools/AssertTool.js +5 -5
  279. package/dist/tools/AssertTool.js.map +1 -1
  280. package/dist/tools/ChangeWebBrowserTabTool.d.ts.map +1 -1
  281. package/dist/tools/ChangeWebBrowserTabTool.js +8 -7
  282. package/dist/tools/ChangeWebBrowserTabTool.js.map +1 -1
  283. package/dist/tools/ClickTool.js +1 -1
  284. package/dist/tools/ClickTool.js.map +1 -1
  285. package/dist/tools/CreateBrowserCookieReportTool.js +1 -1
  286. package/dist/tools/CreateBrowserCookieReportTool.js.map +1 -1
  287. package/dist/tools/CustomToolRunnerTool.d.ts.map +1 -1
  288. package/dist/tools/CustomToolRunnerTool.js +1 -1
  289. package/dist/tools/CustomToolRunnerTool.js.map +1 -1
  290. package/dist/tools/DetectBrokenLinksTool.d.ts.map +1 -1
  291. package/dist/tools/DetectBrokenLinksTool.js +5 -3
  292. package/dist/tools/DetectBrokenLinksTool.js.map +1 -1
  293. package/dist/tools/ExtractGoogleStreetviewEntityDataTool.js +4 -4
  294. package/dist/tools/ExtractGoogleStreetviewEntityDataTool.js.map +1 -1
  295. package/dist/tools/ExtractPaymentProviderKeyTool.js +1 -1
  296. package/dist/tools/ExtractPaymentProviderKeyTool.js.map +1 -1
  297. package/dist/tools/ExtractPublicFacebookEntityDataTool.js +1 -1
  298. package/dist/tools/ExtractPublicFacebookEntityDataTool.js.map +1 -1
  299. package/dist/tools/GoForwardOrBackTool.js +1 -1
  300. package/dist/tools/GoForwardOrBackTool.js.map +1 -1
  301. package/dist/tools/GoToGoogleMapsStreetViewTool.js +1 -1
  302. package/dist/tools/GoToGoogleMapsStreetViewTool.js.map +1 -1
  303. package/dist/tools/GoToWebpageTool.js +1 -1
  304. package/dist/tools/GoToWebpageTool.js.map +1 -1
  305. package/dist/tools/HoverOverElementTool.d.ts.map +1 -1
  306. package/dist/tools/HoverOverElementTool.js +1 -1
  307. package/dist/tools/HoverOverElementTool.js.map +1 -1
  308. package/dist/tools/NavigateWithinStreetView.js +1 -1
  309. package/dist/tools/NavigateWithinStreetView.js.map +1 -1
  310. package/dist/tools/PressKeyTool.js +1 -1
  311. package/dist/tools/PressKeyTool.js.map +1 -1
  312. package/dist/tools/ReloadPageTool.js +1 -1
  313. package/dist/tools/ReloadPageTool.js.map +1 -1
  314. package/dist/tools/ReplayableInteraction.d.ts +16 -1
  315. package/dist/tools/ReplayableInteraction.d.ts.map +1 -1
  316. package/dist/tools/ReplayableInteraction.js +169 -16
  317. package/dist/tools/ReplayableInteraction.js.map +1 -1
  318. package/dist/tools/RunAccessibilityTestTool.d.ts +8 -0
  319. package/dist/tools/RunAccessibilityTestTool.d.ts.map +1 -1
  320. package/dist/tools/RunAccessibilityTestTool.js +15 -2
  321. package/dist/tools/RunAccessibilityTestTool.js.map +1 -1
  322. package/dist/tools/RunInlineJavaScriptCodeTool.d.ts.map +1 -1
  323. package/dist/tools/RunInlineJavaScriptCodeTool.js +1 -1
  324. package/dist/tools/RunInlineJavaScriptCodeTool.js.map +1 -1
  325. package/dist/tools/SaveWebpageAsPdfTool.js +1 -1
  326. package/dist/tools/SaveWebpageAsPdfTool.js.map +1 -1
  327. package/dist/tools/ScrollPageTool.d.ts +1 -1
  328. package/dist/tools/ScrollPageTool.d.ts.map +1 -1
  329. package/dist/tools/ScrollPageTool.js +47 -4
  330. package/dist/tools/ScrollPageTool.js.map +1 -1
  331. package/dist/tools/WaitTool.js +1 -1
  332. package/dist/tools/WaitTool.js.map +1 -1
  333. package/dist/utils/MiscUtils.d.ts +10 -13
  334. package/dist/utils/MiscUtils.d.ts.map +1 -1
  335. package/dist/utils/MiscUtils.js +92 -56
  336. package/dist/utils/MiscUtils.js.map +1 -1
  337. package/dist/utils/PlaywrightUtils.d.ts +32 -130
  338. package/dist/utils/PlaywrightUtils.d.ts.map +1 -1
  339. package/dist/utils/PlaywrightUtils.js +140 -938
  340. package/dist/utils/PlaywrightUtils.js.map +1 -1
  341. package/package.json +4 -2
  342. package/dist/assets/clickable-elements-tracker.js +0 -63
  343. package/dist/assets/zaru-eyes.html +0 -141
  344. package/dist/esm/assets/clickable-elements-tracker.js +0 -63
  345. package/dist/esm/assets/zaru-eyes.html +0 -141
  346. package/dist/esm/managers/TemplateInterpolator.d.ts +0 -19
  347. package/dist/esm/managers/TemplateInterpolator.d.ts.map +0 -1
  348. package/dist/esm/managers/TemplateInterpolator.js +0 -86
  349. package/dist/esm/managers/TemplateInterpolator.js.map +0 -1
  350. package/dist/esm/managers/ToolTipper.d.ts +0 -32
  351. package/dist/esm/managers/ToolTipper.d.ts.map +0 -1
  352. package/dist/esm/managers/ToolTipper.js +0 -229
  353. package/dist/esm/managers/ToolTipper.js.map +0 -1
  354. package/dist/esm/models/BrowserState.d.ts +0 -26
  355. package/dist/esm/models/BrowserState.d.ts.map +0 -1
  356. package/dist/esm/models/BrowserState.js +0 -3
  357. package/dist/esm/models/BrowserState.js.map +0 -1
  358. package/dist/esm/models/ResolverContext.d.ts +0 -7
  359. package/dist/esm/models/ResolverContext.d.ts.map +0 -1
  360. package/dist/esm/models/ResolverContext.js +0 -3
  361. package/dist/esm/models/ResolverContext.js.map +0 -1
  362. package/dist/esm/models/ToolTemplateDataSource.d.ts +0 -36
  363. package/dist/esm/models/ToolTemplateDataSource.d.ts.map +0 -1
  364. package/dist/esm/models/ToolTemplateDataSource.js +0 -3
  365. package/dist/esm/models/ToolTemplateDataSource.js.map +0 -1
  366. package/dist/esm/test.d.ts +0 -78
  367. package/dist/esm/test.d.ts.map +0 -1
  368. package/dist/esm/test.js +0 -423
  369. package/dist/esm/test.js.map +0 -1
  370. package/dist/esm/utils/TemplateInterpolator.d.ts +0 -29
  371. package/dist/esm/utils/TemplateInterpolator.d.ts.map +0 -1
  372. package/dist/esm/utils/TemplateInterpolator.js +0 -206
  373. package/dist/esm/utils/TemplateInterpolator.js.map +0 -1
  374. package/dist/managers/TemplateInterpolator.d.ts +0 -19
  375. package/dist/managers/TemplateInterpolator.d.ts.map +0 -1
  376. package/dist/managers/TemplateInterpolator.js +0 -86
  377. package/dist/managers/TemplateInterpolator.js.map +0 -1
  378. package/dist/managers/ToolTipper.d.ts +0 -32
  379. package/dist/managers/ToolTipper.d.ts.map +0 -1
  380. package/dist/managers/ToolTipper.js +0 -229
  381. package/dist/managers/ToolTipper.js.map +0 -1
  382. package/dist/models/BrowserState.d.ts +0 -26
  383. package/dist/models/BrowserState.d.ts.map +0 -1
  384. package/dist/models/BrowserState.js +0 -3
  385. package/dist/models/BrowserState.js.map +0 -1
  386. package/dist/models/ResolverContext.d.ts +0 -7
  387. package/dist/models/ResolverContext.d.ts.map +0 -1
  388. package/dist/models/ResolverContext.js +0 -3
  389. package/dist/models/ResolverContext.js.map +0 -1
  390. package/dist/models/ToolTemplateDataSource.d.ts +0 -36
  391. package/dist/models/ToolTemplateDataSource.d.ts.map +0 -1
  392. package/dist/models/ToolTemplateDataSource.js +0 -3
  393. package/dist/models/ToolTemplateDataSource.js.map +0 -1
  394. package/dist/test.d.ts +0 -78
  395. package/dist/test.d.ts.map +0 -1
  396. package/dist/test.js +0 -423
  397. package/dist/test.js.map +0 -1
  398. package/dist/tsconfig.esm.tsbuildinfo +0 -1
  399. package/dist/utils/TemplateInterpolator.d.ts +0 -29
  400. package/dist/utils/TemplateInterpolator.d.ts.map +0 -1
  401. package/dist/utils/TemplateInterpolator.js +0 -211
  402. package/dist/utils/TemplateInterpolator.js.map +0 -1
@@ -0,0 +1,783 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PageInspector = void 0;
7
+ const PageClosedException_1 = require("../exceptions/PageClosedException");
8
+ const PlaywrightUtils_1 = require("../utils/PlaywrightUtils");
9
+ const MiscUtils_1 = require("../utils/MiscUtils");
10
+ const path_1 = __importDefault(require("path"));
11
+ /**
12
+ * A class for identifying, attributing, and annotating interactable elements on web pages.
13
+ *
14
+ * The PageInspector provides functionality to:
15
+ * - Find and attribute interactable elements with unique identifiers
16
+ * - Retrieve information about attributed elements
17
+ * - Add visual annotations (numbered indicators) to interactable elements
18
+ * - Clean up both attributes and annotations
19
+ *
20
+ * Interactable elements are determined using comprehensive heuristics including:
21
+ * - Standard HTML interactive elements (buttons, inputs, links, etc.)
22
+ * - Elements with ARIA roles indicating interactivity
23
+ * - Elements with event handlers or CSS classes suggesting interactivity
24
+ * - Elements that are visible, enabled, and accessible at their coordinates
25
+ *
26
+ * This class is designed to work with Playwright's Page and Frame objects
27
+ * and handles cross-frame navigation, shadow DOM, and various edge cases.
28
+ *
29
+ * WARNING: It is REQUIRED that the {@link PageInspector.INIT_SCRIPT} has been
30
+ * run in the browser context before calling this class's methods.
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * // Basic usage
35
+ * await browserContext.addInitScript(PageInspector.INIT_SCRIPT);
36
+ * const inspector = new PageInspector();
37
+ *
38
+ * const page = await browserContext.newPage();
39
+ * await page.goto("https://google.com");
40
+ *
41
+ * // Find and attribute interactable elements
42
+ * await inspector.attributeInteractableElements(page);
43
+ *
44
+ * // Get information about interactable elements
45
+ * const elements = await inspector.getAttributedInteractableElements(page);
46
+ *
47
+ * // Add visual annotations to the page
48
+ * await inspector.annotateInteractableElements(page);
49
+ *
50
+ * // Clean up when done
51
+ * await inspector.removeDonobuAnnotations(page);
52
+ * await inspector.deattributeVisibleInteractableElements(page);
53
+ * ```
54
+ *
55
+ * @remarks
56
+ * This class uses custom HTML attributes (`data-donobu-interactable` by default)
57
+ * to mark elements, and creates a shadow DOM container for annotations to avoid
58
+ * style conflicts with the target page.
59
+ *
60
+ * All methods will throw a {@link PageClosedException} if the page is closed
61
+ * during operation.
62
+ */
63
+ class PageInspector {
64
+ constructor(interactableElementAttribute = 'data-donobu-interactable', interactableAnnotationAttribute = 'data-donobu-annotation') {
65
+ this.interactableElementAttribute = interactableElementAttribute;
66
+ this.interactableAnnotationAttribute = interactableAnnotationAttribute;
67
+ }
68
+ /**
69
+ * Assigns a globally unique attribute to all visible and interactable elements in the page.
70
+ *
71
+ * This method performs the following steps:
72
+ * 1. Removes any pre-existing interactable element attributes from the page
73
+ * 2. Assigns sequential numeric values as attributes to interactable elements in the main frame
74
+ * 3. Processes child frames that are visible in the viewport and assigns attributes to their interactable elements
75
+ *
76
+ * The method identifies "interactable" elements based on tag names, ARIA roles, CSS classes, and other heuristics.
77
+ * Only elements that are:
78
+ * - Visible (non-zero dimensions and not hidden via CSS)
79
+ * - More than 50% in the viewport
80
+ * - Not disabled or inert
81
+ * - Actually reachable at their coordinates (topmost in z-index)
82
+ * will receive the attribute.
83
+ *
84
+ * @param page - The Playwright Page object to process
85
+ * @throws {PageClosedException} If the page is closed during processing
86
+ * @returns {Promise<void>} A promise that resolves when all elements have been attributed
87
+ */
88
+ async attributeInteractableElements(page) {
89
+ try {
90
+ // Remove any preexisting attributes
91
+ await this.deattributeInteractableElements(page);
92
+ // Get viewport dimensions and scroll position properly
93
+ const viewportInfo = await page.evaluate(() => {
94
+ return {
95
+ viewportWidth: window.innerWidth,
96
+ viewportHeight: window.innerHeight,
97
+ scrollX: window.scrollX || window.pageXOffset,
98
+ scrollY: window.scrollY || window.pageYOffset,
99
+ };
100
+ });
101
+ // 1) Attribute elements in the main page
102
+ let annotationOffset = await page.evaluate(PageInspector.attributeElementsInContext, [0, this.interactableElementAttribute]);
103
+ // 2) Check child frames, attributing elements if the frame is (partially) in view
104
+ const frames = page
105
+ .frames()
106
+ .filter((frame) => PageInspector.frameFilter(frame) && frame !== page.mainFrame());
107
+ for (const frame of frames) {
108
+ const elementHandle = await frame.frameElement();
109
+ if (!elementHandle) {
110
+ continue;
111
+ }
112
+ const boundingBox = await elementHandle.boundingBox();
113
+ if (!boundingBox) {
114
+ continue;
115
+ }
116
+ // boundingBox coordinates are already in viewport space, so we need to account for scroll
117
+ const isInViewport = boundingBox.x + boundingBox.width > 0 &&
118
+ boundingBox.x < viewportInfo.viewportWidth &&
119
+ boundingBox.y + boundingBox.height > 0 &&
120
+ boundingBox.y < viewportInfo.viewportHeight;
121
+ if (isInViewport) {
122
+ annotationOffset = await frame.evaluate(PageInspector.attributeElementsInContext, [annotationOffset, this.interactableElementAttribute]);
123
+ }
124
+ }
125
+ }
126
+ catch (error) {
127
+ if (PlaywrightUtils_1.PlaywrightUtils.isPageClosedError(error)) {
128
+ throw new PageClosedException_1.PageClosedException();
129
+ }
130
+ else {
131
+ throw error;
132
+ }
133
+ }
134
+ }
135
+ /**
136
+ * Retrieves all elements that have been previously attributed with the interactable element attribute.
137
+ *
138
+ * This method:
139
+ * 1. Searches all frames in the page (including the main frame and child frames)
140
+ * 2. Collects elements with the {@link interactableElementAttribute} attribute
141
+ * 3. Creates an {@link InteractableElement} object for each attributed element
142
+ *
143
+ * For each interactable element, it extracts:
144
+ * - The attribute value (serving as a unique identifier)
145
+ * - A simplified HTML snippet representation of the element
146
+ * * For 'select' elements, the complete HTML (including options) is preserved
147
+ * * For all other elements, only the opening tag without children is captured
148
+ *
149
+ * Note: This method only finds elements that have been previously attributed using
150
+ * the {@link attributeInteractableElements} method.
151
+ *
152
+ * @param page - The Playwright Page object to process
153
+ * @returns {Promise<InteractableElement[]>} A promise that resolves to an array of
154
+ * interactable elements with their attribute values and HTML snippets
155
+ * @throws {PageClosedException} If the page is closed during processing
156
+ *
157
+ * @example
158
+ * const inspector = new PageInspector();
159
+ * await inspector.attributeInteractableElements(page);
160
+ * const elements = await inspector.getAttributedInteractableElements(page);
161
+ * // elements = [{ donobuAttributeValue: "0", htmlSnippet: "<button id=\"submit\">"}]
162
+ */
163
+ async getAttributedInteractableElements(page) {
164
+ try {
165
+ const interactableElements = [];
166
+ const frames = page
167
+ .frames()
168
+ .filter((frame) => PageInspector.frameFilter(frame));
169
+ for (const frame of frames) {
170
+ const attributeMap = await frame.evaluate((interactableAttribute) => {
171
+ const getOuterHTMLWithoutChildrenExceptForSelectElements = (element) => {
172
+ if (element.tagName.toLowerCase() === 'select') {
173
+ return element.outerHTML;
174
+ }
175
+ else {
176
+ const tempElement = document.createElement('div');
177
+ tempElement.appendChild(element.cloneNode(false));
178
+ return tempElement.innerHTML;
179
+ }
180
+ };
181
+ const attributeToHtmlMap = {};
182
+ const elements = document.querySelectorAll(`[${interactableAttribute}]`);
183
+ elements.forEach((element) => {
184
+ const attributeValue = element.getAttribute(interactableAttribute);
185
+ const outerHtml = getOuterHTMLWithoutChildrenExceptForSelectElements(element);
186
+ if (attributeValue) {
187
+ attributeToHtmlMap[attributeValue] = outerHtml;
188
+ }
189
+ });
190
+ return attributeToHtmlMap;
191
+ }, this.interactableElementAttribute);
192
+ Object.entries(attributeMap).forEach(([donobuAttributeValue, htmlSnippet]) => {
193
+ interactableElements.push({
194
+ donobuAttributeValue,
195
+ htmlSnippet,
196
+ });
197
+ });
198
+ }
199
+ return interactableElements;
200
+ }
201
+ catch (error) {
202
+ if (PlaywrightUtils_1.PlaywrightUtils.isPageClosedError(error)) {
203
+ throw new PageClosedException_1.PageClosedException();
204
+ }
205
+ else {
206
+ throw error;
207
+ }
208
+ }
209
+ }
210
+ /**
211
+ * Visually annotates all interactable elements with numbered indicators on the page.
212
+ *
213
+ * This method:
214
+ * 1. Processes all accessible frames in the page
215
+ * 2. Creates (or reuses) a shadow DOM container to isolate annotation styling
216
+ * 3. Places circular numbered indicators over each element that has the
217
+ * {@link interactableElementAttribute} attribute
218
+ *
219
+ * The annotations:
220
+ * - Are positioned at the center of each interactable element
221
+ * - Have the same numeric value as the element's attribute
222
+ * - Are styled as black circles with red borders and white text
223
+ * - Are placed in a shadow DOM to avoid style conflicts with the page
224
+ * - Have the {@link interactableAnnotationAttribute} for identification
225
+ * - Are non-interactive (pointer-events: none)
226
+ *
227
+ * Note: This method requires elements to be previously attributed using the
228
+ * {@link attributeInteractableElements} method to find the elements to annotate.
229
+ *
230
+ * @param page - The Playwright Page object to process
231
+ * @returns {Promise<void>} A promise that resolves when all elements have been annotated
232
+ * @throws {PageClosedException} If the page is closed during processing
233
+ *
234
+ * @example
235
+ * const inspector = new PageInspector();
236
+ * await inspector.attributeInteractableElements(page);
237
+ * await inspector.annotateInteractableElements(page);
238
+ * // Visible numbered annotations now appear over all interactable elements
239
+ */
240
+ async annotateInteractableElements(page) {
241
+ try {
242
+ // Filter frames as needed
243
+ const frames = page
244
+ .frames()
245
+ .filter((frame) => PageInspector.frameFilter(frame));
246
+ for (const frame of frames) {
247
+ await frame.evaluate(([interactableAttr, annotationAttr]) => {
248
+ // 1) Ensure we have a shadow container in the main document
249
+ let container = document.getElementById('annotation-shadow-container');
250
+ if (!container) {
251
+ container = document.createElement('div');
252
+ container.id = 'annotation-shadow-container';
253
+ // Position container so child elements can be absolutely placed
254
+ Object.assign(container.style, {
255
+ position: 'fixed', // anchor to viewport
256
+ inset: '0', // stretch across it
257
+ pointerEvents: 'none', // Let clicks pass through
258
+ zIndex: '2147483647', // win every z-index fight
259
+ });
260
+ // Check if document.body exists before trying to append.
261
+ if (document.body) {
262
+ document.body.appendChild(container);
263
+ }
264
+ else if (document.documentElement) {
265
+ // Fall back to document.documentElement if body does not exist.
266
+ document.documentElement.appendChild(container);
267
+ }
268
+ else {
269
+ // If neither exists, we can't proceed with annotations in this frame.
270
+ console.warn(`Cannot create annotation container for ${window.location.href} since the document structure is incomplete`);
271
+ return;
272
+ }
273
+ // Attach a shadow root
274
+ const shadowRoot = container.attachShadow({ mode: 'open' });
275
+ // Add a <style> element inside the shadow root to reset and define annotation styles
276
+ const style = document.createElement('style');
277
+ style.textContent = `
278
+ :host {
279
+ all: initial; /* Reset styles in shadow root */
280
+ }
281
+ .annotation {
282
+ position: absolute;
283
+ z-index: 2147483647;
284
+ background-color: black;
285
+ color: white;
286
+ width: 40px;
287
+ height: 40px;
288
+ border-radius: 50%;
289
+ display: flex;
290
+ align-items: center;
291
+ justify-content: center;
292
+ font-size: 14px;
293
+ font-weight: bold;
294
+ line-height: 20px;
295
+ text-align: center;
296
+ box-shadow: 0px 2px 4px rgba(0,0,0,0.2);
297
+ border: 4px solid #FF4136;
298
+ pointer-events: none;
299
+ }
300
+ `;
301
+ shadowRoot.appendChild(style);
302
+ }
303
+ // Retrieve the shadow root to place annotation elements
304
+ const containerEl = document.getElementById('annotation-shadow-container');
305
+ if (!containerEl?.shadowRoot) {
306
+ return;
307
+ }
308
+ const shadowRoot = containerEl.shadowRoot;
309
+ // 2) Factory to create a new annotation inside the shadow root
310
+ const createAnnotation = (value) => {
311
+ const annotation = document.createElement('div');
312
+ annotation.classList.add('annotation');
313
+ annotation.dataset[annotationAttr] = '1';
314
+ annotation.textContent = value;
315
+ return annotation;
316
+ };
317
+ // 3) Position annotation relative to an element
318
+ const positionAnnotation = (annotation, element) => {
319
+ const rect = element.getBoundingClientRect();
320
+ // Center the annotation on the element, adjusting for its size
321
+ const x = rect.left + rect.width / 2 - 20 + window.scrollX;
322
+ const y = rect.top + rect.height / 2 - 20 + window.scrollY;
323
+ annotation.style.left = `${x}px`;
324
+ annotation.style.top = `${y}px`;
325
+ };
326
+ // 4) Traverse DOM (including any nested shadow roots) to find interactable elements
327
+ const processNode = (root) => {
328
+ // Find elements with the interactable attribute
329
+ const elements = root.querySelectorAll(`[${interactableAttr}]`);
330
+ elements.forEach((element) => {
331
+ const value = element.getAttribute(interactableAttr);
332
+ if (value) {
333
+ const annotation = createAnnotation(value);
334
+ shadowRoot.appendChild(annotation);
335
+ positionAnnotation(annotation, element);
336
+ }
337
+ });
338
+ // Recursively process any child shadow roots
339
+ root.querySelectorAll('*').forEach((el) => {
340
+ if (el.shadowRoot) {
341
+ processNode(el.shadowRoot);
342
+ }
343
+ });
344
+ };
345
+ // Start processing from the (frame) document root
346
+ processNode(document);
347
+ }, [
348
+ this.interactableElementAttribute,
349
+ PageInspector.convertToJsAttribute(this.interactableAnnotationAttribute),
350
+ ]);
351
+ }
352
+ }
353
+ catch (error) {
354
+ if (PlaywrightUtils_1.PlaywrightUtils.isPageClosedError(error)) {
355
+ throw new PageClosedException_1.PageClosedException();
356
+ }
357
+ else {
358
+ throw error;
359
+ }
360
+ }
361
+ }
362
+ /**
363
+ * Removes all visual annotations from the page that were created by
364
+ * the {@link annotateInteractableElements} method.
365
+ *
366
+ * This method:
367
+ * 1. Processes all accessible frames in the page
368
+ * 2. Finds and removes the shadow DOM container with ID 'annotation-shadow-container'
369
+ * that contains all the annotations
370
+ *
371
+ * This effectively removes all numbered indicators that were previously placed
372
+ * over interactable elements, leaving the page in its original visual state.
373
+ * Note that this only removes the visual annotations, not the
374
+ * {@link interactableElementAttribute} attributes on the elements themselves.
375
+ *
376
+ * @param page - The Playwright Page object to process
377
+ * @returns {Promise<void>} A promise that resolves when all annotations have been removed
378
+ * @throws {PageClosedException} If the page is closed during processing
379
+ *
380
+ * @example
381
+ * const inspector = new PageInspector();
382
+ * await inspector.attributeInteractableElements(page);
383
+ * await inspector.annotateInteractableElements(page);
384
+ * // ... do some operations with the annotations visible ...
385
+ * await inspector.removeDonobuAnnotations(page);
386
+ * // All visual annotations are now removed from the page
387
+ */
388
+ async removeDonobuAnnotations(page) {
389
+ try {
390
+ const frames = page
391
+ .frames()
392
+ .filter((frame) => PageInspector.frameFilter(frame));
393
+ for (const frame of frames) {
394
+ await frame.evaluate(() => {
395
+ const containerId = 'annotation-shadow-container';
396
+ const container = document.getElementById(containerId);
397
+ if (container) {
398
+ container.remove();
399
+ }
400
+ });
401
+ }
402
+ }
403
+ catch (error) {
404
+ if (PlaywrightUtils_1.PlaywrightUtils.isPageClosedError(error)) {
405
+ throw new PageClosedException_1.PageClosedException();
406
+ }
407
+ throw error;
408
+ }
409
+ }
410
+ /**
411
+ * Removes all interactable element attributes that were previously added to elements in the page.
412
+ *
413
+ * This method:
414
+ * 1. Processes all accessible frames in the page
415
+ * 2. Finds all elements with the {@link interactableElementAttribute} attribute
416
+ * 3. Removes this attribute from each element
417
+ *
418
+ * This effectively undoes the changes made by the {@link attributeInteractableElements} method,
419
+ * returning the page's DOM to its original state without the custom attributes.
420
+ * Note that this does not affect any visual annotations - to remove those, use
421
+ * the {@link removeDonobuAnnotations} method separately.
422
+ *
423
+ * This method is automatically called at the beginning of {@link attributeInteractableElements}
424
+ * to ensure a clean state before adding new attributes, but can also be called
425
+ * independently to clean up the DOM.
426
+ *
427
+ * @param page - The Playwright Page object to process
428
+ * @returns {Promise<void>} A promise that resolves when all attributes have been removed
429
+ * @throws {PageClosedException} If the page is closed during processing
430
+ *
431
+ * @example
432
+ * const inspector = new PageInspector();
433
+ * await inspector.attributeInteractableElements(page);
434
+ * // ... perform operations with attributed elements ...
435
+ * await inspector.deattributeInteractableElements(page);
436
+ * // All interactable element attributes are now removed from the page
437
+ */
438
+ async deattributeInteractableElements(page) {
439
+ try {
440
+ const frames = page
441
+ .frames()
442
+ .filter((frame) => PageInspector.frameFilter(frame));
443
+ for (const frame of frames) {
444
+ await frame.evaluate((attr) => {
445
+ document.querySelectorAll(`[${attr}]`).forEach((element) => {
446
+ element.removeAttribute(attr);
447
+ });
448
+ }, this.interactableElementAttribute);
449
+ }
450
+ }
451
+ catch (error) {
452
+ if (PlaywrightUtils_1.PlaywrightUtils.isPageClosedError(error)) {
453
+ throw new PageClosedException_1.PageClosedException();
454
+ }
455
+ else {
456
+ throw error;
457
+ }
458
+ }
459
+ }
460
+ /**
461
+ * Converts an HTML attribute to a JavaScript attribute. For example,
462
+ * "data-foo-bar" is turned into "fooBar". Notice the dropping of the "data-"
463
+ * prefix, and the conversion from kebab-case to camelCase.
464
+ */
465
+ static convertToJsAttribute(htmlAttribute) {
466
+ if (htmlAttribute.startsWith('data-')) {
467
+ htmlAttribute = htmlAttribute.substring(5);
468
+ }
469
+ const parts = htmlAttribute.split('-');
470
+ const jsAttribute = parts[0] +
471
+ parts
472
+ .slice(1)
473
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
474
+ .join('');
475
+ return jsAttribute;
476
+ }
477
+ /**
478
+ * An internal method that is injected into page/frame contexts to find and attribute interactable elements.
479
+ *
480
+ * This method:
481
+ * 1. Identifies potentially interactable elements using a comprehensive selector
482
+ * 2. Filters elements based on visibility, position in viewport, and interactability
483
+ * 3. Assigns unique sequential numeric values to the interactable attribute
484
+ *
485
+ * The method uses several criteria to determine if an element is truly interactable:
486
+ * - Element must be visible (non-zero dimensions, not hidden via CSS)
487
+ * - Element must have at least 50% of its area within the viewport
488
+ * - Element must not be disabled, inert, or have pointer-events:none
489
+ * - Element must be the topmost element at its coordinates (using point sampling)
490
+ *
491
+ * Special handling is provided for label elements, which will attribute their
492
+ * associated form controls as well.
493
+ *
494
+ * This method can process both standard DOM elements and elements within shadow roots,
495
+ * ensuring thorough coverage of modern web applications.
496
+ *
497
+ * @param arg - A tuple containing [offset: number, interactableAttribute: string]
498
+ * where offset is the starting value for sequential numbering and
499
+ * interactableAttribute is the attribute name to assign
500
+ * @returns The updated offset after assigning attributes (for sequential numbering across frames)
501
+ * @private
502
+ *
503
+ * @remarks
504
+ * This method is designed to be injected into the page context using page.evaluate()
505
+ * and should not be called directly from Node.js code.
506
+ */
507
+ static attributeElementsInContext(arg) {
508
+ let offset = arg[0];
509
+ const interactableAttribute = arg[1];
510
+ // --- Utility Functions ---
511
+ function isElementVisible(rect, style) {
512
+ return (rect.width > 0 &&
513
+ rect.height > 0 &&
514
+ style.display !== 'none' &&
515
+ style.visibility !== 'hidden');
516
+ }
517
+ function isElementMoreThanHalfInViewport(rect) {
518
+ const viewportWidth = window.innerWidth || document.documentElement.clientWidth;
519
+ const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
520
+ const visibleWidth = Math.min(rect.right, viewportWidth) - Math.max(rect.left, 0);
521
+ const visibleHeight = Math.min(rect.bottom, viewportHeight) - Math.max(rect.top, 0);
522
+ const visibleArea = Math.max(0, visibleWidth) * Math.max(0, visibleHeight);
523
+ const elementArea = rect.width * rect.height;
524
+ return visibleArea >= elementArea / 2;
525
+ }
526
+ function isElementEnabled(element, style) {
527
+ // Check standard disabled attribute (for form controls like button, input, etc.)
528
+ if (element.hasAttribute('disabled')) {
529
+ return false;
530
+ }
531
+ // Check for ARIA attributes that indicate non-interactivity
532
+ if (element.getAttribute('aria-disabled') === 'true' ||
533
+ element.getAttribute('aria-hidden') === 'true') {
534
+ return false;
535
+ }
536
+ // Check for pointer-events: none which prevents interactions
537
+ if (style.pointerEvents === 'none') {
538
+ return false;
539
+ }
540
+ // Check for ARIA attributes indicating disabled state
541
+ if (element.getAttribute('aria-disabled') === 'true') {
542
+ return false;
543
+ }
544
+ // Check for inert attribute which makes elements non-interactive
545
+ if (element.hasAttribute('inert')) {
546
+ return false;
547
+ }
548
+ // If the element is in a form and the fieldset is disabled, it might be disabled as well
549
+ let parent = element.parentElement;
550
+ while (parent) {
551
+ if (parent.tagName.toLowerCase() === 'fieldset' &&
552
+ parent.hasAttribute('disabled') &&
553
+ element.tagName.toLowerCase() !== 'legend') {
554
+ return false;
555
+ }
556
+ parent = parent.parentElement;
557
+ }
558
+ return true;
559
+ }
560
+ /**
561
+ * Generate a few test points on the element's bounding box. We only need
562
+ * a small offset (1px) from each corner, plus the center.
563
+ */
564
+ function getPointsToCheck(rect) {
565
+ const cornerOffset = 1;
566
+ return [
567
+ { x: rect.left + cornerOffset, y: rect.top + cornerOffset },
568
+ { x: rect.right - cornerOffset, y: rect.top + cornerOffset },
569
+ { x: rect.left + cornerOffset, y: rect.bottom - cornerOffset },
570
+ { x: rect.right - cornerOffset, y: rect.bottom - cornerOffset },
571
+ { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 },
572
+ ];
573
+ }
574
+ /**
575
+ * Like `elementFromPoint` but continues walking shadow roots if found.
576
+ */
577
+ function getDeepElementFromPoint(x, y) {
578
+ let el = document.elementFromPoint(x, y);
579
+ while (el && el.shadowRoot) {
580
+ const shadowEl = el.shadowRoot.elementFromPoint(x, y);
581
+ if (!shadowEl || shadowEl === el)
582
+ break;
583
+ el = shadowEl;
584
+ }
585
+ return el;
586
+ }
587
+ function getAllInteractableElements(root) {
588
+ const selector = [
589
+ // ----- STANDARD HTML INTERACTIVE ELEMENTS -----
590
+ // Basic form controls and interactive elements
591
+ 'button',
592
+ 'button svg', // SVG inside buttons are also clickable
593
+ 'input',
594
+ 'textarea',
595
+ 'a',
596
+ 'select',
597
+ 'summary', // Disclosure (details/summary) elements
598
+ 'details',
599
+ 'audio[controls]', // Media controls
600
+ 'video[controls]',
601
+ // ----- ARIA ROLE-BASED INTERACTIVE ELEMENTS -----
602
+ // Elements with explicit interactive ARIA roles
603
+ '[role="button"]',
604
+ '[role="option"]',
605
+ '[role="link"]',
606
+ '[role="checkbox"]',
607
+ '[role="radio"]',
608
+ '[role="tab"]',
609
+ '[role="menuitem"]',
610
+ '[role="menuitemcheckbox"]',
611
+ '[role="menuitemradio"]',
612
+ '[role="combobox"]',
613
+ '[role="listbox"]',
614
+ '[role="searchbox"]',
615
+ '[role="spinbutton"]',
616
+ '[role="slider"]',
617
+ '[role="switch"]',
618
+ '[role="menu"]',
619
+ '[role="menubar"]',
620
+ '[role="treeitem"]',
621
+ // ----- INTERACTIVE ARIA ATTRIBUTES -----
622
+ // Elements with popup behavior
623
+ '[aria-haspopup]',
624
+ '[aria-controls]',
625
+ '[aria-expanded]', // Elements that can expand/collapse
626
+ '[aria-pressed]', // Toggle buttons
627
+ '[aria-selected]', // Selectable items
628
+ // ----- EDITABLE AND FOCUSABLE ELEMENTS -----
629
+ // Elements that can receive input
630
+ '[contenteditable="true"]',
631
+ // Elements that can be dragged
632
+ '[draggable="true"]',
633
+ // Elements with explicit focus capability
634
+ '[tabindex]:not([tabindex="-1"])',
635
+ // ----- CSS FRAMEWORK-SPECIFIC CLASSES -----
636
+ // Bootstrap & similar frameworks
637
+ '.btn', // Standard button class
638
+ '.dropdown-toggle', // Dropdown triggers
639
+ '.nav-link', // Navigation links
640
+ '.page-link', // Pagination links
641
+ '.card-header[data-toggle="collapse"]', // Collapsible headers
642
+ '.accordion-button', // Accordion toggles
643
+ '.close', // Close buttons
644
+ '.modal-close', // Modal close buttons
645
+ // Material Design & Angular Material
646
+ '.mdc-button',
647
+ '.mat-button',
648
+ '.mat-icon-button',
649
+ '.mat-fab',
650
+ '.mat-mini-fab',
651
+ '.mat-menu-item',
652
+ '.mat-tab-label',
653
+ // Foundation
654
+ '.button',
655
+ '.menu-item',
656
+ '.accordion-title',
657
+ // Tailwind UI & Headless UI components
658
+ '.tw-button',
659
+ '[x-on\\:click]', // Alpine.js click handlers
660
+ // Vue-based frameworks
661
+ '.v-btn', // Vuetify
662
+ '.el-button', // Element UI
663
+ // React-based frameworks
664
+ '.ant-btn', // Ant Design
665
+ '.chakra-button', // Chakra UI
666
+ '.mui-button', // Material-UI
667
+ // ----- CUSTOM INTERACTIVE PATTERNS -----
668
+ // Common custom interactive classes
669
+ '.clickable',
670
+ '.selectable',
671
+ '.interactive',
672
+ '.toggle',
673
+ '.expandable',
674
+ '.switch',
675
+ '.slider',
676
+ // Common dropdown/select libraries
677
+ '.select2-selection',
678
+ '.chosen-single',
679
+ '.vs__dropdown-toggle', // Vue Select
680
+ // Tabs and accordion components
681
+ '.tab',
682
+ '.tab-header',
683
+ '.tab-title',
684
+ '.accordion-header',
685
+ // Mobile-friendly interactive elements
686
+ '.swipe-item',
687
+ '.touch-target',
688
+ // ----- COMMON COMPONENT PATTERNS -----
689
+ // Cards and tiles that are often clickable
690
+ '.card[onclick]',
691
+ '.tile[onclick]',
692
+ '.card a', // Links inside cards
693
+ // Social media & e-commerce patterns
694
+ '.share-button',
695
+ '.like-button',
696
+ '.add-to-cart',
697
+ '.product-card',
698
+ // Notification and alert controls
699
+ '.alert .close',
700
+ '.toast .close',
701
+ '.notification-action',
702
+ ].join(', ');
703
+ let elements = Array.from(root.querySelectorAll(selector));
704
+ // Dive into shadow roots
705
+ root.querySelectorAll('*').forEach((el) => {
706
+ if (el.shadowRoot) {
707
+ // Recurse
708
+ elements = elements.concat(getAllInteractableElements(el.shadowRoot));
709
+ }
710
+ });
711
+ // Remove duplicates
712
+ return Array.from(new Set(elements));
713
+ }
714
+ // 1) Gather candidate elements
715
+ const interactableElements = getAllInteractableElements(document)
716
+ .concat(window.__donobu.getInteractiveElements())
717
+ .filter((el) => !el.id || (typeof el.id === 'string' && !el.id.startsWith('donobu-')));
718
+ // Use a Set to avoid duplicates
719
+ const uniqueElements = new Set(interactableElements);
720
+ // 2) Check each element for visibility + actual "interactability"
721
+ uniqueElements.forEach((element) => {
722
+ if (typeof element.getBoundingClientRect !== 'function') {
723
+ // Should be rare, but just in case
724
+ return;
725
+ }
726
+ const rect = element.getBoundingClientRect();
727
+ const style = window.getComputedStyle(element);
728
+ const visible = isElementVisible(rect, style) && isElementMoreThanHalfInViewport(rect);
729
+ // Check if the element is actually enabled/interactive
730
+ const enabled = isElementEnabled(element, style);
731
+ if (!visible || !enabled) {
732
+ return;
733
+ }
734
+ let annotated = false;
735
+ // 3) Test small set of points on the element to confirm it's truly topmost
736
+ for (const pt of getPointsToCheck(rect)) {
737
+ let elToCheck = getDeepElementFromPoint(pt.x, pt.y);
738
+ // Walk up the DOM tree from that point
739
+ while (elToCheck) {
740
+ if (elToCheck === element) {
741
+ // Found the actual element
742
+ element.setAttribute(interactableAttribute, offset.toString());
743
+ offset++;
744
+ annotated = true;
745
+ break;
746
+ }
747
+ else if (elToCheck.tagName?.toLowerCase() === 'label' &&
748
+ elToCheck.htmlFor) {
749
+ // If we found a label referencing an element, also mark that
750
+ const forId = elToCheck.htmlFor;
751
+ const associatedInput = document.getElementById(forId);
752
+ if (associatedInput) {
753
+ associatedInput.setAttribute(interactableAttribute, offset.toString());
754
+ offset++;
755
+ }
756
+ annotated = true;
757
+ break;
758
+ }
759
+ elToCheck = elToCheck.parentElement;
760
+ }
761
+ if (annotated) {
762
+ break;
763
+ }
764
+ }
765
+ });
766
+ return offset;
767
+ }
768
+ static frameFilter(frame) {
769
+ return (!frame.isDetached() &&
770
+ !frame.url().startsWith('about:') &&
771
+ !frame.url().startsWith('chrome:') &&
772
+ !frame.url().startsWith('edge:'));
773
+ }
774
+ }
775
+ exports.PageInspector = PageInspector;
776
+ /**
777
+ * A JavaScript code snippet intended to run as an initialization
778
+ * script for `DonobuFlow` flows. This script helps other scripts to know
779
+ * non-traditional interactive elements via calling the
780
+ * {@link window.__donobu.getInteractiveElements} function.
781
+ */
782
+ PageInspector.INIT_SCRIPT = MiscUtils_1.MiscUtils.getResourceFileAsString(path_1.default.join('interactive-elements-tracker.js'));
783
+ //# sourceMappingURL=PageInspector.js.map