@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.
- package/LICENSE +396 -0
- package/README.md +114 -0
- package/dist/assets/favicon.svg +17 -0
- package/dist/components/CLAUDE.md +44 -0
- package/dist/components/browser/Breadcrumb.svelte +50 -0
- package/dist/components/browser/Breadcrumb.svelte.d.ts +7 -0
- package/dist/components/browser/CreateFolderDialog.svelte +98 -0
- package/dist/components/browser/CreateFolderDialog.svelte.d.ts +6 -0
- package/dist/components/browser/DeleteConfirmDialog.svelte +90 -0
- package/dist/components/browser/DeleteConfirmDialog.svelte.d.ts +8 -0
- package/dist/components/browser/DropZone.svelte +83 -0
- package/dist/components/browser/DropZone.svelte.d.ts +7 -0
- package/dist/components/browser/FileBrowser.svelte +229 -0
- package/dist/components/browser/FileBrowser.svelte.d.ts +3 -0
- package/dist/components/browser/FileRow.svelte +112 -0
- package/dist/components/browser/FileRow.svelte.d.ts +9 -0
- package/dist/components/browser/FileTreeSidebar.svelte +559 -0
- package/dist/components/browser/FileTreeSidebar.svelte.d.ts +8 -0
- package/dist/components/browser/RenameDialog.svelte +101 -0
- package/dist/components/browser/RenameDialog.svelte.d.ts +8 -0
- package/dist/components/browser/SearchBar.svelte +40 -0
- package/dist/components/browser/SearchBar.svelte.d.ts +6 -0
- package/dist/components/browser/UploadButton.svelte +65 -0
- package/dist/components/browser/UploadButton.svelte.d.ts +3 -0
- package/dist/components/editor/CodeMirrorEditor.svelte +404 -0
- package/dist/components/editor/CodeMirrorEditor.svelte.d.ts +12 -0
- package/dist/components/editor/MilkdownEditor.svelte +98 -0
- package/dist/components/editor/MilkdownEditor.svelte.d.ts +9 -0
- package/dist/components/editor/SqlEditor.svelte +173 -0
- package/dist/components/editor/SqlEditor.svelte.d.ts +7 -0
- package/dist/components/editor/SqlResultBlock.svelte +199 -0
- package/dist/components/editor/SqlResultBlock.svelte.d.ts +9 -0
- package/dist/components/layout/ConnectionDialog.svelte +439 -0
- package/dist/components/layout/ConnectionDialog.svelte.d.ts +9 -0
- package/dist/components/layout/LocaleToggle.svelte +32 -0
- package/dist/components/layout/LocaleToggle.svelte.d.ts +3 -0
- package/dist/components/layout/SafeLockToggle.svelte +37 -0
- package/dist/components/layout/SafeLockToggle.svelte.d.ts +18 -0
- package/dist/components/layout/Sidebar.svelte +314 -0
- package/dist/components/layout/Sidebar.svelte.d.ts +3 -0
- package/dist/components/layout/StatusBar.svelte +73 -0
- package/dist/components/layout/StatusBar.svelte.d.ts +3 -0
- package/dist/components/layout/TabBar.svelte +102 -0
- package/dist/components/layout/TabBar.svelte.d.ts +7 -0
- package/dist/components/layout/ThemeToggle.svelte +52 -0
- package/dist/components/layout/ThemeToggle.svelte.d.ts +3 -0
- package/dist/components/ui/badge/badge.svelte +49 -0
- package/dist/components/ui/badge/badge.svelte.d.ts +32 -0
- package/dist/components/ui/badge/index.d.ts +1 -0
- package/dist/components/ui/badge/index.js +1 -0
- package/dist/components/ui/button/button.svelte +82 -0
- package/dist/components/ui/button/button.svelte.d.ts +64 -0
- package/dist/components/ui/button/index.d.ts +2 -0
- package/dist/components/ui/button/index.js +4 -0
- package/dist/components/ui/context-menu/context-menu-checkbox-item.svelte +40 -0
- package/dist/components/ui/context-menu/context-menu-checkbox-item.svelte.d.ts +9 -0
- package/dist/components/ui/context-menu/context-menu-content.svelte +28 -0
- package/dist/components/ui/context-menu/context-menu-content.svelte.d.ts +10 -0
- package/dist/components/ui/context-menu/context-menu-group-heading.svelte +21 -0
- package/dist/components/ui/context-menu/context-menu-group-heading.svelte.d.ts +7 -0
- package/dist/components/ui/context-menu/context-menu-group.svelte +7 -0
- package/dist/components/ui/context-menu/context-menu-group.svelte.d.ts +4 -0
- package/dist/components/ui/context-menu/context-menu-item.svelte +27 -0
- package/dist/components/ui/context-menu/context-menu-item.svelte.d.ts +8 -0
- package/dist/components/ui/context-menu/context-menu-label.svelte +24 -0
- package/dist/components/ui/context-menu/context-menu-label.svelte.d.ts +8 -0
- package/dist/components/ui/context-menu/context-menu-portal.svelte +7 -0
- package/dist/components/ui/context-menu/context-menu-portal.svelte.d.ts +3 -0
- package/dist/components/ui/context-menu/context-menu-radio-group.svelte +16 -0
- package/dist/components/ui/context-menu/context-menu-radio-group.svelte.d.ts +4 -0
- package/dist/components/ui/context-menu/context-menu-radio-item.svelte +33 -0
- package/dist/components/ui/context-menu/context-menu-radio-item.svelte.d.ts +4 -0
- package/dist/components/ui/context-menu/context-menu-separator.svelte +17 -0
- package/dist/components/ui/context-menu/context-menu-separator.svelte.d.ts +4 -0
- package/dist/components/ui/context-menu/context-menu-shortcut.svelte +20 -0
- package/dist/components/ui/context-menu/context-menu-shortcut.svelte.d.ts +5 -0
- package/dist/components/ui/context-menu/context-menu-sub-content.svelte +20 -0
- package/dist/components/ui/context-menu/context-menu-sub-content.svelte.d.ts +4 -0
- package/dist/components/ui/context-menu/context-menu-sub-trigger.svelte +29 -0
- package/dist/components/ui/context-menu/context-menu-sub-trigger.svelte.d.ts +8 -0
- package/dist/components/ui/context-menu/context-menu-sub.svelte +7 -0
- package/dist/components/ui/context-menu/context-menu-sub.svelte.d.ts +3 -0
- package/dist/components/ui/context-menu/context-menu-trigger.svelte +7 -0
- package/dist/components/ui/context-menu/context-menu-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/context-menu/context-menu.svelte +7 -0
- package/dist/components/ui/context-menu/context-menu.svelte.d.ts +3 -0
- package/dist/components/ui/context-menu/index.d.ts +17 -0
- package/dist/components/ui/context-menu/index.js +19 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte +16 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +43 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +9 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte +29 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte.d.ts +10 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +22 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte.d.ts +8 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-group.svelte +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-group.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte +27 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte.d.ts +8 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte +24 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte.d.ts +8 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-portal.svelte +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-portal.svelte.d.ts +3 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte +16 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +33 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte +17 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +20 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte.d.ts +5 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +20 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +29 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte.d.ts +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub.svelte +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub.svelte.d.ts +3 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu.svelte +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu.svelte.d.ts +3 -0
- package/dist/components/ui/dropdown-menu/index.d.ts +18 -0
- package/dist/components/ui/dropdown-menu/index.js +18 -0
- package/dist/components/ui/input/index.d.ts +2 -0
- package/dist/components/ui/input/index.js +4 -0
- package/dist/components/ui/input/input.svelte +52 -0
- package/dist/components/ui/input/input.svelte.d.ts +13 -0
- package/dist/components/ui/resizable/index.d.ts +4 -0
- package/dist/components/ui/resizable/index.js +6 -0
- package/dist/components/ui/resizable/resizable-handle.svelte +30 -0
- package/dist/components/ui/resizable/resizable-handle.svelte.d.ts +8 -0
- package/dist/components/ui/resizable/resizable-pane-group.svelte +20 -0
- package/dist/components/ui/resizable/resizable-pane-group.svelte.d.ts +7 -0
- package/dist/components/ui/scroll-area/index.d.ts +3 -0
- package/dist/components/ui/scroll-area/index.js +5 -0
- package/dist/components/ui/scroll-area/scroll-area-scrollbar.svelte +31 -0
- package/dist/components/ui/scroll-area/scroll-area-scrollbar.svelte.d.ts +4 -0
- package/dist/components/ui/scroll-area/scroll-area.svelte +47 -0
- package/dist/components/ui/scroll-area/scroll-area.svelte.d.ts +11 -0
- package/dist/components/ui/separator/index.d.ts +2 -0
- package/dist/components/ui/separator/index.js +4 -0
- package/dist/components/ui/separator/separator.svelte +21 -0
- package/dist/components/ui/separator/separator.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/index.d.ts +11 -0
- package/dist/components/ui/sheet/index.js +13 -0
- package/dist/components/ui/sheet/sheet-close.svelte +7 -0
- package/dist/components/ui/sheet/sheet-close.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/sheet-content.svelte +62 -0
- package/dist/components/ui/sheet/sheet-content.svelte.d.ts +37 -0
- package/dist/components/ui/sheet/sheet-description.svelte +17 -0
- package/dist/components/ui/sheet/sheet-description.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/sheet-footer.svelte +20 -0
- package/dist/components/ui/sheet/sheet-footer.svelte.d.ts +5 -0
- package/dist/components/ui/sheet/sheet-header.svelte +20 -0
- package/dist/components/ui/sheet/sheet-header.svelte.d.ts +5 -0
- package/dist/components/ui/sheet/sheet-overlay.svelte +20 -0
- package/dist/components/ui/sheet/sheet-overlay.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/sheet-portal.svelte +7 -0
- package/dist/components/ui/sheet/sheet-portal.svelte.d.ts +3 -0
- package/dist/components/ui/sheet/sheet-title.svelte +13 -0
- package/dist/components/ui/sheet/sheet-title.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/sheet-trigger.svelte +7 -0
- package/dist/components/ui/sheet/sheet-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/sheet.svelte +7 -0
- package/dist/components/ui/sheet/sheet.svelte.d.ts +3 -0
- package/dist/components/ui/switch/index.d.ts +2 -0
- package/dist/components/ui/switch/index.js +4 -0
- package/dist/components/ui/switch/switch.svelte +28 -0
- package/dist/components/ui/switch/switch.svelte.d.ts +8 -0
- package/dist/components/ui/tabs/index.d.ts +5 -0
- package/dist/components/ui/tabs/index.js +7 -0
- package/dist/components/ui/tabs/tabs-content.svelte +17 -0
- package/dist/components/ui/tabs/tabs-content.svelte.d.ts +4 -0
- package/dist/components/ui/tabs/tabs-list.svelte +16 -0
- package/dist/components/ui/tabs/tabs-list.svelte.d.ts +4 -0
- package/dist/components/ui/tabs/tabs-trigger.svelte +20 -0
- package/dist/components/ui/tabs/tabs-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/tabs/tabs.svelte +19 -0
- package/dist/components/ui/tabs/tabs.svelte.d.ts +4 -0
- package/dist/components/ui/tooltip/index.d.ts +6 -0
- package/dist/components/ui/tooltip/index.js +8 -0
- package/dist/components/ui/tooltip/tooltip-content.svelte +52 -0
- package/dist/components/ui/tooltip/tooltip-content.svelte.d.ts +11 -0
- package/dist/components/ui/tooltip/tooltip-portal.svelte +7 -0
- package/dist/components/ui/tooltip/tooltip-portal.svelte.d.ts +4 -0
- package/dist/components/ui/tooltip/tooltip-provider.svelte +7 -0
- package/dist/components/ui/tooltip/tooltip-provider.svelte.d.ts +4 -0
- package/dist/components/ui/tooltip/tooltip-trigger.svelte +7 -0
- package/dist/components/ui/tooltip/tooltip-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/tooltip/tooltip.svelte +7 -0
- package/dist/components/ui/tooltip/tooltip.svelte.d.ts +4 -0
- package/dist/components/viewers/ArchiveViewer.svelte +586 -0
- package/dist/components/viewers/ArchiveViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/CLAUDE.md +60 -0
- package/dist/components/viewers/CodeViewer.svelte +553 -0
- package/dist/components/viewers/CodeViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/CogViewer.svelte +1345 -0
- package/dist/components/viewers/CogViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/CopcViewer.svelte +25 -0
- package/dist/components/viewers/CopcViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/DatabaseViewer.svelte +169 -0
- package/dist/components/viewers/DatabaseViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/FileInfo.svelte +174 -0
- package/dist/components/viewers/FileInfo.svelte.d.ts +10 -0
- package/dist/components/viewers/FlatGeobufViewer.svelte +755 -0
- package/dist/components/viewers/FlatGeobufViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/GeoParquetMapViewer.svelte +278 -0
- package/dist/components/viewers/GeoParquetMapViewer.svelte.d.ts +17 -0
- package/dist/components/viewers/ImageViewer.svelte +233 -0
- package/dist/components/viewers/ImageViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/LoadProgress.svelte +93 -0
- package/dist/components/viewers/LoadProgress.svelte.d.ts +15 -0
- package/dist/components/viewers/MapViewer.svelte +234 -0
- package/dist/components/viewers/MapViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/MarkdownViewer.svelte +478 -0
- package/dist/components/viewers/MarkdownViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/MediaViewer.svelte +121 -0
- package/dist/components/viewers/MediaViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/ModelViewer.svelte +164 -0
- package/dist/components/viewers/ModelViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/NotebookViewer.svelte +389 -0
- package/dist/components/viewers/NotebookViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/PdfViewer.svelte +278 -0
- package/dist/components/viewers/PdfViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/PmtilesViewer.svelte +191 -0
- package/dist/components/viewers/PmtilesViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/QueryHistoryPanel.svelte +159 -0
- package/dist/components/viewers/QueryHistoryPanel.svelte.d.ts +8 -0
- package/dist/components/viewers/RawViewer.svelte +117 -0
- package/dist/components/viewers/RawViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/StacMapViewer.svelte +20 -0
- package/dist/components/viewers/StacMapViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/StyleEditorOverlay.svelte +27 -0
- package/dist/components/viewers/StyleEditorOverlay.svelte.d.ts +7 -0
- package/dist/components/viewers/TableGrid.svelte +355 -0
- package/dist/components/viewers/TableGrid.svelte.d.ts +12 -0
- package/dist/components/viewers/TableStatusBar.svelte +92 -0
- package/dist/components/viewers/TableStatusBar.svelte.d.ts +11 -0
- package/dist/components/viewers/TableToolbar.svelte +382 -0
- package/dist/components/viewers/TableToolbar.svelte.d.ts +25 -0
- package/dist/components/viewers/TableViewer.svelte +923 -0
- package/dist/components/viewers/TableViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/ViewerRouter.svelte +70 -0
- package/dist/components/viewers/ViewerRouter.svelte.d.ts +7 -0
- package/dist/components/viewers/ZarrMapViewer.svelte +288 -0
- package/dist/components/viewers/ZarrMapViewer.svelte.d.ts +17 -0
- package/dist/components/viewers/ZarrViewer.svelte +256 -0
- package/dist/components/viewers/ZarrViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/map/AttributeTable.svelte +52 -0
- package/dist/components/viewers/map/AttributeTable.svelte.d.ts +8 -0
- package/dist/components/viewers/map/MapContainer.svelte +158 -0
- package/dist/components/viewers/map/MapContainer.svelte.d.ts +12 -0
- package/dist/components/viewers/pmtiles/PmtilesArchiveView.svelte +389 -0
- package/dist/components/viewers/pmtiles/PmtilesArchiveView.svelte.d.ts +10 -0
- package/dist/components/viewers/pmtiles/PmtilesMapView.svelte +332 -0
- package/dist/components/viewers/pmtiles/PmtilesMapView.svelte.d.ts +11 -0
- package/dist/components/viewers/pmtiles/PmtilesTileInspector.svelte +373 -0
- package/dist/components/viewers/pmtiles/PmtilesTileInspector.svelte.d.ts +12 -0
- package/dist/components/viewers/pmtiles/SvgTileRenderer.svelte +112 -0
- package/dist/components/viewers/pmtiles/SvgTileRenderer.svelte.d.ts +10 -0
- package/dist/file-icons/CLAUDE.md +21 -0
- package/dist/file-icons/FileTypeIcon.svelte +74 -0
- package/dist/file-icons/FileTypeIcon.svelte.d.ts +9 -0
- package/dist/file-icons/index.d.ts +56 -0
- package/dist/file-icons/index.js +1070 -0
- package/dist/i18n/CLAUDE.md +19 -0
- package/dist/i18n/ar.d.ts +1 -0
- package/dist/i18n/ar.js +404 -0
- package/dist/i18n/en.d.ts +1 -0
- package/dist/i18n/en.js +404 -0
- package/dist/i18n/index.svelte.d.ts +9 -0
- package/dist/i18n/index.svelte.js +27 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +13 -0
- package/dist/query/CLAUDE.md +22 -0
- package/dist/query/engine.d.ts +56 -0
- package/dist/query/engine.js +6 -0
- package/dist/query/index.d.ts +4 -0
- package/dist/query/index.js +19 -0
- package/dist/query/wasm.d.ts +20 -0
- package/dist/query/wasm.js +890 -0
- package/dist/storage/CLAUDE.md +23 -0
- package/dist/storage/adapter.d.ts +21 -0
- package/dist/storage/adapter.js +1 -0
- package/dist/storage/browser-azure.d.ts +25 -0
- package/dist/storage/browser-azure.js +271 -0
- package/dist/storage/browser-cloud.d.ts +32 -0
- package/dist/storage/browser-cloud.js +293 -0
- package/dist/storage/index.d.ts +11 -0
- package/dist/storage/index.js +37 -0
- package/dist/storage/url-adapter.d.ts +19 -0
- package/dist/storage/url-adapter.js +51 -0
- package/dist/stores/CLAUDE.md +29 -0
- package/dist/stores/browser.svelte.d.ts +28 -0
- package/dist/stores/browser.svelte.js +160 -0
- package/dist/stores/connections.svelte.d.ts +56 -0
- package/dist/stores/connections.svelte.js +272 -0
- package/dist/stores/credentials.svelte.d.ts +56 -0
- package/dist/stores/credentials.svelte.js +79 -0
- package/dist/stores/files.svelte.d.ts +20 -0
- package/dist/stores/files.svelte.js +76 -0
- package/dist/stores/query-history.svelte.d.ts +16 -0
- package/dist/stores/query-history.svelte.js +57 -0
- package/dist/stores/safelock.svelte.d.ts +8 -0
- package/dist/stores/safelock.svelte.js +52 -0
- package/dist/stores/settings.svelte.d.ts +11 -0
- package/dist/stores/settings.svelte.js +101 -0
- package/dist/stores/tab-resources.svelte.d.ts +25 -0
- package/dist/stores/tab-resources.svelte.js +61 -0
- package/dist/stores/tabs.svelte.d.ts +17 -0
- package/dist/stores/tabs.svelte.js +110 -0
- package/dist/types/notebookjs.d.ts +14 -0
- package/dist/types.d.ts +47 -0
- package/dist/types.js +1 -0
- package/dist/utils/CLAUDE.md +54 -0
- package/dist/utils/analytics.d.ts +10 -0
- package/dist/utils/analytics.js +38 -0
- package/dist/utils/archive.d.ts +70 -0
- package/dist/utils/archive.js +333 -0
- package/dist/utils/column-types.d.ts +5 -0
- package/dist/utils/column-types.js +137 -0
- package/dist/utils/deck.d.ts +98 -0
- package/dist/utils/deck.js +208 -0
- package/dist/utils/evidence-context.d.ts +22 -0
- package/dist/utils/evidence-context.js +56 -0
- package/dist/utils/export.d.ts +2 -0
- package/dist/utils/export.js +51 -0
- package/dist/utils/format.d.ts +14 -0
- package/dist/utils/format.js +56 -0
- package/dist/utils/geoarrow.d.ts +32 -0
- package/dist/utils/geoarrow.js +672 -0
- package/dist/utils/hex.d.ts +10 -0
- package/dist/utils/hex.js +27 -0
- package/dist/utils/host-detection.d.ts +23 -0
- package/dist/utils/host-detection.js +289 -0
- package/dist/utils/map-selection.d.ts +12 -0
- package/dist/utils/map-selection.js +45 -0
- package/dist/utils/markdown-sql.d.ts +30 -0
- package/dist/utils/markdown-sql.js +73 -0
- package/dist/utils/markdown.d.ts +18 -0
- package/dist/utils/markdown.js +146 -0
- package/dist/utils/model3d.d.ts +13 -0
- package/dist/utils/model3d.js +62 -0
- package/dist/utils/parquet-metadata.d.ts +58 -0
- package/dist/utils/parquet-metadata.js +228 -0
- package/dist/utils/pdf.d.ts +8 -0
- package/dist/utils/pdf.js +28 -0
- package/dist/utils/pmtiles-tile.d.ts +38 -0
- package/dist/utils/pmtiles-tile.js +64 -0
- package/dist/utils/pmtiles.d.ts +46 -0
- package/dist/utils/pmtiles.js +135 -0
- package/dist/utils/shiki.d.ts +8 -0
- package/dist/utils/shiki.js +98 -0
- package/dist/utils/storage-url.d.ts +64 -0
- package/dist/utils/storage-url.js +374 -0
- package/dist/utils/url-state.d.ts +40 -0
- package/dist/utils/url-state.js +113 -0
- package/dist/utils/url.d.ts +27 -0
- package/dist/utils/url.js +115 -0
- package/dist/utils/wkb.d.ts +43 -0
- package/dist/utils/wkb.js +345 -0
- package/dist/utils/zarr.d.ts +39 -0
- package/dist/utils/zarr.js +204 -0
- package/dist/utils.d.ts +12 -0
- package/dist/utils.js +5 -0
- 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,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,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;
|