@walkthru-earth/objex 0.1.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 (367) hide show
  1. package/LICENSE +396 -0
  2. package/README.md +114 -0
  3. package/dist/assets/favicon.svg +17 -0
  4. package/dist/components/CLAUDE.md +44 -0
  5. package/dist/components/browser/Breadcrumb.svelte +50 -0
  6. package/dist/components/browser/Breadcrumb.svelte.d.ts +7 -0
  7. package/dist/components/browser/CreateFolderDialog.svelte +98 -0
  8. package/dist/components/browser/CreateFolderDialog.svelte.d.ts +6 -0
  9. package/dist/components/browser/DeleteConfirmDialog.svelte +90 -0
  10. package/dist/components/browser/DeleteConfirmDialog.svelte.d.ts +8 -0
  11. package/dist/components/browser/DropZone.svelte +83 -0
  12. package/dist/components/browser/DropZone.svelte.d.ts +7 -0
  13. package/dist/components/browser/FileBrowser.svelte +229 -0
  14. package/dist/components/browser/FileBrowser.svelte.d.ts +3 -0
  15. package/dist/components/browser/FileRow.svelte +112 -0
  16. package/dist/components/browser/FileRow.svelte.d.ts +9 -0
  17. package/dist/components/browser/FileTreeSidebar.svelte +559 -0
  18. package/dist/components/browser/FileTreeSidebar.svelte.d.ts +8 -0
  19. package/dist/components/browser/RenameDialog.svelte +101 -0
  20. package/dist/components/browser/RenameDialog.svelte.d.ts +8 -0
  21. package/dist/components/browser/SearchBar.svelte +40 -0
  22. package/dist/components/browser/SearchBar.svelte.d.ts +6 -0
  23. package/dist/components/browser/UploadButton.svelte +65 -0
  24. package/dist/components/browser/UploadButton.svelte.d.ts +3 -0
  25. package/dist/components/editor/CodeMirrorEditor.svelte +404 -0
  26. package/dist/components/editor/CodeMirrorEditor.svelte.d.ts +12 -0
  27. package/dist/components/editor/MilkdownEditor.svelte +98 -0
  28. package/dist/components/editor/MilkdownEditor.svelte.d.ts +9 -0
  29. package/dist/components/editor/SqlEditor.svelte +173 -0
  30. package/dist/components/editor/SqlEditor.svelte.d.ts +7 -0
  31. package/dist/components/editor/SqlResultBlock.svelte +199 -0
  32. package/dist/components/editor/SqlResultBlock.svelte.d.ts +9 -0
  33. package/dist/components/layout/ConnectionDialog.svelte +439 -0
  34. package/dist/components/layout/ConnectionDialog.svelte.d.ts +9 -0
  35. package/dist/components/layout/LocaleToggle.svelte +32 -0
  36. package/dist/components/layout/LocaleToggle.svelte.d.ts +3 -0
  37. package/dist/components/layout/SafeLockToggle.svelte +37 -0
  38. package/dist/components/layout/SafeLockToggle.svelte.d.ts +18 -0
  39. package/dist/components/layout/Sidebar.svelte +314 -0
  40. package/dist/components/layout/Sidebar.svelte.d.ts +3 -0
  41. package/dist/components/layout/StatusBar.svelte +73 -0
  42. package/dist/components/layout/StatusBar.svelte.d.ts +3 -0
  43. package/dist/components/layout/TabBar.svelte +102 -0
  44. package/dist/components/layout/TabBar.svelte.d.ts +7 -0
  45. package/dist/components/layout/ThemeToggle.svelte +52 -0
  46. package/dist/components/layout/ThemeToggle.svelte.d.ts +3 -0
  47. package/dist/components/ui/badge/badge.svelte +49 -0
  48. package/dist/components/ui/badge/badge.svelte.d.ts +32 -0
  49. package/dist/components/ui/badge/index.d.ts +1 -0
  50. package/dist/components/ui/badge/index.js +1 -0
  51. package/dist/components/ui/button/button.svelte +82 -0
  52. package/dist/components/ui/button/button.svelte.d.ts +64 -0
  53. package/dist/components/ui/button/index.d.ts +2 -0
  54. package/dist/components/ui/button/index.js +4 -0
  55. package/dist/components/ui/context-menu/context-menu-checkbox-item.svelte +40 -0
  56. package/dist/components/ui/context-menu/context-menu-checkbox-item.svelte.d.ts +9 -0
  57. package/dist/components/ui/context-menu/context-menu-content.svelte +28 -0
  58. package/dist/components/ui/context-menu/context-menu-content.svelte.d.ts +10 -0
  59. package/dist/components/ui/context-menu/context-menu-group-heading.svelte +21 -0
  60. package/dist/components/ui/context-menu/context-menu-group-heading.svelte.d.ts +7 -0
  61. package/dist/components/ui/context-menu/context-menu-group.svelte +7 -0
  62. package/dist/components/ui/context-menu/context-menu-group.svelte.d.ts +4 -0
  63. package/dist/components/ui/context-menu/context-menu-item.svelte +27 -0
  64. package/dist/components/ui/context-menu/context-menu-item.svelte.d.ts +8 -0
  65. package/dist/components/ui/context-menu/context-menu-label.svelte +24 -0
  66. package/dist/components/ui/context-menu/context-menu-label.svelte.d.ts +8 -0
  67. package/dist/components/ui/context-menu/context-menu-portal.svelte +7 -0
  68. package/dist/components/ui/context-menu/context-menu-portal.svelte.d.ts +3 -0
  69. package/dist/components/ui/context-menu/context-menu-radio-group.svelte +16 -0
  70. package/dist/components/ui/context-menu/context-menu-radio-group.svelte.d.ts +4 -0
  71. package/dist/components/ui/context-menu/context-menu-radio-item.svelte +33 -0
  72. package/dist/components/ui/context-menu/context-menu-radio-item.svelte.d.ts +4 -0
  73. package/dist/components/ui/context-menu/context-menu-separator.svelte +17 -0
  74. package/dist/components/ui/context-menu/context-menu-separator.svelte.d.ts +4 -0
  75. package/dist/components/ui/context-menu/context-menu-shortcut.svelte +20 -0
  76. package/dist/components/ui/context-menu/context-menu-shortcut.svelte.d.ts +5 -0
  77. package/dist/components/ui/context-menu/context-menu-sub-content.svelte +20 -0
  78. package/dist/components/ui/context-menu/context-menu-sub-content.svelte.d.ts +4 -0
  79. package/dist/components/ui/context-menu/context-menu-sub-trigger.svelte +29 -0
  80. package/dist/components/ui/context-menu/context-menu-sub-trigger.svelte.d.ts +8 -0
  81. package/dist/components/ui/context-menu/context-menu-sub.svelte +7 -0
  82. package/dist/components/ui/context-menu/context-menu-sub.svelte.d.ts +3 -0
  83. package/dist/components/ui/context-menu/context-menu-trigger.svelte +7 -0
  84. package/dist/components/ui/context-menu/context-menu-trigger.svelte.d.ts +4 -0
  85. package/dist/components/ui/context-menu/context-menu.svelte +7 -0
  86. package/dist/components/ui/context-menu/context-menu.svelte.d.ts +3 -0
  87. package/dist/components/ui/context-menu/index.d.ts +17 -0
  88. package/dist/components/ui/context-menu/index.js +19 -0
  89. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte +16 -0
  90. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte.d.ts +4 -0
  91. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +43 -0
  92. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +9 -0
  93. package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte +29 -0
  94. package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte.d.ts +10 -0
  95. package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +22 -0
  96. package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte.d.ts +8 -0
  97. package/dist/components/ui/dropdown-menu/dropdown-menu-group.svelte +7 -0
  98. package/dist/components/ui/dropdown-menu/dropdown-menu-group.svelte.d.ts +4 -0
  99. package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte +27 -0
  100. package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte.d.ts +8 -0
  101. package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte +24 -0
  102. package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte.d.ts +8 -0
  103. package/dist/components/ui/dropdown-menu/dropdown-menu-portal.svelte +7 -0
  104. package/dist/components/ui/dropdown-menu/dropdown-menu-portal.svelte.d.ts +3 -0
  105. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte +16 -0
  106. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte.d.ts +4 -0
  107. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +33 -0
  108. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte.d.ts +4 -0
  109. package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte +17 -0
  110. package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte.d.ts +4 -0
  111. package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +20 -0
  112. package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte.d.ts +5 -0
  113. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +20 -0
  114. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte.d.ts +4 -0
  115. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +29 -0
  116. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte.d.ts +7 -0
  117. package/dist/components/ui/dropdown-menu/dropdown-menu-sub.svelte +7 -0
  118. package/dist/components/ui/dropdown-menu/dropdown-menu-sub.svelte.d.ts +3 -0
  119. package/dist/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +7 -0
  120. package/dist/components/ui/dropdown-menu/dropdown-menu-trigger.svelte.d.ts +4 -0
  121. package/dist/components/ui/dropdown-menu/dropdown-menu.svelte +7 -0
  122. package/dist/components/ui/dropdown-menu/dropdown-menu.svelte.d.ts +3 -0
  123. package/dist/components/ui/dropdown-menu/index.d.ts +18 -0
  124. package/dist/components/ui/dropdown-menu/index.js +18 -0
  125. package/dist/components/ui/input/index.d.ts +2 -0
  126. package/dist/components/ui/input/index.js +4 -0
  127. package/dist/components/ui/input/input.svelte +52 -0
  128. package/dist/components/ui/input/input.svelte.d.ts +13 -0
  129. package/dist/components/ui/resizable/index.d.ts +4 -0
  130. package/dist/components/ui/resizable/index.js +6 -0
  131. package/dist/components/ui/resizable/resizable-handle.svelte +30 -0
  132. package/dist/components/ui/resizable/resizable-handle.svelte.d.ts +8 -0
  133. package/dist/components/ui/resizable/resizable-pane-group.svelte +20 -0
  134. package/dist/components/ui/resizable/resizable-pane-group.svelte.d.ts +7 -0
  135. package/dist/components/ui/scroll-area/index.d.ts +3 -0
  136. package/dist/components/ui/scroll-area/index.js +5 -0
  137. package/dist/components/ui/scroll-area/scroll-area-scrollbar.svelte +31 -0
  138. package/dist/components/ui/scroll-area/scroll-area-scrollbar.svelte.d.ts +4 -0
  139. package/dist/components/ui/scroll-area/scroll-area.svelte +47 -0
  140. package/dist/components/ui/scroll-area/scroll-area.svelte.d.ts +11 -0
  141. package/dist/components/ui/separator/index.d.ts +2 -0
  142. package/dist/components/ui/separator/index.js +4 -0
  143. package/dist/components/ui/separator/separator.svelte +21 -0
  144. package/dist/components/ui/separator/separator.svelte.d.ts +4 -0
  145. package/dist/components/ui/sheet/index.d.ts +11 -0
  146. package/dist/components/ui/sheet/index.js +13 -0
  147. package/dist/components/ui/sheet/sheet-close.svelte +7 -0
  148. package/dist/components/ui/sheet/sheet-close.svelte.d.ts +4 -0
  149. package/dist/components/ui/sheet/sheet-content.svelte +62 -0
  150. package/dist/components/ui/sheet/sheet-content.svelte.d.ts +37 -0
  151. package/dist/components/ui/sheet/sheet-description.svelte +17 -0
  152. package/dist/components/ui/sheet/sheet-description.svelte.d.ts +4 -0
  153. package/dist/components/ui/sheet/sheet-footer.svelte +20 -0
  154. package/dist/components/ui/sheet/sheet-footer.svelte.d.ts +5 -0
  155. package/dist/components/ui/sheet/sheet-header.svelte +20 -0
  156. package/dist/components/ui/sheet/sheet-header.svelte.d.ts +5 -0
  157. package/dist/components/ui/sheet/sheet-overlay.svelte +20 -0
  158. package/dist/components/ui/sheet/sheet-overlay.svelte.d.ts +4 -0
  159. package/dist/components/ui/sheet/sheet-portal.svelte +7 -0
  160. package/dist/components/ui/sheet/sheet-portal.svelte.d.ts +3 -0
  161. package/dist/components/ui/sheet/sheet-title.svelte +13 -0
  162. package/dist/components/ui/sheet/sheet-title.svelte.d.ts +4 -0
  163. package/dist/components/ui/sheet/sheet-trigger.svelte +7 -0
  164. package/dist/components/ui/sheet/sheet-trigger.svelte.d.ts +4 -0
  165. package/dist/components/ui/sheet/sheet.svelte +7 -0
  166. package/dist/components/ui/sheet/sheet.svelte.d.ts +3 -0
  167. package/dist/components/ui/switch/index.d.ts +2 -0
  168. package/dist/components/ui/switch/index.js +4 -0
  169. package/dist/components/ui/switch/switch.svelte +28 -0
  170. package/dist/components/ui/switch/switch.svelte.d.ts +8 -0
  171. package/dist/components/ui/tabs/index.d.ts +5 -0
  172. package/dist/components/ui/tabs/index.js +7 -0
  173. package/dist/components/ui/tabs/tabs-content.svelte +17 -0
  174. package/dist/components/ui/tabs/tabs-content.svelte.d.ts +4 -0
  175. package/dist/components/ui/tabs/tabs-list.svelte +16 -0
  176. package/dist/components/ui/tabs/tabs-list.svelte.d.ts +4 -0
  177. package/dist/components/ui/tabs/tabs-trigger.svelte +20 -0
  178. package/dist/components/ui/tabs/tabs-trigger.svelte.d.ts +4 -0
  179. package/dist/components/ui/tabs/tabs.svelte +19 -0
  180. package/dist/components/ui/tabs/tabs.svelte.d.ts +4 -0
  181. package/dist/components/ui/tooltip/index.d.ts +6 -0
  182. package/dist/components/ui/tooltip/index.js +8 -0
  183. package/dist/components/ui/tooltip/tooltip-content.svelte +52 -0
  184. package/dist/components/ui/tooltip/tooltip-content.svelte.d.ts +11 -0
  185. package/dist/components/ui/tooltip/tooltip-portal.svelte +7 -0
  186. package/dist/components/ui/tooltip/tooltip-portal.svelte.d.ts +4 -0
  187. package/dist/components/ui/tooltip/tooltip-provider.svelte +7 -0
  188. package/dist/components/ui/tooltip/tooltip-provider.svelte.d.ts +4 -0
  189. package/dist/components/ui/tooltip/tooltip-trigger.svelte +7 -0
  190. package/dist/components/ui/tooltip/tooltip-trigger.svelte.d.ts +4 -0
  191. package/dist/components/ui/tooltip/tooltip.svelte +7 -0
  192. package/dist/components/ui/tooltip/tooltip.svelte.d.ts +4 -0
  193. package/dist/components/viewers/ArchiveViewer.svelte +586 -0
  194. package/dist/components/viewers/ArchiveViewer.svelte.d.ts +7 -0
  195. package/dist/components/viewers/CLAUDE.md +60 -0
  196. package/dist/components/viewers/CodeViewer.svelte +553 -0
  197. package/dist/components/viewers/CodeViewer.svelte.d.ts +7 -0
  198. package/dist/components/viewers/CogViewer.svelte +1345 -0
  199. package/dist/components/viewers/CogViewer.svelte.d.ts +7 -0
  200. package/dist/components/viewers/CopcViewer.svelte +25 -0
  201. package/dist/components/viewers/CopcViewer.svelte.d.ts +7 -0
  202. package/dist/components/viewers/DatabaseViewer.svelte +169 -0
  203. package/dist/components/viewers/DatabaseViewer.svelte.d.ts +7 -0
  204. package/dist/components/viewers/FileInfo.svelte +174 -0
  205. package/dist/components/viewers/FileInfo.svelte.d.ts +10 -0
  206. package/dist/components/viewers/FlatGeobufViewer.svelte +755 -0
  207. package/dist/components/viewers/FlatGeobufViewer.svelte.d.ts +7 -0
  208. package/dist/components/viewers/GeoParquetMapViewer.svelte +278 -0
  209. package/dist/components/viewers/GeoParquetMapViewer.svelte.d.ts +17 -0
  210. package/dist/components/viewers/ImageViewer.svelte +233 -0
  211. package/dist/components/viewers/ImageViewer.svelte.d.ts +7 -0
  212. package/dist/components/viewers/LoadProgress.svelte +93 -0
  213. package/dist/components/viewers/LoadProgress.svelte.d.ts +15 -0
  214. package/dist/components/viewers/MapViewer.svelte +234 -0
  215. package/dist/components/viewers/MapViewer.svelte.d.ts +7 -0
  216. package/dist/components/viewers/MarkdownViewer.svelte +478 -0
  217. package/dist/components/viewers/MarkdownViewer.svelte.d.ts +7 -0
  218. package/dist/components/viewers/MediaViewer.svelte +121 -0
  219. package/dist/components/viewers/MediaViewer.svelte.d.ts +7 -0
  220. package/dist/components/viewers/ModelViewer.svelte +164 -0
  221. package/dist/components/viewers/ModelViewer.svelte.d.ts +7 -0
  222. package/dist/components/viewers/NotebookViewer.svelte +389 -0
  223. package/dist/components/viewers/NotebookViewer.svelte.d.ts +7 -0
  224. package/dist/components/viewers/PdfViewer.svelte +278 -0
  225. package/dist/components/viewers/PdfViewer.svelte.d.ts +7 -0
  226. package/dist/components/viewers/PmtilesViewer.svelte +191 -0
  227. package/dist/components/viewers/PmtilesViewer.svelte.d.ts +7 -0
  228. package/dist/components/viewers/QueryHistoryPanel.svelte +159 -0
  229. package/dist/components/viewers/QueryHistoryPanel.svelte.d.ts +8 -0
  230. package/dist/components/viewers/RawViewer.svelte +117 -0
  231. package/dist/components/viewers/RawViewer.svelte.d.ts +7 -0
  232. package/dist/components/viewers/StacMapViewer.svelte +20 -0
  233. package/dist/components/viewers/StacMapViewer.svelte.d.ts +7 -0
  234. package/dist/components/viewers/StyleEditorOverlay.svelte +27 -0
  235. package/dist/components/viewers/StyleEditorOverlay.svelte.d.ts +7 -0
  236. package/dist/components/viewers/TableGrid.svelte +355 -0
  237. package/dist/components/viewers/TableGrid.svelte.d.ts +12 -0
  238. package/dist/components/viewers/TableStatusBar.svelte +92 -0
  239. package/dist/components/viewers/TableStatusBar.svelte.d.ts +11 -0
  240. package/dist/components/viewers/TableToolbar.svelte +382 -0
  241. package/dist/components/viewers/TableToolbar.svelte.d.ts +25 -0
  242. package/dist/components/viewers/TableViewer.svelte +923 -0
  243. package/dist/components/viewers/TableViewer.svelte.d.ts +7 -0
  244. package/dist/components/viewers/ViewerRouter.svelte +70 -0
  245. package/dist/components/viewers/ViewerRouter.svelte.d.ts +7 -0
  246. package/dist/components/viewers/ZarrMapViewer.svelte +288 -0
  247. package/dist/components/viewers/ZarrMapViewer.svelte.d.ts +17 -0
  248. package/dist/components/viewers/ZarrViewer.svelte +256 -0
  249. package/dist/components/viewers/ZarrViewer.svelte.d.ts +7 -0
  250. package/dist/components/viewers/map/AttributeTable.svelte +52 -0
  251. package/dist/components/viewers/map/AttributeTable.svelte.d.ts +8 -0
  252. package/dist/components/viewers/map/MapContainer.svelte +158 -0
  253. package/dist/components/viewers/map/MapContainer.svelte.d.ts +12 -0
  254. package/dist/components/viewers/pmtiles/PmtilesArchiveView.svelte +389 -0
  255. package/dist/components/viewers/pmtiles/PmtilesArchiveView.svelte.d.ts +10 -0
  256. package/dist/components/viewers/pmtiles/PmtilesMapView.svelte +332 -0
  257. package/dist/components/viewers/pmtiles/PmtilesMapView.svelte.d.ts +11 -0
  258. package/dist/components/viewers/pmtiles/PmtilesTileInspector.svelte +373 -0
  259. package/dist/components/viewers/pmtiles/PmtilesTileInspector.svelte.d.ts +12 -0
  260. package/dist/components/viewers/pmtiles/SvgTileRenderer.svelte +112 -0
  261. package/dist/components/viewers/pmtiles/SvgTileRenderer.svelte.d.ts +10 -0
  262. package/dist/file-icons/CLAUDE.md +21 -0
  263. package/dist/file-icons/FileTypeIcon.svelte +74 -0
  264. package/dist/file-icons/FileTypeIcon.svelte.d.ts +9 -0
  265. package/dist/file-icons/index.d.ts +56 -0
  266. package/dist/file-icons/index.js +1070 -0
  267. package/dist/i18n/CLAUDE.md +19 -0
  268. package/dist/i18n/ar.d.ts +1 -0
  269. package/dist/i18n/ar.js +404 -0
  270. package/dist/i18n/en.d.ts +1 -0
  271. package/dist/i18n/en.js +404 -0
  272. package/dist/i18n/index.svelte.d.ts +9 -0
  273. package/dist/i18n/index.svelte.js +27 -0
  274. package/dist/index.d.ts +20 -0
  275. package/dist/index.js +13 -0
  276. package/dist/query/CLAUDE.md +22 -0
  277. package/dist/query/engine.d.ts +56 -0
  278. package/dist/query/engine.js +6 -0
  279. package/dist/query/index.d.ts +4 -0
  280. package/dist/query/index.js +19 -0
  281. package/dist/query/wasm.d.ts +20 -0
  282. package/dist/query/wasm.js +890 -0
  283. package/dist/storage/CLAUDE.md +23 -0
  284. package/dist/storage/adapter.d.ts +21 -0
  285. package/dist/storage/adapter.js +1 -0
  286. package/dist/storage/browser-azure.d.ts +25 -0
  287. package/dist/storage/browser-azure.js +271 -0
  288. package/dist/storage/browser-cloud.d.ts +32 -0
  289. package/dist/storage/browser-cloud.js +293 -0
  290. package/dist/storage/index.d.ts +11 -0
  291. package/dist/storage/index.js +37 -0
  292. package/dist/storage/url-adapter.d.ts +19 -0
  293. package/dist/storage/url-adapter.js +51 -0
  294. package/dist/stores/CLAUDE.md +29 -0
  295. package/dist/stores/browser.svelte.d.ts +28 -0
  296. package/dist/stores/browser.svelte.js +160 -0
  297. package/dist/stores/connections.svelte.d.ts +56 -0
  298. package/dist/stores/connections.svelte.js +272 -0
  299. package/dist/stores/credentials.svelte.d.ts +56 -0
  300. package/dist/stores/credentials.svelte.js +79 -0
  301. package/dist/stores/files.svelte.d.ts +20 -0
  302. package/dist/stores/files.svelte.js +76 -0
  303. package/dist/stores/query-history.svelte.d.ts +16 -0
  304. package/dist/stores/query-history.svelte.js +57 -0
  305. package/dist/stores/safelock.svelte.d.ts +8 -0
  306. package/dist/stores/safelock.svelte.js +52 -0
  307. package/dist/stores/settings.svelte.d.ts +11 -0
  308. package/dist/stores/settings.svelte.js +101 -0
  309. package/dist/stores/tab-resources.svelte.d.ts +25 -0
  310. package/dist/stores/tab-resources.svelte.js +61 -0
  311. package/dist/stores/tabs.svelte.d.ts +17 -0
  312. package/dist/stores/tabs.svelte.js +110 -0
  313. package/dist/types/notebookjs.d.ts +14 -0
  314. package/dist/types.d.ts +47 -0
  315. package/dist/types.js +1 -0
  316. package/dist/utils/CLAUDE.md +54 -0
  317. package/dist/utils/analytics.d.ts +10 -0
  318. package/dist/utils/analytics.js +38 -0
  319. package/dist/utils/archive.d.ts +70 -0
  320. package/dist/utils/archive.js +333 -0
  321. package/dist/utils/column-types.d.ts +5 -0
  322. package/dist/utils/column-types.js +137 -0
  323. package/dist/utils/deck.d.ts +98 -0
  324. package/dist/utils/deck.js +208 -0
  325. package/dist/utils/evidence-context.d.ts +22 -0
  326. package/dist/utils/evidence-context.js +56 -0
  327. package/dist/utils/export.d.ts +2 -0
  328. package/dist/utils/export.js +51 -0
  329. package/dist/utils/format.d.ts +14 -0
  330. package/dist/utils/format.js +56 -0
  331. package/dist/utils/geoarrow.d.ts +32 -0
  332. package/dist/utils/geoarrow.js +672 -0
  333. package/dist/utils/hex.d.ts +10 -0
  334. package/dist/utils/hex.js +27 -0
  335. package/dist/utils/host-detection.d.ts +23 -0
  336. package/dist/utils/host-detection.js +289 -0
  337. package/dist/utils/map-selection.d.ts +12 -0
  338. package/dist/utils/map-selection.js +45 -0
  339. package/dist/utils/markdown-sql.d.ts +30 -0
  340. package/dist/utils/markdown-sql.js +73 -0
  341. package/dist/utils/markdown.d.ts +18 -0
  342. package/dist/utils/markdown.js +146 -0
  343. package/dist/utils/model3d.d.ts +13 -0
  344. package/dist/utils/model3d.js +62 -0
  345. package/dist/utils/parquet-metadata.d.ts +58 -0
  346. package/dist/utils/parquet-metadata.js +228 -0
  347. package/dist/utils/pdf.d.ts +8 -0
  348. package/dist/utils/pdf.js +28 -0
  349. package/dist/utils/pmtiles-tile.d.ts +38 -0
  350. package/dist/utils/pmtiles-tile.js +64 -0
  351. package/dist/utils/pmtiles.d.ts +46 -0
  352. package/dist/utils/pmtiles.js +135 -0
  353. package/dist/utils/shiki.d.ts +8 -0
  354. package/dist/utils/shiki.js +98 -0
  355. package/dist/utils/storage-url.d.ts +64 -0
  356. package/dist/utils/storage-url.js +374 -0
  357. package/dist/utils/url-state.d.ts +40 -0
  358. package/dist/utils/url-state.js +113 -0
  359. package/dist/utils/url.d.ts +27 -0
  360. package/dist/utils/url.js +115 -0
  361. package/dist/utils/wkb.d.ts +43 -0
  362. package/dist/utils/wkb.js +345 -0
  363. package/dist/utils/zarr.d.ts +39 -0
  364. package/dist/utils/zarr.js +204 -0
  365. package/dist/utils.d.ts +12 -0
  366. package/dist/utils.js +5 -0
  367. package/package.json +203 -0
