shadow-claw 1.23.3 → 1.24.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 (286) hide show
  1. package/README.md +42 -5
  2. package/bin/assert-version-bump.mjs +60 -38
  3. package/bin/assert-version-bump.test.mjs +74 -11
  4. package/bin/cli.mjs +166 -0
  5. package/bin/cli.test.mjs +60 -0
  6. package/bin/commands/backup.mjs +70 -0
  7. package/bin/commands/clients.mjs +41 -0
  8. package/bin/commands/peer-id.mjs +76 -0
  9. package/bin/commands/peer-id.test.mjs +104 -0
  10. package/bin/commands/send.mjs +51 -0
  11. package/bin/commands/tasks.mjs +59 -0
  12. package/bin/commands/webrtc-listen.mjs +254 -0
  13. package/bin/prerender-dsd-shell/prerender-dsd-shell.test.mjs +46 -0
  14. package/bin/rolldown.config.test.mjs +401 -8
  15. package/bin/utils/control-client.mjs +243 -0
  16. package/bin/utils/control-client.test.mjs +83 -0
  17. package/bin/utils/ulid.mjs +45 -0
  18. package/bin/utils/webrtc-control-client.mjs +699 -0
  19. package/bin/utils/webrtc-control-client.test.mjs +318 -0
  20. package/dist/electron/main.cjs +1 -1
  21. package/dist/public/AGENTS.md +5 -3
  22. package/dist/public/README.md +42 -5
  23. package/dist/public/agent.worker.js +6 -6
  24. package/dist/public/{app-routes-B0ePT49v.js → app-routes-Bs-riIvr.js} +1 -1
  25. package/dist/public/backup-controller-C_s9in2t.js +1 -0
  26. package/dist/public/components/settings/shadow-claw-control-plane/shadow-claw-control-plane.css +1 -0
  27. package/dist/public/components/settings/shadow-claw-control-plane/shadow-claw-control-plane.html +1 -0
  28. package/dist/public/components/settings/shadow-claw-storage/shadow-claw-storage.html +1 -1
  29. package/dist/public/components/settings/shadow-claw-task-server/shadow-claw-task-server.css +1 -1
  30. package/dist/public/components/settings/shadow-claw-task-server/shadow-claw-task-server.html +1 -1
  31. package/dist/public/components/shadow-claw-files/shadow-claw-files.css +1 -1
  32. package/dist/public/components/shadow-claw-files/shadow-claw-files.html +1 -1
  33. package/dist/public/components/shadow-claw-settings/shadow-claw-settings.html +1 -1
  34. package/dist/public/config-CrHchneq.js +1 -0
  35. package/dist/public/{configurePeerJs-B7kNU8AQ.js → configurePeerJs-CxpZeDJJ.js} +1 -1
  36. package/dist/public/{connections-xd_66YVU.js → connections-DvbgdkaB.js} +1 -1
  37. package/dist/public/{custom-element-security-CZ92anB8.js → custom-element-security-NCqQ5lmC.js} +1 -1
  38. package/dist/public/docs/README.md +3 -1
  39. package/dist/public/docs/architecture/overview.md +12 -12
  40. package/dist/public/docs/architecture/storage.md +5 -2
  41. package/dist/public/docs/decisions/bundled-typescript-architecture.md +1 -1
  42. package/dist/public/docs/decisions/indexeddb-and-opfs-storage.md +6 -3
  43. package/dist/public/docs/decisions/native-web-components-and-signals.md +1 -1
  44. package/dist/public/docs/example/article/index.html +2 -2
  45. package/dist/public/docs/guides/configuring-messaging-channels.md +41 -6
  46. package/dist/public/docs/guides/server-development-configuration.md +24 -0
  47. package/dist/public/docs/publishing/index.html +19 -76
  48. package/dist/public/docs/skill-creator/index.html +2 -2
  49. package/dist/public/docs/subsystems/backup.md +56 -0
  50. package/dist/public/docs/subsystems/cli.md +124 -0
  51. package/dist/public/docs/subsystems/control-plane.md +158 -0
  52. package/dist/public/docs/subsystems/notifications.md +54 -2
  53. package/dist/public/docs/subsystems/reactive-ui.md +1 -0
  54. package/dist/public/downloadGroupFile-By0GR6eV.js +1 -0
  55. package/dist/public/e2e/README.md +5 -1
  56. package/dist/public/{e2e-bridge-DkS5xFGX.js → e2e-bridge-IGWsRl4i.js} +1 -1
  57. package/dist/public/file-viewer-D0eflgt6.js +1 -0
  58. package/dist/public/files/main/~/docs/publishing-to-github-pages.md +17 -82
  59. package/dist/public/getAllTasks-vpBlgGsc.js +1 -0
  60. package/dist/public/getGroupDir-P1h9wl6S.js +1 -0
  61. package/dist/public/{git-BkjrsRXX.js → git-7Vq_SJSp.js} +2 -2
  62. package/dist/public/{iframe-sanitizer-L6Jyu__Z.js → iframe-sanitizer-y2Z1pPwY.js} +1 -1
  63. package/dist/public/index.html +2 -2
  64. package/dist/public/index.js +1 -1
  65. package/dist/public/{initChatSplitResize-BslPXAXS.js → initChatSplitResize-CzV2E7Ul.js} +1 -1
  66. package/dist/public/initControlPlane-C9jpnWev.js +1 -0
  67. package/dist/public/llms.txt +1 -1
  68. package/dist/public/main/index.html +2 -2
  69. package/dist/public/main/memory/index.html +2 -2
  70. package/dist/public/{markdown-6MBrIo-S.js → markdown-BnpKxSxl.js} +1 -1
  71. package/dist/public/mcp-reconnect-9emsqGRe.js +1 -0
  72. package/dist/public/{memoryStorage-CjGseKI1.js → memoryStorage-C0KvLNUp.js} +1 -1
  73. package/dist/public/{orchestrator-B9KmIj8Q.js → orchestrator-3h9xxHUm.js} +676 -676
  74. package/dist/public/orchestrator-nJj59RqD.js +15 -0
  75. package/dist/public/pages/main/~/docs/publishing-to-github-pages.md +17 -82
  76. package/dist/public/{peerjs-Dv8JNm7v.js → peerjs-BP4laMXj.js} +1 -1
  77. package/dist/public/{push-client-Dqq06wbB.js → push-client-CrjEXK3U.js} +1 -1
  78. package/dist/public/service-worker/fetch-proxy.js +1 -1
  79. package/dist/public/service-worker/push-handler.js +1 -1
  80. package/dist/public/service-worker.js +1 -1
  81. package/dist/public/{shadow-claw-Bd1rfuVC.js → shadow-claw-CbwETBWf.js} +2 -2
  82. package/dist/public/{shadow-claw-accounts-DL2l3oM0.js → shadow-claw-accounts-B4sBTQEj.js} +3 -3
  83. package/dist/public/{shadow-claw-channels-BGXDsQ38.js → shadow-claw-channels-BDWG5Qa3.js} +1 -1
  84. package/dist/public/{shadow-claw-chat-NXg6zz_l.js → shadow-claw-chat-Crv0DTCY.js} +6 -6
  85. package/dist/public/shadow-claw-control-plane-CX1IGbh9.js +199 -0
  86. package/dist/public/{shadow-claw-conversations-C8eqGpP9.js → shadow-claw-conversations-_9qAaRXk.js} +1 -1
  87. package/dist/public/shadow-claw-dialog-BrOwAOdk.js +1 -0
  88. package/dist/public/shadow-claw-file-viewer-Blf6yGVD.js +577 -0
  89. package/dist/public/shadow-claw-files-CYySBDCl.js +840 -0
  90. package/dist/public/{shadow-claw-git-C0ntz7aX.js → shadow-claw-git-v8S0JjuR.js} +3 -3
  91. package/dist/public/{shadow-claw-integrations-DCXV2r69.js → shadow-claw-integrations-D7ufpwhX.js} +1 -1
  92. package/dist/public/{shadow-claw-llm-CudgFQsS.js → shadow-claw-llm-GWgoVfhI.js} +2 -2
  93. package/dist/public/{shadow-claw-mcp-remote-B8RkpX28.js → shadow-claw-mcp-remote-kY4LMFNN.js} +1 -1
  94. package/dist/public/{shadow-claw-networking-BLiRsrsK.js → shadow-claw-networking-qHbP95z9.js} +1 -1
  95. package/dist/public/{shadow-claw-notifications-CQhQcjtL.js → shadow-claw-notifications-YyHOK2Fr.js} +1 -1
  96. package/dist/public/{shadow-claw-page-header-NeRD0tKU.js → shadow-claw-page-header-DMKbkv3s.js} +1 -1
  97. package/dist/public/{shadow-claw-pages-DCHnFh6r.js → shadow-claw-pages-DFZHhzFZ.js} +3 -3
  98. package/dist/public/{shadow-claw-settings-VAfjKFQg.js → shadow-claw-settings-DhxrKIfA.js} +10 -3
  99. package/dist/public/shadow-claw-storage-BFynbP0j.js +219 -0
  100. package/dist/public/{shadow-claw-task-server-Dk33N_1G.js → shadow-claw-task-server-3BIeb5oZ.js} +25 -4
  101. package/dist/public/{shadow-claw-tasks-xA1VfmWN.js → shadow-claw-tasks-Caxc9atL.js} +4 -4
  102. package/dist/public/{shadow-claw-terminal-Du2r0ciq.js → shadow-claw-terminal-Beb5qF-U.js} +1 -1
  103. package/dist/public/{shadow-claw-tools-CZj4rq7l.js → shadow-claw-tools-BfJx3A9W.js} +2 -2
  104. package/dist/public/{shadow-claw-webvm-JYUkWICG.js → shadow-claw-webvm-BCS8ykeP.js} +1 -1
  105. package/dist/public/static-main/~/docs/publishing-to-github-pages.md +17 -82
  106. package/dist/public/static-main-manifest.json +1 -1
  107. package/dist/public/{syncWebMcpRegistration-DfpvASnh.js → syncWebMcpRegistration-B_M2fCjH.js} +1 -1
  108. package/dist/server.js +286 -189
  109. package/package.json +2 -1
  110. package/src/__mocks__/jszip.cjs +15 -5
  111. package/src/components/settings/shadow-claw-accounts/shadow-claw-accounts.test.ts +35 -0
  112. package/src/components/settings/shadow-claw-control-plane/shadow-claw-control-plane.css +117 -0
  113. package/src/components/settings/shadow-claw-control-plane/shadow-claw-control-plane.html +81 -0
  114. package/src/components/settings/shadow-claw-control-plane/shadow-claw-control-plane.test.ts +127 -0
  115. package/src/components/settings/shadow-claw-control-plane/shadow-claw-control-plane.ts +292 -0
  116. package/src/components/settings/shadow-claw-git/shadow-claw-git.test.ts +72 -0
  117. package/src/components/settings/shadow-claw-integrations/connection-test-auth.test.ts +20 -30
  118. package/src/components/settings/shadow-claw-integrations/shadow-claw-integrations.test.ts +116 -0
  119. package/src/components/settings/shadow-claw-llm/model-ranking.test.ts +143 -51
  120. package/src/components/settings/shadow-claw-llm/shadow-claw-llm.test.ts +307 -4
  121. package/src/components/settings/shadow-claw-llm/shadow-claw-llm.ts +8 -8
  122. package/src/components/settings/shadow-claw-mcp-remote/shadow-claw-mcp-remote.test.ts +31 -0
  123. package/src/components/settings/shadow-claw-peerjs/shadow-claw-peerjs.test.ts +186 -0
  124. package/src/components/settings/shadow-claw-storage/shadow-claw-storage.html +17 -0
  125. package/src/components/settings/shadow-claw-storage/shadow-claw-storage.test.ts +120 -0
  126. package/src/components/settings/shadow-claw-storage/shadow-claw-storage.ts +56 -0
  127. package/src/components/settings/shadow-claw-task-server/shadow-claw-task-server.css +23 -2
  128. package/src/components/settings/shadow-claw-task-server/shadow-claw-task-server.html +1 -1
  129. package/src/components/settings/shadow-claw-task-server/shadow-claw-task-server.test.ts +19 -0
  130. package/src/components/settings/shadow-claw-task-server/shadow-claw-task-server.ts +2 -1
  131. package/src/components/shadow-claw/utils/initChatSplitResize.test.ts +180 -13
  132. package/src/components/shadow-claw/utils/setupEffects.test.ts +39 -0
  133. package/src/components/shadow-claw-a2ui/catalog/basic/shared.test.ts +117 -0
  134. package/src/components/shadow-claw-a2ui/shadow-claw-a2ui.test.ts +1159 -1
  135. package/src/components/shadow-claw-chat/shadow-claw-chat.test.ts +1523 -19
  136. package/src/components/shadow-claw-chat/utils/escapeHtml.test.ts +13 -0
  137. package/src/components/shadow-claw-chat/utils/getPeerChatDisplayStatus.test.ts +20 -0
  138. package/src/components/shadow-claw-conversations/shadow-claw-conversations.test.ts +494 -0
  139. package/src/components/shadow-claw-dialog/shadow-claw-dialog.ts +13 -2
  140. package/src/components/shadow-claw-file-viewer/shadow-claw-file-viewer.test.ts +378 -0
  141. package/src/components/shadow-claw-file-viewer/shadow-claw-file-viewer.ts +11 -9
  142. package/src/components/shadow-claw-files/shadow-claw-files.css +41 -17
  143. package/src/components/shadow-claw-files/shadow-claw-files.html +35 -0
  144. package/src/components/shadow-claw-files/shadow-claw-files.test.ts +627 -1
  145. package/src/components/shadow-claw-files/shadow-claw-files.ts +170 -6
  146. package/src/components/shadow-claw-pages/utils/resolveWorkspaceLinkPath.test.ts +31 -0
  147. package/src/components/shadow-claw-pages/utils/resolveWorkspaceLinkPath.ts +2 -1
  148. package/src/components/shadow-claw-pages/utils/rewriteWorkspacePreviewHtml.test.ts +15 -0
  149. package/src/components/shadow-claw-pdf-viewer/utils/installGetOrInsertComputedPolyfill.test.ts +65 -0
  150. package/src/components/shadow-claw-settings/shadow-claw-settings.html +7 -0
  151. package/src/components/shadow-claw-settings/shadow-claw-settings.test.ts +221 -0
  152. package/src/components/shadow-claw-settings/shadow-claw-settings.ts +2 -0
  153. package/src/components/shadow-claw-tasks/shadow-claw-tasks.test.ts +407 -0
  154. package/src/components/shadow-claw-terminal/utils/consumeEscapeSequence.test.ts +58 -0
  155. package/src/components/shadow-claw-tools/shadow-claw-tools.test.ts +80 -0
  156. package/src/config/config.test.ts +9 -0
  157. package/src/config/config.ts +15 -0
  158. package/src/core/app-routes.test.ts +56 -0
  159. package/src/core/app-routes.ts +8 -1
  160. package/src/core/backup-controller.test.ts +101 -0
  161. package/src/core/backup-controller.ts +137 -0
  162. package/src/core/control-plane-client.test.ts +408 -0
  163. package/src/core/control-plane-client.ts +425 -0
  164. package/src/core/orchestrator/orchestrator.ts +4 -0
  165. package/src/core/orchestrator/utils/compactContext.test.ts +78 -0
  166. package/src/core/orchestrator/utils/operations/channel.test.ts +254 -9
  167. package/src/core/orchestrator/utils/operations/provider.test.ts +326 -34
  168. package/src/core/orchestrator/utils/operations/vm.test.ts +114 -2
  169. package/src/core/orchestrator/utils/syncProxyConfigToServiceWorker.test.ts +60 -0
  170. package/src/core/utils/initControlPlane.test.ts +276 -0
  171. package/src/core/utils/initControlPlane.ts +437 -0
  172. package/src/core/utils/initializeApp.ts +18 -0
  173. package/src/db/getSession.test.ts +13 -1
  174. package/src/db/openDatabase.test.ts +10 -1
  175. package/src/db/openDatabase.ts +3 -1
  176. package/src/server/app.test.ts +12 -0
  177. package/src/server/app.ts +18 -8
  178. package/src/server/client-registry.test.ts +250 -0
  179. package/src/server/client-registry.ts +477 -0
  180. package/src/server/config.ts +15 -0
  181. package/src/server/control-plane-types.ts +120 -0
  182. package/src/server/control-plane.test.ts +472 -0
  183. package/src/server/control-plane.ts +581 -0
  184. package/src/server/routes/backup.test.ts +263 -0
  185. package/src/server/routes/backup.ts +262 -0
  186. package/src/server/routes/integrations-email.test.ts +532 -0
  187. package/src/server/routes/llamafile.test.ts +172 -48
  188. package/src/server/routes/mesh-llm.test.ts +192 -0
  189. package/src/server/routes/ollama.test.ts +49 -0
  190. package/src/server/server-peer.test.ts +86 -0
  191. package/src/server/server-peer.ts +330 -0
  192. package/src/server/server.ts +35 -0
  193. package/src/server/services/llamafile-manager.test.ts +230 -6
  194. package/src/server/services/transformers-runtime.test.ts +186 -18
  195. package/src/server/webrtc.test.ts +21 -0
  196. package/src/server/webrtc.ts +72 -0
  197. package/src/service-worker/fetch-proxy.test.ts +64 -1
  198. package/src/service-worker/push-handler.ts +39 -0
  199. package/src/shell/vm.test.ts +744 -12
  200. package/src/storage/ensureMainGroupIndex.test.ts +153 -0
  201. package/src/storage/getGroupFile.test.ts +66 -0
  202. package/src/storage/memoryStorage.test.ts +82 -2
  203. package/src/storage/migrateLegacyOpfs.test.ts +327 -0
  204. package/src/storage/migrateLegacyOpfs.ts +117 -0
  205. package/src/storage/writeGroupFileBytes.test.ts +143 -0
  206. package/src/stores/chat-ui.test.ts +20 -0
  207. package/src/stores/orchestrator.test.ts +134 -0
  208. package/src/stores/toast.test.ts +50 -0
  209. package/src/stores/tools.test.ts +147 -10
  210. package/src/subsystems/channels/imessage.test.ts +59 -0
  211. package/src/subsystems/channels/peerjs.test.ts +500 -62
  212. package/src/subsystems/channels/peerjs.ts +71 -4
  213. package/src/subsystems/channels/telegram.test.ts +177 -0
  214. package/src/subsystems/email/catalog.test.ts +1 -0
  215. package/src/subsystems/email/connections.test.ts +39 -1
  216. package/src/subsystems/git/credentials.test.ts +160 -825
  217. package/src/subsystems/git/git.test.ts +463 -0
  218. package/src/subsystems/notifications/__mocks__/node-sqlite.cjs +12 -1
  219. package/src/subsystems/notifications/push-routes.test.ts +33 -0
  220. package/src/subsystems/notifications/push-routes.ts +23 -0
  221. package/src/subsystems/notifications/push-store.ts +1 -1
  222. package/src/subsystems/providers/builtin-ai-tasks.test.ts +74 -0
  223. package/src/subsystems/providers/litert-lm-provider.test.ts +212 -51
  224. package/src/subsystems/providers/model-registry.test.ts +115 -0
  225. package/src/subsystems/providers/providers.test.ts +94 -1
  226. package/src/subsystems/providers/transformers-js-provider.test.ts +279 -0
  227. package/src/subsystems/providers/utils/createModelCacheFetch.test.ts +2 -2
  228. package/src/subsystems/providers/utils/downloadModelToCache.test.ts +2 -2
  229. package/src/subsystems/providers/utils/loadModelStream.test.ts +2 -2
  230. package/src/subsystems/skills/activateSkill.test.ts +101 -0
  231. package/src/subsystems/skills/discoverSkills.test.ts +251 -0
  232. package/src/subsystems/tools/cron.test.ts +64 -0
  233. package/src/subsystems/tools/declarative.test.ts +255 -89
  234. package/src/testing/assets/v86.9pfs/libv86.mjs +63 -0
  235. package/src/testing/assets/v86.ext2/libv86.mjs +3 -0
  236. package/src/testing/assets_missing_v86/assets/v86.9pfs/libv86.mjs +1 -0
  237. package/src/testing/jest-setup.ts +328 -40
  238. package/src/testing/mock-v86.mjs +49 -0
  239. package/src/ui/a2ui/types.ts +4 -3
  240. package/src/ui/a2ui/utils/normaliseComponentsToMap.test.ts +102 -0
  241. package/src/ui/a2ui/utils/resolveChildIds.test.ts +63 -0
  242. package/src/ui/a2ui/utils/resolveDynamicNumber.test.ts +13 -1
  243. package/src/worker/tools/bash/utils/waitForVMReady.test.ts +40 -0
  244. package/src/worker/tools/email/email.test.ts +193 -8
  245. package/src/worker/tools/email/utils/asEmailAttachmentInputs.test.ts +47 -0
  246. package/src/worker/tools/git/git.test.ts +214 -3
  247. package/src/worker/tools/rooms/invite-to-room.test.ts +54 -0
  248. package/src/worker/tools/rooms/leave-room.test.ts +40 -0
  249. package/src/worker/tools/rooms/list-room-members.test.ts +75 -0
  250. package/src/worker/tools/tasks/tasks-utils.test.ts +22 -0
  251. package/src/worker/tools/ui/ask-user.test.ts +50 -0
  252. package/src/worker/tools/ui/clear-chat.test.ts +19 -0
  253. package/src/worker/tools/ui/get-current-time.test.ts +19 -0
  254. package/src/worker/tools/ui/javascript.test.ts +116 -0
  255. package/src/worker/tools/ui/list-components.test.ts +10 -0
  256. package/src/worker/tools/ui/list-tool-profiles.test.ts +42 -0
  257. package/src/worker/tools/ui/manage-tools.test.ts +34 -0
  258. package/src/worker/tools/ui/render-component.test.ts +346 -0
  259. package/src/worker/tools/ui/send-notification.test.ts +40 -0
  260. package/src/worker/tools/ui/utils/getAllowFullInternetAccess.test.ts +31 -0
  261. package/src/worker/tools/ui/utils/parseBooleanConfig.test.ts +25 -0
  262. package/src/worker/tools/workspace/attach-file.test.ts +84 -0
  263. package/src/worker/tools/workspace/copy-file.test.ts +69 -0
  264. package/src/worker/tools/workspace/create-directory.test.ts +40 -0
  265. package/src/worker/tools/workspace/delete-file.test.ts +73 -0
  266. package/src/worker/tools/workspace/diff-files.test.ts +94 -0
  267. package/src/worker/tools/workspace/list-files.test.ts +36 -0
  268. package/src/worker/tools/workspace/move-file.test.ts +66 -0
  269. package/src/worker/tools/workspace/open-file.test.ts +57 -0
  270. package/src/worker/tools/workspace/patch-file.test.ts +81 -0
  271. package/src/worker/tools/workspace/read-file.test.ts +116 -0
  272. package/src/worker/tools/workspace/send-file.test.ts +82 -0
  273. package/src/worker/tools/workspace/update-memory.test.ts +29 -0
  274. package/src/worker/tools/workspace/write-file.test.ts +28 -0
  275. package/src/worker/utils/rate-limit.test.ts +199 -0
  276. package/src/worker/utils/tool-state.test.ts +29 -0
  277. package/src/worker/utils/transformers-js-utils.test.ts +59 -0
  278. package/dist/public/config-AL77QAx4.js +0 -1
  279. package/dist/public/downloadGroupFile-BABv_1mJ.js +0 -1
  280. package/dist/public/file-viewer-CCSABMsE.js +0 -1
  281. package/dist/public/mcp-reconnect-DoicazQd.js +0 -1
  282. package/dist/public/orchestrator-4su7iyWj.js +0 -15
  283. package/dist/public/shadow-claw-dialog-ByyHgxM9.js +0 -1
  284. package/dist/public/shadow-claw-file-viewer-9Qkwc30T.js +0 -577
  285. package/dist/public/shadow-claw-files-aDyq6Hv7.js +0 -781
  286. package/dist/public/shadow-claw-storage-Cf31np81.js +0 -202
@@ -1 +0,0 @@
1
- var e=class extends HTMLElement{static get observedAttributes(){return[`dialog-class`,`dialog-aria-label`,`dialog-aria-labelledby`]}_dialog=null;attributeChangedCallback(){this.syncDialogAttributes()}connectedCallback(){this.ensureDialog()}close(e){this.ensureDialog(),this._dialog?.close(e)}get dialog(){return this.ensureDialog(),this._dialog}ensureDialog(){if(this._dialog){this.syncDialogAttributes();return}this.style.display=`contents`;let e=document.createElement(`dialog`);this._dialog=e,this.syncDialogAttributes();let t=this.querySelector(`:scope > template`);if(t instanceof HTMLTemplateElement){e.appendChild(t.content.cloneNode(!0)),this.appendChild(e);return}for(;this.firstChild;)e.appendChild(this.firstChild);this.appendChild(e)}get open(){return this._dialog?.open??!1}get returnValue(){return this._dialog?.returnValue??``}set returnValue(e){this._dialog&&(this._dialog.returnValue=e)}showModal(){this.ensureDialog(),this._dialog?.showModal()}syncDialogAttributes(){if(!this._dialog)return;let e=this.getAttribute(`dialog-class`)||``;this._dialog.className=e;let t=this.getAttribute(`dialog-aria-label`);t?this._dialog.setAttribute(`aria-label`,t):this._dialog.removeAttribute(`aria-label`);let n=this.getAttribute(`dialog-aria-labelledby`);n?this._dialog.setAttribute(`aria-labelledby`,n):this._dialog.removeAttribute(`aria-labelledby`)}};customElements.get(`shadow-claw-dialog`)||customElements.define(`shadow-claw-dialog`,e);export{e as ShadowClawDialog};
@@ -1,577 +0,0 @@
1
- import{r as e}from"./config-AL77QAx4.js";import{a as t,n,o as r,s as i,u as a}from"./app-routes-B0ePT49v.js";import{n as o}from"./txPromise-EBECky1b.js";import{t as s}from"./getConfig-D89uJgo5.js";import{d as c,f as l,i as u,l as d,n as f,r as p,s as m,u as h}from"./custom-element-security-CZ92anB8.js";import{bn as g,mn as _,sn as v,t as y}from"./orchestrator-B9KmIj8Q.js";import{r as b,t as x}from"./toast-D3gxhZpN.js";import{t as S}from"./shadow-claw-element-DIrv3P6A.js";import{t as C}from"./effect-BEsuusE8.js";import{n as w,r as T,t as E}from"./markdown-6MBrIo-S.js";import{t as D}from"./file-viewer-CCSABMsE.js";import{t as O}from"./config-value-oBfKgLT4.js";import"./shadow-claw-dialog-ByyHgxM9.js";import{a as k,c as A,i as j,n as M,o as N,r as P,s as F,t as I}from"./iframe-storage-proxy-B9Zt-vJ2.js";const L=new CSSStyleSheet;L.replaceSync(`*,
2
- *::before,
3
- *::after {
4
- box-sizing: border-box;
5
- scrollbar-color: var(--shadow-claw-border-color) transparent;
6
- scrollbar-width: thin;
7
- }
8
-
9
- :root {
10
- --shadow-claw-font-mono: "Fira Code", "Courier New", monospace;
11
- }
12
-
13
- pre {
14
- font-family: var(--shadow-claw-font-mono) !important;
15
- }
16
-
17
- /* Scrollbar — cross-browser thin style (Shadow DOM) */
18
- * {
19
- scrollbar-color: var(--shadow-claw-border-color) transparent;
20
- scrollbar-width: thin;
21
- }
22
-
23
- ::-webkit-scrollbar {
24
- height: 0.5rem;
25
- width: 0.5rem;
26
- }
27
-
28
- ::-webkit-scrollbar-track {
29
- background: transparent;
30
- }
31
-
32
- ::-webkit-scrollbar-thumb {
33
- background: var(--shadow-claw-border-color);
34
- border-radius: 0.25rem;
35
- }
36
-
37
- ::-webkit-scrollbar-thumb:hover {
38
- background: var(--shadow-claw-text-tertiary);
39
- }
40
-
41
- .hidden,
42
- [hidden] {
43
- display: none !important;
44
- }
45
-
46
- :host {
47
- display: contents;
48
- }
49
-
50
- .file-modal {
51
- background: transparent;
52
- border: none;
53
- margin: 0;
54
- max-height: unset;
55
- max-width: unset;
56
- padding: 0;
57
- }
58
-
59
- .file-modal[open] {
60
- align-items: flex-start;
61
- box-sizing: border-box;
62
- display: flex;
63
- inset: 0;
64
- justify-content: center;
65
- padding: 0.5rem;
66
- position: fixed;
67
- width: auto;
68
- z-index: 1000;
69
- }
70
-
71
- .file-modal::backdrop {
72
- background-color: rgba(0, 0, 0, 0.5);
73
- }
74
-
75
- .modal-content {
76
- background-color: var(--shadow-claw-bg-primary);
77
- border: 0.0625rem solid var(--shadow-claw-border-color);
78
- border-radius: var(--shadow-claw-radius-l);
79
- box-shadow: var(--shadow-claw-shadow-lg);
80
- display: flex;
81
- flex-direction: column;
82
- height: min(88dvh, 45rem);
83
- max-height: calc(100dvh - 1rem);
84
- max-width: 56rem;
85
- width: calc(100vw - 1rem);
86
- }
87
-
88
- .modal-content.modal-content--fullscreen {
89
- height: calc(100dvh - 1rem);
90
- max-height: calc(100dvh - 1rem);
91
- max-width: calc(100vw - 1rem);
92
- width: calc(100vw - 1rem);
93
- }
94
-
95
- .modal-header {
96
- align-items: center;
97
- border-bottom: 0.0625rem solid var(--shadow-claw-border-color);
98
- display: flex;
99
- gap: 0.5rem;
100
- justify-content: space-between;
101
- min-width: 0;
102
- padding: 0.625rem 0.75rem;
103
- }
104
-
105
- .modal-header-actions {
106
- align-items: center;
107
- display: flex;
108
- flex: none;
109
- gap: 0.5rem;
110
- }
111
-
112
- .modal-cancel-btn,
113
- .modal-save-btn,
114
- .modal-share-btn {
115
- background-color: transparent;
116
- border: 0.0625rem solid var(--shadow-claw-border-color);
117
- border-radius: var(--shadow-claw-radius-m);
118
- color: var(--shadow-claw-text-secondary);
119
- cursor: pointer;
120
- font-size: 0.75rem;
121
- font-weight: 600;
122
- min-height: 2rem;
123
- padding: 0.375rem 0.625rem;
124
- transition: all 0.15s;
125
- }
126
-
127
- .modal-share-btn:hover {
128
- border-color: var(--shadow-claw-text-primary);
129
- box-shadow: var(--shadow-claw-shadow-md);
130
- color: var(--shadow-claw-text-primary);
131
- }
132
-
133
- .modal-save-btn {
134
- background-color: var(--shadow-claw-text-primary);
135
- border-color: var(--shadow-claw-text-primary);
136
- color: var(--shadow-claw-bg-primary);
137
- }
138
-
139
- .modal-save-btn:hover {
140
- background-color: var(--shadow-claw-accent-primary);
141
- border-color: var(--shadow-claw-accent-primary);
142
- color: var(--shadow-claw-on-primary);
143
- }
144
-
145
- .modal-cancel-btn {
146
- border-color: var(--shadow-claw-border-color);
147
- color: var(--shadow-claw-text-secondary);
148
- }
149
-
150
- .modal-cancel-btn:hover {
151
- border-color: var(--shadow-claw-error, #ef4444);
152
- color: var(--shadow-claw-error, #ef4444);
153
- }
154
-
155
- .modal-title {
156
- color: var(--shadow-claw-text-primary);
157
- flex: 1;
158
- font-size: 1rem;
159
- font-weight: 600;
160
- margin: 0;
161
- overflow: hidden;
162
- text-overflow: ellipsis;
163
- white-space: nowrap;
164
- }
165
-
166
- /* Segmented view-mode group (Edit + Preview) */
167
- .modal-view-modes {
168
- border: 0.0625rem solid var(--shadow-claw-border-color);
169
- border-radius: var(--shadow-claw-radius-m);
170
- display: flex;
171
- flex: none;
172
- margin-right: 0.5rem;
173
- overflow: hidden;
174
- }
175
-
176
- .modal-view-modes .modal-edit-btn,
177
- .modal-view-modes .modal-preview-btn,
178
- .modal-view-modes .modal-fullscreen-btn {
179
- background-color: transparent;
180
- border: none;
181
- border-radius: 0;
182
- color: var(--shadow-claw-text-secondary);
183
- cursor: pointer;
184
- font-size: 0.75rem;
185
- font-weight: 600;
186
- min-height: 2rem;
187
- padding: 0.375rem 0.625rem;
188
- transition: all 0.15s;
189
- }
190
-
191
- .modal-view-modes .modal-edit-btn {
192
- border-right: 0.0625rem solid var(--shadow-claw-border-color);
193
- }
194
-
195
- .modal-view-modes .modal-preview-btn {
196
- border-right: 0.0625rem solid var(--shadow-claw-border-color);
197
- }
198
-
199
- /* When edit button is hidden (binary files), preview gets full rounding */
200
- .modal-view-modes .modal-edit-btn.hidden + .modal-preview-btn {
201
- border-radius: var(--shadow-claw-radius-m);
202
- }
203
-
204
- .modal-view-modes .modal-edit-btn:hover,
205
- .modal-view-modes .modal-preview-btn:hover,
206
- .modal-view-modes .modal-fullscreen-btn:hover {
207
- background-color: var(--shadow-claw-bg-secondary);
208
- color: var(--shadow-claw-text-primary);
209
- }
210
-
211
- .modal-view-modes .modal-edit-btn[aria-pressed="true"],
212
- .modal-view-modes .modal-preview-btn[aria-pressed="true"],
213
- .modal-view-modes .modal-fullscreen-btn[aria-pressed="true"] {
214
- background-color: var(--shadow-claw-bg-secondary);
215
- color: var(--shadow-claw-text-primary);
216
- }
217
-
218
- .modal-close-btn {
219
- background-color: var(--shadow-claw-bg-tertiary);
220
- border: 0.0625rem solid var(--shadow-claw-border-color);
221
- border-radius: var(--shadow-claw-radius-m);
222
- color: var(--shadow-claw-text-secondary);
223
- cursor: pointer;
224
- font-size: 1.25rem;
225
- line-height: 1;
226
- min-height: 2rem;
227
- padding: 0.375rem 0.625rem;
228
- }
229
-
230
- .modal-close-btn:hover {
231
- background-color: var(--shadow-claw-bg-secondary);
232
- border-color: var(--shadow-claw-accent-primary);
233
- color: var(--shadow-claw-text-primary);
234
- }
235
-
236
- @media (max-width: 640px) {
237
- .modal-cancel-btn .btn-label,
238
- .modal-save-btn .btn-label {
239
- display: none;
240
- }
241
- }
242
-
243
- @media (max-width: 480px) {
244
- .btn-label {
245
- display: none;
246
- }
247
-
248
- .modal-header-actions {
249
- gap: 0.25rem;
250
- }
251
- }
252
-
253
- .modal-body {
254
- display: flex;
255
- flex: 1;
256
- flex-direction: column;
257
- min-height: 0;
258
- overflow: hidden;
259
- padding: 0;
260
- position: relative;
261
- }
262
-
263
- .modal-body.modal-body--editing {
264
- overflow: hidden;
265
- }
266
-
267
- .file-content {
268
- color: var(--shadow-claw-text-primary);
269
- flex: 1;
270
- font-family: var(--shadow-claw-font-mono);
271
- font-size: 0.8125rem;
272
- min-height: 0;
273
- overflow-x: hidden;
274
- overflow-y: auto;
275
- padding: 0.75rem;
276
- white-space: pre-wrap;
277
- word-break: break-all;
278
- }
279
-
280
- .file-content--preview {
281
- font-family: var(--shadow-claw-font-sans);
282
- font-size: var(--shadow-claw-font-size-sm);
283
- line-height: 1.5;
284
- overflow-wrap: anywhere;
285
- padding: 0.75rem 1rem;
286
- user-select: text !important;
287
- white-space: normal;
288
- word-break: break-word;
289
- }
290
-
291
- .file-content--preview *,
292
- .file-content--preview pre,
293
- .file-content--preview code {
294
- user-select: text !important;
295
- }
296
-
297
- .file-content--preview > :first-child {
298
- margin-top: 0;
299
- }
300
-
301
- .file-content--preview > :last-child {
302
- margin-bottom: 0;
303
- }
304
-
305
- .file-content--preview pre {
306
- background: var(--shadow-claw-bg-secondary);
307
- border: 0.0625rem solid var(--shadow-claw-border-color);
308
- border-radius: var(--shadow-claw-radius-m);
309
- margin: 0.75rem 0;
310
- overflow-x: auto;
311
- padding: 0;
312
- }
313
-
314
- .file-content--preview pre code.hljs {
315
- background-color: transparent;
316
- display: block;
317
- font-size: 0.8125rem;
318
- line-height: 1.6;
319
- padding: 0.75rem;
320
- }
321
-
322
- .file-content--preview code:not(pre code) {
323
- background: var(--shadow-claw-bg-tertiary);
324
- border-radius: var(--shadow-claw-radius-s);
325
- font-size: 0.85em;
326
- padding: 0.125rem 0.3rem;
327
- }
328
-
329
- .file-content--preview img {
330
- height: auto;
331
- max-width: 100%;
332
- }
333
-
334
- .file-content--preview table {
335
- border-collapse: collapse;
336
- display: block;
337
- max-width: 100%;
338
- overflow-x: auto;
339
- }
340
-
341
- .file-content--preview th,
342
- .file-content--preview td {
343
- border: 0.0625rem solid var(--shadow-claw-border-color);
344
- padding: 0.375rem 0.75rem;
345
- text-align: left;
346
- }
347
-
348
- .file-content--preview th {
349
- background: var(--shadow-claw-bg-secondary);
350
- font-weight: 600;
351
- }
352
-
353
- .file-content--preview blockquote {
354
- border-left: 0.25rem solid var(--shadow-claw-border-color);
355
- color: var(--shadow-claw-text-secondary);
356
- margin: 0.75rem 0;
357
- padding: 0.25rem 1rem;
358
- }
359
-
360
- .file-content--preview a {
361
- color: var(--shadow-claw-accent-primary);
362
- }
363
-
364
- .file-content--preview h1,
365
- .file-content--preview h2 {
366
- border-bottom: 0.0625rem solid var(--shadow-claw-border-color);
367
- padding-bottom: 0.375rem;
368
- }
369
-
370
- .file-content--preview ul,
371
- .file-content--preview ol {
372
- padding-left: 1.5rem;
373
- }
374
-
375
- .file-content--iframe {
376
- height: 100%;
377
- margin: 0;
378
- overflow: auto;
379
- padding: 0;
380
- width: 100%;
381
- }
382
-
383
- .file-content-iframe {
384
- background-color: var(--shadow-claw-bg-primary);
385
- border: none;
386
- border-radius: var(--shadow-claw-radius-s);
387
- display: block;
388
- min-height: 100%;
389
- width: 100%;
390
- }
391
-
392
- .file-editor-container {
393
- background-color: var(--shadow-claw-hljs-background-color, rgb(40, 44, 52));
394
- display: none;
395
- flex: 1;
396
- margin: 0.75rem;
397
- min-height: 0;
398
- min-width: 0;
399
- position: relative;
400
- }
401
-
402
- .file-editor-container.active {
403
- display: block;
404
- }
405
-
406
- .file-editor {
407
- background-color: transparent;
408
- border: 0.0625rem solid var(--shadow-claw-border-color);
409
- border-radius: var(--shadow-claw-radius-s);
410
- caret-color: #abb2bf !important;
411
- color: transparent;
412
- font-family: var(--shadow-claw-font-mono), monospace !important;
413
- font-size: 1rem !important;
414
- font-variant-ligatures: none !important;
415
- height: 100%;
416
- left: 0;
417
- line-height: 1.5 !important;
418
- overflow: auto;
419
- padding: 0.625rem;
420
- position: absolute;
421
- resize: none;
422
- tab-size: 2;
423
- top: 0;
424
- white-space: pre;
425
- width: 100%;
426
- z-index: 1;
427
- }
428
-
429
- .file-editor-container pre.file-editor-overlay {
430
- border: 0.0625rem solid transparent !important;
431
- border-radius: var(--shadow-claw-radius-s);
432
- box-sizing: border-box !important;
433
- font-family: var(--shadow-claw-font-mono), monospace !important;
434
- font-size: 1rem !important;
435
- font-variant-ligatures: none !important;
436
- height: 100% !important;
437
- left: 0 !important;
438
- line-height: 1.5 !important;
439
- margin: 0 !important;
440
- overflow: hidden !important;
441
- padding: 0.625rem !important;
442
- pointer-events: none;
443
- position: absolute !important;
444
- tab-size: 2 !important;
445
- top: 0 !important;
446
- white-space: pre !important;
447
- width: 100% !important;
448
- z-index: 0;
449
- }
450
-
451
- .file-editor-container pre.file-editor-overlay code,
452
- .file-editor-container pre.file-editor-overlay code.hljs {
453
- display: block !important;
454
- font-family: inherit !important;
455
- font-size: inherit !important;
456
- font-variant-ligatures: none !important;
457
- /* hljs CSS injects overflow-x:auto on pre code.hljs via a constructed stylesheet.
458
- Inside the overlay (pointer-events:none) this would create an unclickable ghost scrollbar.
459
- Use overflow:visible so the code content extends into the pre's scroll area.
460
- The pre (overflow:hidden) handles visual clipping; JS sync scrolls the pre.
461
- visible never generates a scrollbar, so no ghost scrollbar appears. */
462
- overflow: visible !important;
463
- line-height: inherit !important;
464
- margin: 0 !important;
465
- padding: 0 !important;
466
- white-space: inherit !important;
467
- word-break: normal !important;
468
- word-wrap: normal !important;
469
- }
470
-
471
- .file-editor:focus {
472
- border-color: var(--shadow-claw-accent-primary);
473
- box-shadow: 0 0 0 0.125rem var(--shadow-claw-bg-tertiary);
474
- outline: none;
475
- }
476
-
477
- .code-line {
478
- border-left: 0.1875rem solid transparent;
479
- display: inline-block;
480
- padding-left: 0.5rem;
481
- transition:
482
- background-color 0.2s ease,
483
- border-color 0.2s ease;
484
- width: 100%;
485
- }
486
-
487
- .code-line.highlighted {
488
- background-color: var(--shadow-claw-bg-tertiary);
489
- border-left: 0.1875rem solid var(--shadow-claw-accent-primary);
490
- }
491
- `);const R=new DOMParser().parseFromString(`<template>
492
- <shadow-claw-dialog dialog-class="file-modal" dialog-aria-label="File viewer">
493
- <div class="modal-content">
494
- <div class="modal-header">
495
- <h3 class="modal-title">File:</h3>
496
- <div class="modal-header-actions">
497
- <button
498
- aria-label="Share file"
499
- class="modal-share-btn hidden"
500
- type="button"
501
- >
502
- ↗<span class="btn-label"> Share</span>
503
- </button>
504
- <div class="modal-view-modes">
505
- <button
506
- aria-pressed="false"
507
- aria-label="Edit file"
508
- class="modal-edit-btn"
509
- title="Edit"
510
- type="button"
511
- >
512
- ✏️<span class="btn-label"> Edit</span>
513
- </button>
514
- <button
515
- aria-pressed="false"
516
- aria-label="Toggle preview mode"
517
- class="modal-preview-btn"
518
- title="Preview"
519
- type="button"
520
- >
521
- 👁️<span class="btn-label"> Preview</span>
522
- </button>
523
- <button
524
- aria-pressed="false"
525
- aria-label="Enter fullscreen"
526
- class="modal-fullscreen-btn"
527
- title="Fullscreen"
528
- type="button"
529
- >
530
- ⛶<span class="btn-label"> Fullscreen</span>
531
- </button>
532
- </div>
533
- <button
534
- aria-label="Discard changes"
535
- class="modal-cancel-btn hidden"
536
- title="Discard unsaved changes"
537
- type="button"
538
- >
539
- ✕<span class="btn-label"> Cancel</span>
540
- </button>
541
- <button
542
- aria-label="Save file"
543
- class="modal-save-btn hidden"
544
- type="button"
545
- >
546
- 💾<span class="btn-label"> Save</span>
547
- </button>
548
- <button
549
- aria-label="Close file viewer"
550
- class="modal-close-btn"
551
- type="button"
552
- >
553
- &times;
554
- </button>
555
- </div>
556
- </div>
557
- <div class="modal-body">
558
- <div class="file-content file-content--raw"></div>
559
- <div class="file-editor-container">
560
- <pre
561
- class="file-editor-overlay"
562
- aria-hidden="true"
563
- ><code class="hljs"></code></pre>
564
- <textarea
565
- aria-label="File editor"
566
- class="file-editor"
567
- spellcheck="false"
568
- ></textarea>
569
- </div>
570
- </div>
571
- </div>
572
- </shadow-claw-dialog>
573
- </template>
574
- `,`text/html`),z=R.querySelector(`template`);let B=[];B=z?Array.from(z.content.children):Array.from(R.head.children).concat(Array.from(R.body.children));var V=B;const H=`shadow-claw-file-viewer`,U=`components/${H}/highlightjs-atom-one-dark.min.css`,W=`pre code.hljs, code.hljs, .hljs { font-family: var(--shadow-claw-font-mono) !important; }`,G={ALLOWED_URI_REGEXP:/^(?:(?:https?|mailto|ftp|tel|file|blob|data):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i,ADD_TAGS:[`iframe`,`figure`,`figcaption`],CUSTOM_ELEMENT_HANDLING:{tagNameCheck:e=>m(e),attributeNameCheck:()=>!0,allowCustomizedBuiltInElements:!1},ADD_ATTR:[`allow`,`allowfullscreen`,`frameborder`,`scrolling`,`referrerpolicy`,`loading`]};function K(e,t){return!e||typeof e.transaction!=`function`||s(e,t).then(e=>O(e,!0)).catch(()=>!0)}var q=class extends S{static styles=L;static template=V;broadcastProxy=null;currentImageObjectUrls=[];currentObjectUrl=null;db=null;editorDraftContent=null;isEditorDirty=!1;isFileEditMode=!1;isFilePreviewMode=!1;isFullscreenMode=!1;lastOpenedFileName=``;previewFrameWindow=null;themeObserver=null;viewRenderToken=0;constructor(){super()}async connectedCallback(){if(!this.shadowRoot)throw Error(`shadowRoot not found`);this.setupEffects(),this.bindEventListeners(),this.broadcastProxy=new N(()=>this.previewFrameWindow||this.shadowRoot?.querySelector(`.file-content-iframe`)?.contentWindow||null),window.addEventListener(`message`,this.handleIframeMessage),document.addEventListener(`fullscreenchange`,this.handleFullscreenChange),this.themeObserver=new MutationObserver(e=>{for(let t of e)t.type===`attributes`&&t.attributeName===`class`&&this.syncIframeTheme()}),this.themeObserver.observe(document.documentElement,{attributes:!0,attributeFilter:[`class`]}),this.db=await o();try{let e=await fetch(U).then(e=>e.text());this.applyHighlightStyles(e)}catch(e){console.warn(`Failed to load highlight.js styles:`,e)}}disconnectedCallback(){this.broadcastProxy?.dispose(),this.broadcastProxy=null,window.removeEventListener(`message`,this.handleIframeMessage),document.removeEventListener(`fullscreenchange`,this.handleFullscreenChange),this.themeObserver&&=(this.themeObserver.disconnect(),null),this.revokeObjectUrl()}applyFullscreenMode(e){let t=e.querySelector(`.modal-content`);t instanceof HTMLElement&&t.classList.toggle(`modal-content--fullscreen`,this.isFullscreenMode);let n=e.querySelector(`.modal-fullscreen-btn`);n instanceof HTMLButtonElement&&(n.setAttribute(`aria-pressed`,String(this.isFullscreenMode)),n.setAttribute(`aria-label`,this.isFullscreenMode?`Exit fullscreen`:`Enter fullscreen`),n.title=this.isFullscreenMode?`Exit fullscreen`:`Fullscreen`)}applyHighlightStyles(e){let t=this.shadowRoot;if(!t)return;if(typeof CSSStyleSheet<`u`&&typeof CSSStyleSheet.prototype.replaceSync==`function`&&`adoptedStyleSheets`in t)try{let n=new CSSStyleSheet;n.replaceSync(e);let r=new CSSStyleSheet;r.replaceSync(W),t.adoptedStyleSheets=[...t.adoptedStyleSheets?Array.from(t.adoptedStyleSheets):[],n,r];return}catch{}let n=document.createElement(`style`);n.setAttribute(`data-shadow-claw-highlight-theme`,`true`),n.textContent=`${e}\n${W}`,t.appendChild(n)}bindEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.querySelector(`.file-modal`);t?.addEventListener(`cancel`,e=>{e.preventDefault(),this.requestCloseViewer()}),t?.addEventListener(`close`,()=>{D.file&&D.closeFile()}),e.querySelector(`.modal-close-btn`)?.addEventListener(`click`,()=>void this.requestCloseViewer()),e.querySelector(`.modal-preview-btn`)?.addEventListener(`click`,async()=>{this.isFilePreviewMode=!this.isFilePreviewMode,this.isFileEditMode=!1,await this.updateView()}),e.querySelector(`.modal-fullscreen-btn`)?.addEventListener(`click`,()=>{t&&this.toggleFullscreenMode(t)}),e.querySelector(`.modal-share-btn`)?.addEventListener(`click`,async()=>{await this.handleShareFile()}),e.querySelector(`.modal-edit-btn`)?.addEventListener(`click`,async()=>{this.isFileEditMode=!this.isFileEditMode,this.isFileEditMode&&(this.isFilePreviewMode=!1),await this.updateView()}),e.querySelector(`.modal-save-btn`)?.addEventListener(`click`,()=>this.handleSave()),e.querySelector(`.modal-cancel-btn`)?.addEventListener(`click`,async()=>{this.isEditorDirty=!1,this.editorDraftContent=null,this.isFileEditMode=!1,await this.updateView()});let n=e.querySelector(`.file-editor`);if(n?.addEventListener(`input`,()=>{n instanceof HTMLTextAreaElement&&(this.editorDraftContent=n.value,this.updateEditorHighlight(n.value)),this.isEditorDirty=!0,this.updateView()}),n instanceof HTMLTextAreaElement){let t=()=>{let t=e.querySelector(`.file-editor-overlay`);t&&(t.scrollTop=n.scrollTop,t.scrollLeft=n.scrollLeft)};n.addEventListener(`scroll`,t),n.addEventListener(`focus`,t),n.addEventListener(`click`,t),n.addEventListener(`keyup`,t),n.addEventListener(`mouseup`,t),e.querySelector(`.modal-body`)?.addEventListener(`scroll`,t)}}buildWebShareFile(e){if(e?.nativeFile instanceof File)return e.nativeFile;let t=e?.binaryContent;if(!(t instanceof Uint8Array)||t.length===0)return null;let n=new Uint8Array(t.byteLength);return n.set(t),new File([n],e.name||`shared-file`,{type:e?.mimeType||`application/octet-stream`})}canShareCurrentFile(e){if(!e||!this.isWebShareAvailable())return!1;if(e.kind===`text`)return!0;let t=this.buildWebShareFile(e);if(!t||typeof navigator.canShare!=`function`)return!1;try{return navigator.canShare({files:[t]})}catch{return!1}}canUseNativeFullscreen(e){return document.fullscreenEnabled===!0&&(typeof e.requestFullscreen==`function`||typeof e.webkitRequestFullscreen==`function`)&&(typeof document.exitFullscreen==`function`||typeof document.webkitExitFullscreen==`function`)}getCurrentFullscreenElement(){return document.fullscreenElement||document.webkitFullscreenElement||null}getFullscreenTarget(e){let t=e.querySelector(`.modal-content`);return t instanceof HTMLElement?t:null}getIframeBridgeScriptUrl(){return n(`/assets/file-viewer-preview-bridge.js`)}getIframeSandboxPermissions(e){return/\.svg$/i.test(e)?`allow-modals allow-popups allow-popups-to-escape-sandbox`:u()}getLanguageFromFilename(e){return{bash:`bash`,cjs:`javascript`,css:`css`,html:`xml`,java:`java`,javascript:`javascript`,js:`javascript`,json:`json`,jsx:`jsx`,markdown:`markdown`,md:`markdown`,mjs:`javascript`,php:`php`,python:`python`,py:`python`,ruby:`ruby`,rb:`ruby`,rust:`rust`,rs:`rust`,sh:`bash`,sql:`sql`,svg:`xml`,ts:`typescript`,tsx:`tsx`,xml:`xml`,yaml:`yaml`,yml:`yaml`}[e.toLowerCase().split(`.`).pop()||``]||``}getPreviewSourceFile(e,t){return this.getWorkingSourceFile(e,t)}getWorkingSourceFile(e,t){if(!this.isEditorDirty||e?.kind!==`text`)return e;if(typeof this.editorDraftContent==`string`)return{...e,content:this.editorDraftContent};let n=t.querySelector(`.file-editor`);return n instanceof HTMLTextAreaElement?{...e,content:n.value}:e}getWorkspaceRouteTarget(e,t={}){let{allowCrossGroup:n=!1}=t,i=e.split(/[?#]/,1)[0].trim();if(!i)return null;if(/^[a-zA-Z][a-zA-Z\d+.-]*:/u.test(i)||i.startsWith(`//`)){let e;try{e=new URL(i,window.location.href)}catch{return null}if(e.origin!==window.location.origin)return null;i=e.pathname}let a=i.replace(/^(?:\.\/)+/u,``),o=[];if(a.startsWith(`files/`)&&o.push(`/${a}`),i.startsWith(`/`)){let e=i.lastIndexOf(`/files/`);e>0&&o.push(i.slice(e)),o.push(i)}for(let e of o){let t=r(e);if(!t)continue;let i=this.resolveRouteGroupId(t.groupId);if(i&&!(!n&&i!==y.activeGroupId))return{groupId:i,path:t.path}}return null}handleAnchorNavigation(e){let t=this.shadowRoot;if(!t)return!1;let n=t.querySelector(`.file-content`);if(!n)return!1;n.querySelectorAll(`.code-line.highlighted`).forEach(e=>{e.classList.remove(`highlighted`)});let r=e.match(/^#?L(\d+)(?:-L?(\d+))?$/i);if(r){let e=parseInt(r[1],10),t=r[2]?parseInt(r[2],10):e,i=null;return n.querySelectorAll(`.code-line`).forEach(n=>{let r=parseInt(n.getAttribute(`data-line`)||`0`,10);r>=e&&r<=t&&(n.classList.add(`highlighted`),i||=n)}),i?(i.scrollIntoView({behavior:`smooth`,block:`center`}),!0):!1}else{let t=e.replace(/^#/,``),r=n.querySelector(`[id="${t}"]`)||n.querySelector(`a[name="${t}"]`);return r?(r.scrollIntoView({behavior:`smooth`,block:`start`}),!0):!1}}handleFullscreenChange=()=>{let e=this.shadowRoot;if(!e)return;let t=e.querySelector(`.file-modal`);if(!(t instanceof HTMLElement))return;let n=this.getFullscreenTarget(t);this.isFullscreenMode=this.isTargetInFullscreen(n),this.applyFullscreenMode(t)};handleIframeMessage=e=>{if(!e.data||typeof e.data!=`object`)return;let n=e.data;if(n.type===`shadow-claw-broadcast-result`&&typeof n.channel==`string`){this.broadcastProxy?.handleResultFromIframe(e.source,n.channel,n.payload);return}if(n.type===`shadow-claw-iframe-resize`&&typeof n.height==`number`){let t=this.shadowRoot?.querySelector(`.file-content-iframe`);t instanceof HTMLIFrameElement&&(!this.previewFrameWindow||e.source===this.previewFrameWindow||t.contentWindow&&e.source===t.contentWindow)&&(this.previewFrameWindow=t.contentWindow,t.style.setProperty(`height`,`${n.height}px`,`important`));return}if(n.type===`shadow-claw-storage-proxy`){if(this.previewFrameWindow&&e.source!==this.previewFrameWindow)return;let t=n;this.handleStorageProxyRequest(e.source,String(t.requestId||``),String(t.method||``),t.args&&typeof t.args==`object`?t.args:{});return}if(!this.db||n.type!==`shadow-claw-file-viewer-link`||typeof n.href!=`string`||this.previewFrameWindow&&e.source!==this.previewFrameWindow)return;let r=D.file,o=r?.path||r?.name||``,s=t(y.activeGroupId,o),c=a(n.href,s,window.location.origin);if(!c)return;if(c.searchParams.has(`gameSave`)){this.reloadPreviewWithSearchParams(c.search);return}if(!(c.origin===window.location.origin&&(i(c.pathname)||this.resolveWorkspaceLinkPath(n.href,o)))){window.open(c.href,`_blank`,`noopener,noreferrer`);return}let l=`${c.pathname}${c.search}${c.hash}`,u=window.navigation;if(u&&typeof u.navigate==`function`){u.navigate(l);return}window.history.pushState({},``,l),window.dispatchEvent(new PopStateEvent(`popstate`))};hasUnsavedChanges(){return this.isEditorDirty}isIframePreviewFile(e){return/\.(?:html?|svg)$/i.test(e)}isMarkdownLikeFile(e){return/(?:^readme$|\.mdx?$|\.markdown$|\.mdown$)/i.test(e)}isNodeInComposedTree(e,t){let n=e;for(;n;){if(n===t)return!0;if(n.parentNode){n=n.parentNode;continue}let e=n.getRootNode?.();if(e instanceof ShadowRoot&&e.host){n=e.host;continue}n=null}return!1}isRenderTokenCurrent(e){return this.viewRenderToken===e}isTargetInFullscreen(e){if(!e)return!1;let t=this.getCurrentFullscreenElement();return t?t===e||this.isNodeInComposedTree(e,t)||this.isNodeInComposedTree(t,e):!1}isWebShareAvailable(){return typeof navigator<`u`&&typeof navigator.share==`function`}mimeTypeForImageExt(e){return{apng:`image/apng`,avif:`image/avif`,gif:`image/gif`,jpg:`image/jpeg`,jpeg:`image/jpeg`,png:`image/png`,svg:`image/svg+xml`,webp:`image/webp`}[e]??`image/jpeg`}renderBinaryPreview(e,t){let n=t.mimeType||`application/octet-stream`;if(t.nativeFile instanceof File)this.currentObjectUrl=URL.createObjectURL(t.nativeFile);else{let r=t.binaryContent;if(!(r instanceof Uint8Array)||r.length===0){e.classList.remove(`file-content--raw`,`file-content--iframe`),e.classList.add(`file-content--preview`),e.textContent=`Binary content unavailable.`;return}let i=new Uint8Array(r.byteLength);i.set(r);let a=new Blob([i],{type:n});this.currentObjectUrl=URL.createObjectURL(a)}if(e.classList.remove(`file-content--raw`,`file-content--preview`),e.classList.add(`file-content--iframe`),n.startsWith(`image/`)){let n=document.createElement(`img`);n.className=`file-content-iframe`,n.alt=`Preview: ${t.name}`,n.src=this.currentObjectUrl,n.style.objectFit=`contain`,e.replaceChildren(n);return}if(n.startsWith(`video/`)){let t=document.createElement(`video`);t.className=`file-content-iframe`,t.controls=!0,t.src=this.currentObjectUrl,t.style.backgroundColor=`black`,e.replaceChildren(t);return}if(n.startsWith(`audio/`)){let n=document.createElement(`div`);n.className=`file-content file-content--preview`,n.style.padding=`1rem`;let r=document.createElement(`p`);r.textContent=t.name;let i=document.createElement(`audio`);i.controls=!0,i.src=this.currentObjectUrl,i.style.width=`100%`,n.replaceChildren(r,i),e.replaceChildren(n),e.classList.remove(`file-content--iframe`);return}let r=document.createElement(`iframe`);r.className=`file-content-iframe`,r.setAttribute(`title`,`Preview: ${t.name}`),r.setAttribute(`referrerpolicy`,`no-referrer`),r.src=this.currentObjectUrl,e.replaceChildren(r)}resetContent(){let e=this.shadowRoot;if(!e)return;let t=e.querySelector(`.file-modal`);if(!(t instanceof HTMLElement))return;let n=this.getFullscreenTarget(t);n&&this.isTargetInFullscreen(n)&&this.exitNativeFullscreen().catch(()=>{}),this.isFullscreenMode=!1,this.applyFullscreenMode(t);let r=t.querySelector(`.file-content`),i=t.querySelector(`.modal-preview-btn`);i instanceof HTMLButtonElement&&(i.setAttribute(`aria-pressed`,`false`),i.setAttribute(`aria-label`,`Switch to preview mode`));let a=t.querySelector(`.modal-edit-btn`);a instanceof HTMLButtonElement&&(a.setAttribute(`aria-pressed`,`false`),a.setAttribute(`aria-label`,`Edit file`),a.classList.remove(`hidden`));let o=t.querySelector(`.modal-close-btn`);o instanceof HTMLButtonElement&&(o.disabled=!1,o.setAttribute(`aria-label`,`Close file viewer`),o.title=`Close`),t.querySelector(`.modal-save-btn`)?.classList.add(`hidden`),t.querySelector(`.file-editor-container`)?.classList.remove(`active`),t.querySelector(`.modal-body`)?.classList.remove(`modal-body--editing`);let s=t.querySelector(`.file-editor`);s instanceof HTMLTextAreaElement&&(s.value=``,s.removeAttribute(`language`));let c=t.querySelector(`.file-editor-overlay code`);c&&(c.innerHTML=``,c.className=`hljs`),this.isFileEditMode=!1,this.editorDraftContent=null,r instanceof HTMLElement&&(this.revokeObjectUrl(),r.classList.remove(`hidden`),r.classList.add(`file-content--raw`),r.classList.remove(`file-content--preview`,`file-content--iframe`),r.textContent=``)}resolveRouteGroupId(e){let t=y.activeGroupId;if(e===t||this.routeGroupMatches(e,t))return t;let n=Array.isArray(y.groups)?y.groups:[],r=n.find(t=>t.groupId===e);if(r)return r.groupId;let i=n.find(t=>this.routeGroupMatches(e,t.groupId));return i?i.groupId:e||null}resolveWorkspaceLinkPath(e,t=``){let n=e.trim();if(!n||n.startsWith(`#`))return null;let r=n,i=/^[a-zA-Z][a-zA-Z\d+.-]*:/.test(n);if(i||n.startsWith(`//`)){let e;try{e=new URL(n,window.location.href)}catch{return null}if(!(e.protocol===`http:`||e.protocol===`https:`)||e.host!==window.location.host)return null;r=`${e.pathname}${e.search}${e.hash}`}let a=this.getWorkspaceRouteTarget(r);if(a)return a.path;let o=r.split(/[?#]/,1)[0].replace(/\\/g,`/`),s=o.startsWith(`/`);if(i||s||(o=o.replace(/^\/+/,``),!o))return null;let c=[];if(!s){let e=t.replace(/\\/g,`/`).replace(/^\/+/,``).split(`/`).filter(Boolean);e.pop(),c.push(...e)}for(let e of o.split(`/`))if(!(!e||e===`.`)){if(e===`..`){if(c.length===0)return null;c.pop();continue}c.push(e)}return c.length>0?c.join(`/`):null}revokeObjectUrl(){this.previewFrameWindow=null,this.currentObjectUrl&&=(URL.revokeObjectURL(this.currentObjectUrl),null);for(let e of this.currentImageObjectUrls)URL.revokeObjectURL(e);this.currentImageObjectUrls=[]}rewriteWorkspacePreviewHtml(e,n){if(!e)return e;let r=t(y.activeGroupId,n),o=new DOMParser().parseFromString(e,`text/html`),s=(e,t)=>{let s=Array.from(o.querySelectorAll(e));for(let e of s){let o=(e.getAttribute(t)||``).trim();if(!o||o.startsWith(`#`)||o.startsWith(`javascript:`))continue;let s=a(o,r,window.location.origin);!s||s.origin!==window.location.origin||t===`href`&&!(i(s.pathname)||this.resolveWorkspaceLinkPath(o,n))||e.setAttribute(t,`${s.pathname}${s.search}${s.hash}`)}};return s(`a[href]`,`href`),s(`img[src]`,`src`),s(`audio[src]`,`src`),s(`video[src]`,`src`),s(`source[src]`,`src`),o.body.innerHTML}routeGroupMatches(e,t){if(e===t||e===`main`&&t===`br:main`||e===`br:main`&&t===`main`)return!0;if(!e.includes(`:`)&&!t.includes(`:`))return!1;let n=e=>e.trim().replace(/:/g,`-`);return n(e)===n(t)}setupEffects(){C(()=>{let e=_.declarativeTools;this.broadcastProxy&&e.length>0&&this.broadcastProxy.registerChannelsFromTools(e)}),C(()=>{let e=D.file,t=++this.viewRenderToken,n=this.shadowRoot;if(!n)return;let r=n.querySelector(`shadow-claw-dialog`);r&&typeof r.ensureDialog==`function`&&r.ensureDialog();let i=n.querySelector(`.file-modal`);if(e){r&&typeof r.showModal==`function`&&!r.open?r.showModal():i instanceof HTMLDialogElement&&!i.open&&i.showModal();let a=n.querySelector(`.modal-title`);a instanceof HTMLElement&&(a.textContent=`File: ${e.name}`),this.lastOpenedFileName!==e.name&&(this.lastOpenedFileName=e.name,this.isFilePreviewMode=this.shouldAutoPreview(e),this.isFileEditMode=!1,this.isEditorDirty=!1,this.editorDraftContent=null),this.updateView(t)}else r&&typeof r.close==`function`&&r.open?r.close():i instanceof HTMLDialogElement&&i.open&&i.close(),this.lastOpenedFileName=``,this.isFilePreviewMode=!1,this.isEditorDirty=!1,this.editorDraftContent=null,this.resetContent()})}shouldAutoPreview(e){return!e||typeof e!=`object`?!1:e.kind===`pdf`||e.kind===`binary`?!0:e.kind===`text`?this.isIframePreviewFile(e.name)||this.isMarkdownLikeFile(e.name):!1}stripHtmlFrontmatter(e){if(typeof e!=`string`||!e.trimStart().startsWith(`---`))return e;let t=w(e);return Object.keys(t.data||{}).length===0?e:t.content||``}toPreviewMarkdown(e){return this.isMarkdownLikeFile(e.name)?e.content:"```"+this.getLanguageFromFilename(e.name)+`
575
- `+e.content+"\n```"}updateEditorHighlight(e){let t=this.shadowRoot;if(!t)return;let n=t.querySelector(`.file-editor-overlay code`);if(!n)return;let r=D.file,i=this.getLanguageFromFilename(r?.name||``),a=``;try{a=i&&T.getLanguage(i)?T.highlight(e,{language:i}).value:T.highlightAuto(e).value}catch{a=e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`)}n.className=i?`hljs language-${i}`:`hljs`,n.innerHTML=l(a+`<br>`)}wrapCodeLines(e){e.querySelectorAll(`pre code`).forEach(e=>{let t=e.innerHTML.split(/\r?\n/u);t.length>1&&t[t.length-1]===``&&t.pop(),h(e,t.map((e,t)=>`<span class="code-line" data-line="${t+1}">${e||`&nbsp;`}</span>`).join(`
576
- `))})}async buildIframePreviewSrcdoc(e,r=``){if(/\.svg$/i.test(e.name))return e.content;let i=e.path||e.name||``,a=this.stripHtmlFrontmatter(e.content||``),o=this.rewriteWorkspacePreviewHtml(a,i),s=d(await this.resolveRelativeImagesInHtml(o,i),G),c=crypto.randomUUID().replace(/-/g,``),l=this.getIframeBridgeScriptUrl(),u=n(`/assets/iframe-storage-bridge.js`),m=f(),h=p(c),g=typeof document<`u`?document.getElementById(`shadow-claw-site-config`):null,_=g&&g.textContent?`<script id="shadow-claw-site-config" type="application/json">${g.textContent}<\/script>`:``,v=r?`<script nonce="${c}">(function(){try{Object.defineProperty(window.location,"search",{get:function(){return ${JSON.stringify(r)};},configurable:true});}catch(e){}})();<\/script>`:``,b=m.map(e=>`<script type="module" src="${e.startsWith(`http://`)||e.startsWith(`https://`)||e.startsWith(`//`)?e:n(e.startsWith(`/`)?e:`/${e.replace(/^pages\/main\//,``)}`)}" nonce="${c}"><\/script>`).join(`
577
- `),x=`<link rel="stylesheet" href="${n(`/theme.css`)}">`;return[`<!doctype html>`,`<html class="${F()}"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">`,`<meta http-equiv="Content-Security-Policy" content="${h}">`,`<base href="${n(t(y.activeGroupId,i))}" target="_blank">`,v,_,`<script src="${u}" nonce="${c}"><\/script>`,`<script src="${l}" nonce="${c}"><\/script>`,A(),x,b,`</head><body>`,s,`</body></html>`].join(``)}async canDismissViewer(){if(!this.hasUnsavedChanges())return!0;let e=await this.requestConfirmation({title:`Discard Unsaved Changes`,message:`You have unsaved changes. Discard them and close?`,confirmLabel:`Discard`,cancelLabel:`Keep Editing`});return e&&(this.isEditorDirty=!1,this.editorDraftContent=null),e}async exitFullscreenIfActive(e){let t=this.shadowRoot,n=e||t?.querySelector(`.file-modal`);if(!n)return;let r=this.getFullscreenTarget(n);if(!(!r||!this.isTargetInFullscreen(r)))try{await this.exitNativeFullscreen()}catch{}}async exitNativeFullscreen(){let e=document.exitFullscreen||document.webkitExitFullscreen;if(typeof e!=`function`)throw Error(`Native fullscreen exit unavailable`);await Promise.resolve(e.call(document))}async handlePreviewLinkClick(e){if(e.defaultPrevented||e.button!==0||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;let n=e.target;if(!(n instanceof Element))return;let r=n.closest(`a`);if(!(r instanceof HTMLAnchorElement)||!this.db)return;let o=D.file,s=o?.path||o?.name||``,c=r.getAttribute(`href`)||``,l=a(c,t(y.activeGroupId,s),window.location.origin);if(l&&l.origin===window.location.origin&&(i(l.pathname)||this.resolveWorkspaceLinkPath(c,s))&&l){e.preventDefault();let t=`${l.pathname}${l.search}${l.hash}`,n=window.navigation;n&&typeof n.navigate==`function`?n.navigate(t):(window.history.pushState({},``,t),window.dispatchEvent(new PopStateEvent(`popstate`)));return}let u=c.trim();if(u&&!u.startsWith(`#`)&&!u.startsWith(`javascript:`)){let t=r.getAttribute(`target`)||`_blank`,n=t===`_self`||t===`_top`||t===`_parent`?`_blank`:t;try{new URL(u,window.location.href).host!==window.location.host&&(e.preventDefault(),window.open(u,n,`noopener,noreferrer`))}catch{/^[a-zA-Z][a-zA-Z\d+.-]*:/u.test(u)&&(e.preventDefault(),window.open(u,n,`noopener,noreferrer`))}}}async handleSave(){let e=D.file;if(!e||!this.db)return;let t=this.shadowRoot,n=t?.querySelector(`.modal-save-btn`),r=t?.querySelector(`.file-editor`);if(r instanceof HTMLTextAreaElement)try{n instanceof HTMLButtonElement&&(n.disabled=!0,n.textContent=`⏳ saving...`);let t=r.value,i=e.path||(y.currentPath===`.`?e.name:`${y.currentPath}/${e.name}`),a=e.groupId||y.activeGroupId;await v(this.db,a,i,t),b(`Saved ${e.name}`),document.dispatchEvent(new CustomEvent(`shadow-claw-file-saved`,{detail:{groupId:a,path:i},bubbles:!0,composed:!0})),await y.loadFiles(this.db),e.content=t,this.isFileEditMode=!1,this.isEditorDirty=!1,this.editorDraftContent=null,await this.updateView()}catch(e){x(`Failed to save file: ${e instanceof Error?e.message:String(e)}`)}finally{n instanceof HTMLButtonElement&&(n.disabled=!1,n.textContent=`💾 Save`)}}async handleShareFile(){let e=D.file;if(!e||!this.canShareCurrentFile(e)){x(`Sharing is not supported for this file on this device.`,4500);return}try{if(e.kind===`text`)await navigator.share({title:e.name,text:e.content||``});else{let t=this.buildWebShareFile(e);if(!t||!navigator.canShare?.({files:[t]})){x(`File sharing is not supported on this device.`,4500);return}await navigator.share({title:e.name,files:[t]})}b(`Shared ${e.name}`)}catch(e){if(e instanceof DOMException&&e.name===`AbortError`)return;x(`Failed to share file: ${e instanceof Error?e.message:String(e)}`,5e3)}}async openFolderInFilesView(e){if(!this.db)return;let t=e.replace(/^\/+|\/+$/g,``);if(t)try{await y.setCurrentPath(this.db,t),D.closeFile();let e=window?.shadowclaw?.ui;e&&typeof e.showPage==`function`&&e.showPage(`files`)}catch(e){x(`Failed to open linked folder: ${e instanceof Error?e.message:String(e)}`,5e3)}}async openWorkspaceLink(e,t){if(!this.db)return;let n=this.resolveWorkspaceLinkPath(e,t);if(!n)return;let r=n.split(`/`).filter(Boolean).pop()||``;if(!/\.[^./]+$/u.test(r)){try{await D.openFile(this.db,n,y.activeGroupId);return}catch(e){let t=e instanceof DOMException&&e.name===`NotFoundError`,n=e instanceof DOMException&&e.name===`TypeMismatchError`;if(!t&&!n){x(`Failed to open linked file: ${e instanceof Error?e.message:String(e)}`,5e3);return}}await this.openFolderInFilesView(n);return}try{await D.openFile(this.db,n,y.activeGroupId)}catch(e){x(`Failed to open linked file: ${e instanceof Error?e.message:String(e)}`,5e3)}}async renderPreview(t,n,r=this.viewRenderToken){if(!this.isRenderTokenCurrent(r))return;if(this.revokeObjectUrl(),this.previewFrameWindow=null,n.kind===`pdf`){t.classList.remove(`file-content--raw`,`file-content--preview`,`file-content--iframe`),import(`./shadow-claw-pdf-viewer-gOiW-_Bh.js`).then(()=>{let e=document.createElement(`shadow-claw-pdf-viewer`);e.file=n,t.replaceChildren(e)}).catch(console.error);return}if(n.kind===`binary`){this.renderBinaryPreview(t,n);return}if(this.isIframePreviewFile(n.name)){t.classList.remove(`file-content--raw`,`file-content--preview`),t.classList.add(`file-content--iframe`);let e=document.createElement(`iframe`);e.className=`file-content-iframe`,e.setAttribute(`title`,`Preview: ${n.name}`),e.setAttribute(`sandbox`,this.getIframeSandboxPermissions(n.name)),e.setAttribute(`allow`,`fullscreen`),e.setAttribute(`referrerpolicy`,`no-referrer`),c(e,await this.buildIframePreviewSrcdoc(n)),e.addEventListener(`load`,()=>{this.previewFrameWindow=e.contentWindow,this.syncIframeTheme()}),t.replaceChildren(e);return}t.classList.remove(`file-content--raw`),t.classList.add(`file-content--preview`);let i=D.file,a=i?.path||i?.name||``,o=this.toPreviewMarkdown(n),s=K(this.db,e.MARKDOWN_FRONTMATTER_FILE_VIEWER),l=await E(o,{renderFrontmatter:typeof s==`boolean`?s:await s});if(!this.isRenderTokenCurrent(r))return;let u=this.rewriteWorkspacePreviewHtml(l,a);this.isRenderTokenCurrent(r)&&(h(t,u,G),this.wrapCodeLines(t),await this.resolveMarkdownImages(t,a))}async requestCloseViewer(){return await this.canDismissViewer()?(await this.exitFullscreenIfActive(),D.closeFile(),!0):!1}async requestConfirmation(e){let t=document.querySelector(`shadow-claw`);return t&&typeof t.requestDialog==`function`?await t.requestDialog({mode:`confirm`,...e}):!1}async requestNativeFullscreen(e){let t=e.requestFullscreen||e.webkitRequestFullscreen;if(typeof t!=`function`)throw Error(`Native fullscreen unavailable`);await Promise.resolve(t.call(e))}async resolveMarkdownImages(e,t){if(!this.db)return;let n=Array.from(e.querySelectorAll(`img`));n.length!==0&&await Promise.all(n.map(async e=>{let n=e.getAttribute(`src`)||``;if(!n||/^(?:blob:|data:|#)/u.test(n))return;let r=this.getWorkspaceRouteTarget(n,{allowCrossGroup:!0})||(()=>{let e=this.resolveWorkspaceLinkPath(n,t);return e?{groupId:y.activeGroupId,path:e}:null})();if(r)try{let t=await g(this.db,r.groupId,r.path),n=r.path.split(`.`).pop()?.toLowerCase()||``,i=this.mimeTypeForImageExt(n),a=new Uint8Array(t.byteLength);a.set(t),e.src=await new Promise((e,t)=>{let n=new FileReader;n.onload=()=>e(n.result),n.onerror=t,n.readAsDataURL(new Blob([a],{type:i}))})}catch{}}))}async resolveRelativeImagesInHtml(e,t){if(!this.db||!e)return e;let n=new DOMParser().parseFromString(e,`text/html`),r=Array.from(n.querySelectorAll(`img`));return r.length===0?e:(await Promise.all(r.map(async e=>{let n=e.getAttribute(`src`)||``;if(!n||/^(?:blob:|data:|#)/u.test(n))return;let r=this.getWorkspaceRouteTarget(n,{allowCrossGroup:!0})||(()=>{let e=this.resolveWorkspaceLinkPath(n,t);return e?{groupId:y.activeGroupId,path:e}:null})();if(r)try{let t=await g(this.db,r.groupId,r.path),n=r.path.split(`.`).pop()?.toLowerCase()||``,i=this.mimeTypeForImageExt(n),a=new Uint8Array(t.byteLength);a.set(t);let o=await new Promise((e,t)=>{let n=new FileReader;n.onload=()=>e(n.result),n.onerror=t,n.readAsDataURL(new Blob([a],{type:i}))});e.setAttribute(`src`,o)}catch{}})),n.body.innerHTML)}async toggleFullscreenMode(e){let t=this.getFullscreenTarget(e);if(t){if(this.canUseNativeFullscreen(t)){let n=this.isTargetInFullscreen(t);try{n?(await this.exitNativeFullscreen(),this.isFullscreenMode=!1):(await this.requestNativeFullscreen(t),this.isFullscreenMode=!0)}catch{this.isFullscreenMode=!this.isFullscreenMode}this.applyFullscreenMode(e);return}this.isFullscreenMode=!this.isFullscreenMode,this.applyFullscreenMode(e)}}async updateView(e=this.viewRenderToken){let t=D.file,n=this.shadowRoot;if(!n||!t)return;let r=n.querySelector(`.file-modal`);if(!(r instanceof HTMLElement))return;this.applyFullscreenMode(r);let i=r.querySelector(`.file-content`),a=r.querySelector(`.modal-preview-btn`),o=r.querySelector(`.modal-body`);if(!(i instanceof HTMLElement))return;i.classList.remove(`file-content--iframe`);let s=this.getWorkingSourceFile(t,r),c=t.kind===`text`;a instanceof HTMLButtonElement&&(a.setAttribute(`aria-pressed`,String(this.isFilePreviewMode)),a.setAttribute(`aria-label`,this.isFilePreviewMode?`Switch to raw text view`:`Switch to preview mode`));let l=r.querySelector(`.file-editor-container`),u=r.querySelector(`.modal-edit-btn`),d=r.querySelector(`.modal-save-btn`),f=r.querySelector(`.modal-share-btn`),p=r.querySelector(`.modal-close-btn`),m=r.querySelector(`.modal-cancel-btn`);if(f instanceof HTMLButtonElement){let e=this.canShareCurrentFile(t);f.classList.toggle(`hidden`,!e),f.disabled=!e}if(p instanceof HTMLButtonElement){let e=this.hasUnsavedChanges();p.disabled=!1,p.setAttribute(`aria-label`,e?`Close file viewer (unsaved changes)`:`Close file viewer`),p.title=e?`Close (you have unsaved changes)`:`Close`}let h=this.hasUnsavedChanges();if(d instanceof HTMLButtonElement&&d.classList.toggle(`hidden`,!h),m instanceof HTMLButtonElement&&m.classList.toggle(`hidden`,!h),this.isFilePreviewMode){o?.classList.remove(`modal-body--editing`),i.classList.remove(`hidden`),l?.classList.remove(`active`),u instanceof HTMLButtonElement&&(u.setAttribute(`aria-pressed`,`false`),u.setAttribute(`aria-label`,`Edit file`),u.classList.toggle(`hidden`,!c)),await this.renderPreview(i,s,e);return}if(this.isRenderTokenCurrent(e))if(this.isFileEditMode&&c){o?.classList.add(`modal-body--editing`),i.classList.add(`hidden`),l?.classList.add(`active`),u instanceof HTMLButtonElement&&(u.setAttribute(`aria-pressed`,`true`),u.setAttribute(`aria-label`,`Switch to raw text view`),u.classList.remove(`hidden`));let e=l?.querySelector(`.file-editor`);if(e instanceof HTMLTextAreaElement){e.setAttribute(`tab-size`,`2`);let n=this.getLanguageFromFilename(t.name);if(n?e.setAttribute(`language`,n):e.removeAttribute(`language`),this.isEditorDirty)typeof s?.content==`string`&&(e.value!==s.content&&(e.value=s.content),this.updateEditorHighlight(e.value));else{let n=t.content||``;e.value!==n&&(e.value=n),this.updateEditorHighlight(e.value)}e.dispatchEvent(new Event(`scroll`))}}else o?.classList.remove(`modal-body--editing`),i.classList.remove(`hidden`),l?.classList.remove(`active`),u instanceof HTMLButtonElement&&(u.setAttribute(`aria-pressed`,`false`),u.setAttribute(`aria-label`,`Edit file`),u.classList.toggle(`hidden`,!c)),i.classList.add(`file-content--raw`),i.classList.remove(`file-content--preview`,`file-content--iframe`),t.kind===`binary`?i.textContent=`Binary file (${t.mimeType||`application/octet-stream`}). Switch to Preview to view.`:i.textContent=s.content||``}syncIframeTheme(){if(!this.previewFrameWindow)return;let e=document.documentElement.classList.contains(`dark-mode`),t=getComputedStyle(document.documentElement),n={};for(let e=0;e<t.length;e++){let r=t[e];r.startsWith(`--`)&&(n[r]=t.getPropertyValue(r))}this.previewFrameWindow.postMessage({type:`shadow-claw-theme-update`,theme:e?`dark`:`light`,customProperties:n},`*`)}async handleStorageProxyRequest(e,t,n,r){if(!t)return;let i=D.file,a=i?.path||i?.name||`__default__`;try{let i;switch(n){case`setItem`:await k(a,String(r.key||``),r.value);break;case`removeItem`:await M(a,String(r.key||``));break;case`clear`:await I(a);break;case`getAllItems`:i=await j(a);break;case`idb-get`:i=await P(`${a}::idb::${r.dbName}::${r.storeName}`,String(r.key||``));break;case`idb-getAll`:i=await j(`${a}::idb::${r.dbName}::${r.storeName}`);break;case`idb-put`:{let e=r.key==null?`__auto_${Date.now()}`:String(r.key);await k(`${a}::idb::${r.dbName}::${r.storeName}`,e,r.value),i=e;break}case`idb-delete`:await M(`${a}::idb::${r.dbName}::${r.storeName}`,String(r.key||``));break;case`idb-clear`:await I(`${a}::idb::${r.dbName}::${r.storeName}`);break;case`idb-deleteDatabase`:await I(`${a}::idb::${r.dbName}::__default__`);break;default:throw Error(`Unknown storage proxy method: ${n}`)}e.postMessage({type:`shadow-claw-storage-proxy-result`,requestId:t,result:i??null},`*`)}catch(n){e.postMessage({type:`shadow-claw-storage-proxy-result`,requestId:t,error:n instanceof Error?n.message:String(n)},`*`)}}async reloadPreviewWithSearchParams(e){let t=D.file;if(!t)return;let n=this.shadowRoot?.querySelector(`.file-viewer__iframe`);n&&(this.previewFrameWindow=null,c(n,await this.buildIframePreviewSrcdoc(t,e)))}};customElements.get(H)||customElements.define(H,q);export{q as ShadowClawFileViewer};