@@ -0,0 +1,278 @@
1
+ <script lang="ts">
2
+ import ChevronLeftIcon from '@lucide/svelte/icons/chevron-left';
3
+ import ChevronRightIcon from '@lucide/svelte/icons/chevron-right';
4
+ import EllipsisVerticalIcon from '@lucide/svelte/icons/ellipsis-vertical';
5
+ import MinusIcon from '@lucide/svelte/icons/minus';
6
+ import PlusIcon from '@lucide/svelte/icons/plus';
7
+ import type { PDFDocumentLoadingTask, PDFDocumentProxy } from 'pdfjs-dist';
8
+ import { onDestroy, untrack } from 'svelte';
9
+ import { Badge } from '../ui/badge/index.js';
10
+ import { Button } from '../ui/button/index.js';
11
+ import * as DropdownMenu from '../ui/dropdown-menu/index.js';
12
+ import { Separator } from '../ui/separator/index.js';
13
+ import { t } from '../../i18n/index.svelte.js';
14
+ import { getAdapter } from '../../storage/index.js';
15
+ import { tabResources } from '../../stores/tab-resources.svelte.js';
16
+ import type { Tab } from '../../types';
17
+ import { loadPdfDocument, loadPdfFromUrl } from '../../utils/pdf';
18
+ import { buildHttpsUrl, canStreamDirectly } from '../../utils/url.js';
19
+
20
+ const LOAD_TIMEOUT_MS = 20_000;
21
+
22
+ let { tab }: { tab: Tab } = $props();
23
+
24
+ let abortController: AbortController | null = null;
25
+ let canvasEl: HTMLCanvasElement | undefined = $state();
26
+ let pdfDoc = $state.raw<PDFDocumentProxy | null>(null);
27
+ let currentPage = $state(1);
28
+ let totalPages = $state(0);
29
+ let scale = $state(1.5);
30
+ let loading = $state(true);
31
+ let error = $state<string | null>(null);
32
+ let renderGeneration = 0;
33
+ let activeTask: PDFDocumentLoadingTask | null = null;
34
+
35
+ $effect(() => {
36
+ if (!tab) return;
37
+ // untrack prevents tracking pdfDoc reads inside loadPdf (pdfDoc?.destroy())
38
+ // — otherwise setting pdfDoc after load re-triggers this effect → infinite loop
39
+ untrack(() => loadPdf());
40
+ });
41
+
42
+ $effect(() => {
43
+ if (!tab) return;
44
+ // Read all reactive deps unconditionally to ensure tracking
45
+ const doc = pdfDoc;
46
+ const canvas = canvasEl;
47
+ const page = currentPage;
48
+ const s = scale;
49
+ if (doc && canvas) renderPage(doc, canvas, page, s);
50
+ });
51
+
52
+ function cancelActiveTask() {
53
+ if (activeTask) {
54
+ activeTask.destroy();
55
+ activeTask = null;
56
+ }
57
+ }
58
+
59
+ async function loadPdf() {
60
+ abortController?.abort();
61
+ abortController = new AbortController();
62
+ const { signal } = abortController;
63
+
64
+ loading = true;
65
+ error = null;
66
+ cancelActiveTask();
67
+ pdfDoc?.destroy();
68
+ pdfDoc = null;
69
+
70
+ try {
71
+ const doc = await loadPdfData(signal);
72
+ pdfDoc = doc;
73
+ totalPages = doc.numPages;
74
+ currentPage = 1;
75
+ } catch (err: any) {
76
+ // Ignore cancellation errors (destroyed loading task) and aborts
77
+ if (err instanceof DOMException && err.name === 'AbortError') return;
78
+ if (err?.name === 'PasswordException' || err?.message?.includes('destroy')) return;
79
+ error = err instanceof Error ? err.message : String(err);
80
+ } finally {
81
+ loading = false;
82
+ }
83
+ }
84
+
85
+ async function loadPdfData(signal: AbortSignal): Promise<PDFDocumentProxy> {
86
+ // Try streaming from URL first (range requests for progressive page rendering)
87
+ if (canStreamDirectly(tab)) {
88
+ try {
89
+ const task = await loadPdfFromUrl(buildHttpsUrl(tab));
90
+ activeTask = task;
91
+ return await withTimeout(task.promise, LOAD_TIMEOUT_MS);
92
+ } catch {
93
+ // CORS, network, or timeout error — fall through to adapter download
94
+ cancelActiveTask();
95
+ }
96
+ }
97
+ // Fall back to full download via storage adapter
98
+ const adapter = getAdapter(tab.source, tab.connectionId);
99
+ const data = await adapter.read(tab.path, undefined, undefined, signal);
100
+ const task = await loadPdfDocument(data);
101
+ activeTask = task;
102
+ return await withTimeout(task.promise, LOAD_TIMEOUT_MS);
103
+ }
104
+
105
+ function withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {
106
+ return Promise.race([
107
+ promise,
108
+ new Promise<never>((_, reject) =>
109
+ setTimeout(() => reject(new Error('PDF loading timed out')), ms)
110
+ )
111
+ ]);
112
+ }
113
+
114
+ async function renderPage(
115
+ doc: PDFDocumentProxy,
116
+ canvas: HTMLCanvasElement,
117
+ pageNum: number,
118
+ currentScale: number
119
+ ) {
120
+ const gen = ++renderGeneration;
121
+
122
+ try {
123
+ const page = await doc.getPage(pageNum);
124
+ // Stale or unmounted — skip
125
+ if (gen !== renderGeneration || !canvasEl) return;
126
+
127
+ const viewport = page.getViewport({ scale: currentScale });
128
+ canvas.width = viewport.width;
129
+ canvas.height = viewport.height;
130
+
131
+ const ctx = canvas.getContext('2d');
132
+ if (!ctx) return;
133
+
134
+ await page.render({ canvasContext: ctx, viewport, canvas } as any).promise;
135
+ } catch (err) {
136
+ if (gen === renderGeneration) {
137
+ error = err instanceof Error ? err.message : String(err);
138
+ }
139
+ }
140
+ }
141
+
142
+ function prevPage() {
143
+ if (currentPage > 1) currentPage--;
144
+ }
145
+
146
+ function nextPage() {
147
+ if (currentPage < totalPages) currentPage++;
148
+ }
149
+
150
+ function zoomIn() {
151
+ scale = Math.min(scale + 0.25, 5);
152
+ }
153
+
154
+ function zoomOut() {
155
+ scale = Math.max(scale - 0.25, 0.5);
156
+ }
157
+
158
+ function cleanup() {
159
+ abortController?.abort();
160
+ abortController = null;
161
+ cancelActiveTask();
162
+ pdfDoc?.destroy();
163
+ pdfDoc = null;
164
+ }
165
+
166
+ $effect(() => {
167
+ const id = tab.id;
168
+ const unregister = tabResources.register(id, cleanup);
169
+ return unregister;
170
+ });
171
+ onDestroy(cleanup);
172
+ </script>
173
+
174
+ <div class="flex h-full flex-col">
175
+ <div
176
+ class="flex items-center gap-1 border-b border-zinc-200 px-2 py-1.5 sm:gap-2 sm:px-4 dark:border-zinc-800"
177
+ >
178
+ <span
179
+ class="truncate max-w-[120px] text-sm font-medium text-zinc-700 sm:max-w-none dark:text-zinc-300"
180
+ >{tab.name}</span
181
+ >
182
+ <Badge variant="secondary">{t("pdf.badge")}</Badge>
183
+
184
+ {#if totalPages > 0}
185
+ <div class="ms-auto flex items-center gap-1 sm:gap-2">
186
+ <!-- Pagination (always visible) -->
187
+ <Button
188
+ variant="ghost"
189
+ size="sm"
190
+ class="h-7 px-1.5"
191
+ onclick={prevPage}
192
+ disabled={currentPage <= 1}
193
+ >
194
+ <ChevronLeftIcon class="size-3.5" />
195
+ <span class="hidden sm:inline">{t("pdf.prev")}</span>
196
+ </Button>
197
+ <span class="text-xs text-zinc-500 dark:text-zinc-400">
198
+ {currentPage} / {totalPages}
199
+ </span>
200
+ <Button
201
+ variant="ghost"
202
+ size="sm"
203
+ class="h-7 px-1.5"
204
+ onclick={nextPage}
205
+ disabled={currentPage >= totalPages}
206
+ >
207
+ <span class="hidden sm:inline">{t("pdf.next")}</span>
208
+ <ChevronRightIcon class="size-3.5" />
209
+ </Button>
210
+
211
+ <!-- Zoom controls — desktop only -->
212
+ <div class="hidden items-center gap-1 sm:flex">
213
+ <Separator orientation="vertical" class="!h-4" />
214
+ <Button
215
+ variant="ghost"
216
+ size="sm"
217
+ class="h-7 px-1.5"
218
+ onclick={zoomOut}
219
+ title={t("pdf.zoomOut")}
220
+ >
221
+ <MinusIcon class="size-3.5" />
222
+ </Button>
223
+ <span class="text-xs text-zinc-500 dark:text-zinc-400">
224
+ {Math.round(scale * 100)}%
225
+ </span>
226
+ <Button
227
+ variant="ghost"
228
+ size="sm"
229
+ class="h-7 px-1.5"
230
+ onclick={zoomIn}
231
+ title={t("pdf.zoomIn")}
232
+ >
233
+ <PlusIcon class="size-3.5" />
234
+ </Button>
235
+ </div>
236
+
237
+ <!-- Mobile overflow menu -->
238
+ <div class="flex sm:hidden">
239
+ <DropdownMenu.Root>
240
+ <DropdownMenu.Trigger
241
+ class="rounded p-1 text-zinc-400 hover:bg-zinc-100 dark:hover:bg-zinc-800"
242
+ >
243
+ <EllipsisVerticalIcon class="size-4" />
244
+ </DropdownMenu.Trigger>
245
+ <DropdownMenu.Content align="end" class="w-44">
246
+ <DropdownMenu.Item onclick={zoomIn}>
247
+ {t("pdf.zoomIn")}
248
+ </DropdownMenu.Item>
249
+ <DropdownMenu.Item onclick={zoomOut}>
250
+ {t("pdf.zoomOut")}
251
+ </DropdownMenu.Item>
252
+ <DropdownMenu.Separator />
253
+ <DropdownMenu.Item disabled>
254
+ {t("pdf.zoom")}: {Math.round(scale * 100)}%
255
+ </DropdownMenu.Item>
256
+ </DropdownMenu.Content>
257
+ </DropdownMenu.Root>
258
+ </div>
259
+ </div>
260
+ {/if}
261
+ </div>
262
+
263
+ <div
264
+ class="flex flex-1 items-start justify-center overflow-auto bg-zinc-200 p-4 dark:bg-zinc-800"
265
+ >
266
+ {#if loading}
267
+ <div class="flex h-full items-center justify-center">
268
+ <p class="text-sm text-zinc-400">{t("pdf.loading")}</p>
269
+ </div>
270
+ {:else if error}
271
+ <div class="flex h-full items-center justify-center">
272
+ <p class="text-sm text-red-400">{error}</p>
273
+ </div>
274
+ {:else}
275
+ <canvas bind:this={canvasEl} class="shadow-lg"></canvas>
276
+ {/if}
277
+ </div>
278
+ </div>
@@ -0,0 +1,7 @@
1
+ import type { Tab } from '../../types';
2
+ type $$ComponentProps = {
3
+ tab: Tab;
4
+ };
5
+ declare const PdfViewer: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type PdfViewer = ReturnType<typeof PdfViewer>;
7
+ export default PdfViewer;
@@ -0,0 +1,191 @@
1
+ <script lang="ts">
2
+ import ArchiveIcon from '@lucide/svelte/icons/archive';
3
+ import GridIcon from '@lucide/svelte/icons/grid-3x3';
4
+ import MapIcon from '@lucide/svelte/icons/map';
5
+ import type { PMTiles } from 'pmtiles';
6
+ import { onDestroy, untrack } from 'svelte';
7
+ import { Badge } from '../ui/badge/index.js';
8
+ import { Button } from '../ui/button/index.js';
9
+ import { Separator } from '../ui/separator/index.js';
10
+ import { t } from '../../i18n/index.svelte.js';
11
+ import { tabResources } from '../../stores/tab-resources.svelte.js';
12
+ import type { Tab } from '../../types';
13
+ import { loadPmtiles, type PmtilesMetadata } from '../../utils/pmtiles';
14
+ import { buildHttpsUrl } from '../../utils/url.js';
15
+ import { getUrlView, updateUrlView } from '../../utils/url-state.js';
16
+
17
+ let { tab }: { tab: Tab } = $props();
18
+
19
+ type ViewMode = 'map' | 'archive' | 'inspector';
20
+
21
+ let loading = $state(true);
22
+ let error = $state<string | null>(null);
23
+ let metadata = $state<PmtilesMetadata | null>(null);
24
+ let pmtilesInstance = $state<PMTiles | null>(null);
25
+ let pmtilesUrl = $state('');
26
+
27
+ // Read initial view from URL hash
28
+ const urlView = getUrlView();
29
+ let viewMode = $state<ViewMode>(
30
+ urlView === 'archive' ? 'archive' : urlView === 'inspector' ? 'inspector' : 'map'
31
+ );
32
+
33
+ // Tile inspector initial coordinates (set when navigating from archive)
34
+ let inspectorZ = $state<number | undefined>();
35
+ let inspectorX = $state<number | undefined>();
36
+ let inspectorY = $state<number | undefined>();
37
+
38
+ function setViewMode(mode: ViewMode) {
39
+ viewMode = mode;
40
+ updateUrlView(mode);
41
+ }
42
+
43
+ function openInInspector(z: number, x: number, y: number) {
44
+ inspectorZ = z;
45
+ inspectorX = x;
46
+ inspectorY = y;
47
+ setViewMode('inspector');
48
+ }
49
+
50
+ function cleanup() {
51
+ pmtilesInstance = null;
52
+ metadata = null;
53
+ pmtilesUrl = '';
54
+ }
55
+
56
+ $effect(() => {
57
+ const id = tab.id;
58
+ const unregister = tabResources.register(id, cleanup);
59
+ return unregister;
60
+ });
61
+ onDestroy(cleanup);
62
+
63
+ $effect(() => {
64
+ if (!tab) return;
65
+ const _tabId = tab.id;
66
+ untrack(() => {
67
+ load();
68
+ });
69
+ });
70
+
71
+ async function load() {
72
+ loading = true;
73
+ error = null;
74
+
75
+ try {
76
+ pmtilesUrl = buildHttpsUrl(tab);
77
+ const result = await loadPmtiles(pmtilesUrl);
78
+ pmtilesInstance = result.pmtiles;
79
+ metadata = result.metadata;
80
+ } catch (err) {
81
+ error = err instanceof Error ? err.message : String(err);
82
+ } finally {
83
+ loading = false;
84
+ }
85
+ }
86
+
87
+ const fileName = $derived(tab.path.split('/').pop() ?? 'pmtiles');
88
+ </script>
89
+
90
+ <div class="flex h-full flex-col">
91
+ <!-- Toolbar -->
92
+ {#if !loading && !error && metadata}
93
+ <div
94
+ class="flex items-center gap-1 border-b border-zinc-200 px-2 py-1.5 sm:gap-2 sm:px-4 dark:border-zinc-800"
95
+ >
96
+ <!-- File info -->
97
+ <span
98
+ class="max-w-[100px] truncate text-sm font-medium text-zinc-700 sm:max-w-none dark:text-zinc-300"
99
+ >
100
+ {fileName}
101
+ </span>
102
+ <Badge variant="outline" class="hidden text-[10px] sm:inline-flex">
103
+ {metadata.formatLabel}
104
+ </Badge>
105
+ <span class="hidden text-xs text-zinc-400 sm:inline dark:text-zinc-500">
106
+ z{metadata.minZoom}-{metadata.maxZoom} · {metadata.numAddressedTiles.toLocaleString()} tiles
107
+ </span>
108
+
109
+ <!-- View mode buttons -->
110
+ <div class="ms-auto flex items-center gap-1">
111
+ <Button
112
+ variant={viewMode === 'map' ? 'default' : 'outline'}
113
+ size="sm"
114
+ class="h-7 gap-1 px-2 text-xs {viewMode !== 'map'
115
+ ? 'border-zinc-300 text-zinc-600 hover:bg-zinc-50 dark:border-zinc-700 dark:text-zinc-400 dark:hover:bg-zinc-900'
116
+ : ''}"
117
+ onclick={() => setViewMode('map')}
118
+ >
119
+ <MapIcon class="size-3" />
120
+ <span class="hidden sm:inline">{t('pmtiles.mapView')}</span>
121
+ </Button>
122
+
123
+ <Button
124
+ variant={viewMode === 'archive' ? 'default' : 'outline'}
125
+ size="sm"
126
+ class="h-7 gap-1 px-2 text-xs {viewMode !== 'archive'
127
+ ? 'border-zinc-300 text-zinc-600 hover:bg-zinc-50 dark:border-zinc-700 dark:text-zinc-400 dark:hover:bg-zinc-900'
128
+ : ''}"
129
+ onclick={() => setViewMode('archive')}
130
+ >
131
+ <ArchiveIcon class="size-3" />
132
+ <span class="hidden sm:inline">{t('pmtiles.archiveView')}</span>
133
+ </Button>
134
+
135
+ <Button
136
+ variant={viewMode === 'inspector' ? 'default' : 'outline'}
137
+ size="sm"
138
+ class="h-7 gap-1 px-2 text-xs {viewMode !== 'inspector'
139
+ ? 'border-zinc-300 text-zinc-600 hover:bg-zinc-50 dark:border-zinc-700 dark:text-zinc-400 dark:hover:bg-zinc-900'
140
+ : ''}"
141
+ onclick={() => setViewMode('inspector')}
142
+ >
143
+ <GridIcon class="size-3" />
144
+ <span class="hidden sm:inline">{t('pmtiles.inspectorView')}</span>
145
+ </Button>
146
+ </div>
147
+ </div>
148
+ {/if}
149
+
150
+ <!-- Content area -->
151
+ <div class="min-h-0 flex-1 overflow-hidden">
152
+ {#if loading}
153
+ <div class="flex h-full items-center justify-center">
154
+ <p class="text-sm text-zinc-400">{t('map.loadingPmtiles')}</p>
155
+ </div>
156
+ {:else if error}
157
+ <div class="flex h-full items-center justify-center">
158
+ <p class="text-sm text-red-400">{error}</p>
159
+ </div>
160
+ {:else if metadata && pmtilesInstance}
161
+ {#if viewMode === 'map'}
162
+ {#await import('./pmtiles/PmtilesMapView.svelte') then mod}
163
+ <mod.default
164
+ {tab}
165
+ {metadata}
166
+ {pmtilesUrl}
167
+ onOpenInspector={openInInspector}
168
+ />
169
+ {/await}
170
+ {:else if viewMode === 'archive'}
171
+ {#await import('./pmtiles/PmtilesArchiveView.svelte') then mod}
172
+ <mod.default
173
+ {metadata}
174
+ pmtiles={pmtilesInstance}
175
+ onOpenInspector={openInInspector}
176
+ />
177
+ {/await}
178
+ {:else if viewMode === 'inspector'}
179
+ {#await import('./pmtiles/PmtilesTileInspector.svelte') then mod}
180
+ <mod.default
181
+ {metadata}
182
+ pmtiles={pmtilesInstance}
183
+ initialZ={inspectorZ}
184
+ initialX={inspectorX}
185
+ initialY={inspectorY}
186
+ />
187
+ {/await}
188
+ {/if}
189
+ {/if}
190
+ </div>
191
+ </div>
@@ -0,0 +1,7 @@
1
+ import type { Tab } from '../../types';
2
+ type $$ComponentProps = {
3
+ tab: Tab;
4
+ };
5
+ declare const PmtilesViewer: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type PmtilesViewer = ReturnType<typeof PmtilesViewer>;
7
+ export default PmtilesViewer;
@@ -0,0 +1,159 @@
1
+ <script lang="ts">
2
+ import ClockIcon from '@lucide/svelte/icons/clock';
3
+ import SearchIcon from '@lucide/svelte/icons/search';
4
+ import TrashIcon from '@lucide/svelte/icons/trash-2';
5
+ import XIcon from '@lucide/svelte/icons/x';
6
+ import { ScrollArea } from '../ui/scroll-area/index.js';
7
+ import { t } from '../../i18n/index.svelte.js';
8
+ import type { QueryHistoryEntry } from '../../stores/query-history.svelte.js';
9
+ import { queryHistory } from '../../stores/query-history.svelte.js';
10
+
11
+ let {
12
+ visible = false,
13
+ onSelect,
14
+ onClose
15
+ }: {
16
+ visible?: boolean;
17
+ onSelect?: (sql: string) => void;
18
+ onClose?: () => void;
19
+ } = $props();
20
+
21
+ let searchQuery = $state('');
22
+
23
+ const filteredEntries = $derived(
24
+ searchQuery ? queryHistory.search(searchQuery) : queryHistory.entries
25
+ );
26
+
27
+ function formatTime(timestamp: number): string {
28
+ const date = new Date(timestamp);
29
+ const now = new Date();
30
+ const diffMs = now.getTime() - date.getTime();
31
+ const diffMins = Math.floor(diffMs / 60000);
32
+
33
+ if (diffMins < 1) return t('queryHistory.justNow');
34
+ if (diffMins < 60) return t('queryHistory.minsAgo', { n: diffMins });
35
+ const diffHours = Math.floor(diffMins / 60);
36
+ if (diffHours < 24) return t('queryHistory.hoursAgo', { n: diffHours });
37
+ const diffDays = Math.floor(diffHours / 24);
38
+ if (diffDays < 7) return t('queryHistory.daysAgo', { n: diffDays });
39
+
40
+ return date.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });
41
+ }
42
+
43
+ function truncateSql(sql: string, maxLen = 120): string {
44
+ const oneLine = sql.replace(/\s+/g, ' ').trim();
45
+ if (oneLine.length <= maxLen) return oneLine;
46
+ return `${oneLine.slice(0, maxLen)}...`;
47
+ }
48
+ </script>
49
+
50
+ {#if visible}
51
+ <!-- Mobile: absolute overlay; Desktop: flex sidebar -->
52
+ <div
53
+ class="absolute inset-y-0 end-0 z-10 flex w-72 flex-col overflow-hidden border-s border-zinc-200 bg-zinc-50 sm:relative sm:z-auto sm:shrink-0 dark:border-zinc-800 dark:bg-zinc-900"
54
+ >
55
+ <!-- Header -->
56
+ <div
57
+ class="flex items-center justify-between border-b border-zinc-200 px-3 py-2 dark:border-zinc-800"
58
+ >
59
+ <div class="flex items-center gap-1.5">
60
+ <ClockIcon class="size-3.5 text-zinc-500" />
61
+ <h3 class="text-xs font-medium text-zinc-500 dark:text-zinc-400">
62
+ {t('queryHistory.title')}
63
+ </h3>
64
+ </div>
65
+ <div class="flex items-center gap-2">
66
+ {#if queryHistory.entries.length > 0}
67
+ <button
68
+ class="text-[10px] text-zinc-400 hover:text-red-500 dark:hover:text-red-400"
69
+ onclick={() => queryHistory.clear()}
70
+ >
71
+ {t('queryHistory.clearAll')}
72
+ </button>
73
+ {/if}
74
+ {#if onClose}
75
+ <button
76
+ class="rounded p-0.5 text-zinc-400 hover:bg-zinc-200 hover:text-zinc-600 sm:hidden dark:hover:bg-zinc-700 dark:hover:text-zinc-300"
77
+ onclick={onClose}
78
+ >
79
+ <XIcon class="size-3.5" />
80
+ </button>
81
+ {/if}
82
+ </div>
83
+ </div>
84
+
85
+ <!-- Search -->
86
+ <div class="border-b border-zinc-200 px-3 py-1.5 dark:border-zinc-800">
87
+ <div
88
+ class="flex items-center gap-1.5 rounded border border-zinc-200 bg-white px-2 py-1 dark:border-zinc-700 dark:bg-zinc-800"
89
+ >
90
+ <SearchIcon class="size-3 shrink-0 text-zinc-400" />
91
+ <input
92
+ type="text"
93
+ class="w-full bg-transparent text-xs outline-none placeholder:text-zinc-400"
94
+ placeholder={t('queryHistory.searchPlaceholder')}
95
+ bind:value={searchQuery}
96
+ />
97
+ {#if searchQuery}
98
+ <button
99
+ class="shrink-0 text-zinc-400 hover:text-zinc-600"
100
+ onclick={() => {
101
+ searchQuery = '';
102
+ }}
103
+ >
104
+ <XIcon class="size-3" />
105
+ </button>
106
+ {/if}
107
+ </div>
108
+ </div>
109
+
110
+ <!-- Entries -->
111
+ <ScrollArea class="flex-1">
112
+ {#if filteredEntries.length === 0}
113
+ <div class="px-3 py-6 text-center text-xs text-zinc-400">
114
+ {searchQuery ? 'No matching queries' : 'No query history yet'}
115
+ </div>
116
+ {:else}
117
+ <div class="divide-y divide-zinc-100 dark:divide-zinc-800">
118
+ {#each filteredEntries as entry (entry.id)}
119
+ <div
120
+ class="group flex w-full cursor-pointer flex-col gap-0.5 px-3 py-2 text-start hover:bg-zinc-100 dark:hover:bg-zinc-800"
121
+ role="button"
122
+ tabindex="0"
123
+ onclick={() => onSelect?.(entry.sql)}
124
+ onkeydown={(e) => {
125
+ if (e.key === 'Enter') onSelect?.(entry.sql);
126
+ }}
127
+ >
128
+ <div
129
+ class="font-mono text-[11px] leading-snug text-zinc-600 dark:text-zinc-300"
130
+ >
131
+ {truncateSql(entry.sql)}
132
+ </div>
133
+ <div class="flex items-center gap-2 text-[10px] text-zinc-400">
134
+ <span>{formatTime(entry.timestamp)}</span>
135
+ <span>{entry.durationMs}ms</span>
136
+ {#if entry.rowCount > 0}
137
+ <span>{entry.rowCount.toLocaleString()} rows</span>
138
+ {/if}
139
+ {#if entry.error}
140
+ <span class="text-red-400">error</span>
141
+ {/if}
142
+ <button
143
+ class="ms-auto opacity-0 group-hover:opacity-100"
144
+ onclick={(e) => {
145
+ e.stopPropagation();
146
+ queryHistory.remove(entry.id);
147
+ }}
148
+ title="Remove"
149
+ >
150
+ <TrashIcon class="size-3 text-zinc-400 hover:text-red-500" />
151
+ </button>
152
+ </div>
153
+ </div>
154
+ {/each}
155
+ </div>
156
+ {/if}
157
+ </ScrollArea>
158
+ </div>
159
+ {/if}
@@ -0,0 +1,8 @@
1
+ type $$ComponentProps = {
2
+ visible?: boolean;
3
+ onSelect?: (sql: string) => void;
4
+ onClose?: () => void;
5
+ };
6
+ declare const QueryHistoryPanel: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type QueryHistoryPanel = ReturnType<typeof QueryHistoryPanel>;
8
+ export default QueryHistoryPanel;