@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,5 @@
|
|
|
1
|
+
export type TypeCategory = 'number' | 'string' | 'date' | 'boolean' | 'geo' | 'binary' | 'json' | 'other';
|
|
2
|
+
export declare function classifyType(duckdbType: string): TypeCategory;
|
|
3
|
+
export declare function typeColor(category: TypeCategory): string;
|
|
4
|
+
export declare function typeBadgeClass(category: TypeCategory): string;
|
|
5
|
+
export declare function typeLabel(category: TypeCategory): string;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
const NUMBER_TYPES = [
|
|
2
|
+
'TINYINT',
|
|
3
|
+
'SMALLINT',
|
|
4
|
+
'INTEGER',
|
|
5
|
+
'BIGINT',
|
|
6
|
+
'HUGEINT',
|
|
7
|
+
'UTINYINT',
|
|
8
|
+
'USMALLINT',
|
|
9
|
+
'UINTEGER',
|
|
10
|
+
'UBIGINT',
|
|
11
|
+
'FLOAT',
|
|
12
|
+
'DOUBLE',
|
|
13
|
+
'DECIMAL',
|
|
14
|
+
'NUMERIC',
|
|
15
|
+
'REAL',
|
|
16
|
+
'INT',
|
|
17
|
+
'INT1',
|
|
18
|
+
'INT2',
|
|
19
|
+
'INT4',
|
|
20
|
+
'INT8',
|
|
21
|
+
'SIGNED',
|
|
22
|
+
'SHORT',
|
|
23
|
+
'LONG'
|
|
24
|
+
];
|
|
25
|
+
const STRING_TYPES = ['VARCHAR', 'TEXT', 'STRING', 'CHAR', 'BPCHAR', 'NAME', 'UUID', 'ENUM'];
|
|
26
|
+
const DATE_TYPES = [
|
|
27
|
+
'DATE',
|
|
28
|
+
'TIME',
|
|
29
|
+
'TIMESTAMP',
|
|
30
|
+
'TIMESTAMP_S',
|
|
31
|
+
'TIMESTAMP_MS',
|
|
32
|
+
'TIMESTAMP_NS',
|
|
33
|
+
'TIMESTAMP WITH TIME ZONE',
|
|
34
|
+
'TIMESTAMPTZ',
|
|
35
|
+
'INTERVAL',
|
|
36
|
+
'TIMESTAMP_TZ'
|
|
37
|
+
];
|
|
38
|
+
const BOOLEAN_TYPES = ['BOOLEAN', 'BOOL', 'LOGICAL'];
|
|
39
|
+
const GEO_TYPES = [
|
|
40
|
+
'GEOMETRY',
|
|
41
|
+
'POINT',
|
|
42
|
+
'LINESTRING',
|
|
43
|
+
'POLYGON',
|
|
44
|
+
'MULTIPOINT',
|
|
45
|
+
'MULTILINESTRING',
|
|
46
|
+
'MULTIPOLYGON',
|
|
47
|
+
'GEOMETRYCOLLECTION',
|
|
48
|
+
'WKB_GEOMETRY'
|
|
49
|
+
];
|
|
50
|
+
const BINARY_TYPES = ['BLOB', 'BYTEA', 'BINARY', 'VARBINARY'];
|
|
51
|
+
const JSON_TYPES = ['JSON', 'JSONB'];
|
|
52
|
+
export function classifyType(duckdbType) {
|
|
53
|
+
const upper = duckdbType.toUpperCase().trim();
|
|
54
|
+
// Handle parameterized types like DECIMAL(18,3), VARCHAR(100)
|
|
55
|
+
const base = upper.replace(/\(.*\)/, '').trim();
|
|
56
|
+
if (NUMBER_TYPES.includes(base))
|
|
57
|
+
return 'number';
|
|
58
|
+
if (STRING_TYPES.includes(base))
|
|
59
|
+
return 'string';
|
|
60
|
+
if (DATE_TYPES.includes(base))
|
|
61
|
+
return 'date';
|
|
62
|
+
if (BOOLEAN_TYPES.includes(base))
|
|
63
|
+
return 'boolean';
|
|
64
|
+
if (GEO_TYPES.includes(base))
|
|
65
|
+
return 'geo';
|
|
66
|
+
if (BINARY_TYPES.includes(base))
|
|
67
|
+
return 'binary';
|
|
68
|
+
if (JSON_TYPES.includes(base))
|
|
69
|
+
return 'json';
|
|
70
|
+
// Compound types
|
|
71
|
+
if (base.startsWith('STRUCT') || base.startsWith('MAP') || base.startsWith('UNION'))
|
|
72
|
+
return 'json';
|
|
73
|
+
if (base.endsWith('[]') || base.startsWith('LIST'))
|
|
74
|
+
return 'json';
|
|
75
|
+
// Fallback checks
|
|
76
|
+
if (upper.includes('INT') ||
|
|
77
|
+
upper.includes('FLOAT') ||
|
|
78
|
+
upper.includes('DOUBLE') ||
|
|
79
|
+
upper.includes('DECIMAL') ||
|
|
80
|
+
upper.includes('NUMERIC'))
|
|
81
|
+
return 'number';
|
|
82
|
+
if (upper.includes('CHAR') || upper.includes('TEXT') || upper.includes('STRING'))
|
|
83
|
+
return 'string';
|
|
84
|
+
if (upper.includes('TIME') || upper.includes('DATE'))
|
|
85
|
+
return 'date';
|
|
86
|
+
if (upper.includes('BOOL'))
|
|
87
|
+
return 'boolean';
|
|
88
|
+
if (upper.includes('GEOMETRY') || upper.includes('GEO') || upper.includes('WKB'))
|
|
89
|
+
return 'geo';
|
|
90
|
+
if (upper.includes('BLOB') || upper.includes('BINARY'))
|
|
91
|
+
return 'binary';
|
|
92
|
+
if (upper.includes('JSON') ||
|
|
93
|
+
upper.includes('STRUCT') ||
|
|
94
|
+
upper.includes('MAP') ||
|
|
95
|
+
upper.includes('LIST'))
|
|
96
|
+
return 'json';
|
|
97
|
+
return 'other';
|
|
98
|
+
}
|
|
99
|
+
const TYPE_COLORS = {
|
|
100
|
+
number: 'text-blue-500',
|
|
101
|
+
string: 'text-green-500',
|
|
102
|
+
date: 'text-amber-500',
|
|
103
|
+
boolean: 'text-purple-500',
|
|
104
|
+
geo: 'text-teal-500',
|
|
105
|
+
binary: 'text-zinc-500',
|
|
106
|
+
json: 'text-orange-500',
|
|
107
|
+
other: 'text-zinc-400'
|
|
108
|
+
};
|
|
109
|
+
const TYPE_BADGE_CLASSES = {
|
|
110
|
+
number: 'bg-blue-500/10 text-blue-600 dark:text-blue-400 border-blue-500/20',
|
|
111
|
+
string: 'bg-green-500/10 text-green-600 dark:text-green-400 border-green-500/20',
|
|
112
|
+
date: 'bg-amber-500/10 text-amber-600 dark:text-amber-400 border-amber-500/20',
|
|
113
|
+
boolean: 'bg-purple-500/10 text-purple-600 dark:text-purple-400 border-purple-500/20',
|
|
114
|
+
geo: 'bg-teal-500/10 text-teal-600 dark:text-teal-400 border-teal-500/20',
|
|
115
|
+
binary: 'bg-zinc-500/10 text-zinc-600 dark:text-zinc-400 border-zinc-500/20',
|
|
116
|
+
json: 'bg-orange-500/10 text-orange-600 dark:text-orange-400 border-orange-500/20',
|
|
117
|
+
other: 'bg-zinc-500/10 text-zinc-500 dark:text-zinc-400 border-zinc-500/20'
|
|
118
|
+
};
|
|
119
|
+
const TYPE_LABELS = {
|
|
120
|
+
number: '#',
|
|
121
|
+
string: 'Aa',
|
|
122
|
+
date: 'dt',
|
|
123
|
+
boolean: 'T/F',
|
|
124
|
+
geo: 'geo',
|
|
125
|
+
binary: '01',
|
|
126
|
+
json: '{}',
|
|
127
|
+
other: '?'
|
|
128
|
+
};
|
|
129
|
+
export function typeColor(category) {
|
|
130
|
+
return TYPE_COLORS[category];
|
|
131
|
+
}
|
|
132
|
+
export function typeBadgeClass(category) {
|
|
133
|
+
return TYPE_BADGE_CLASSES[category];
|
|
134
|
+
}
|
|
135
|
+
export function typeLabel(category) {
|
|
136
|
+
return TYPE_LABELS[category];
|
|
137
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared deck.gl utilities for map viewers.
|
|
3
|
+
*
|
|
4
|
+
* - GeoJSON overlay: used by FlatGeobufViewer
|
|
5
|
+
* - GeoArrow overlay: used by GeoParquetMapViewer (zero-copy DuckDB → GPU pipeline)
|
|
6
|
+
*/
|
|
7
|
+
import type { GeoArrowResult } from './geoarrow.js';
|
|
8
|
+
/**
|
|
9
|
+
* Create an onHover callback that toggles the cursor on the MapLibre canvas.
|
|
10
|
+
* With `interleaved: false`, deck.gl's own canvas has pointer-events: none,
|
|
11
|
+
* so getCursor on MapboxOverlay has no visible effect — we must set cursor
|
|
12
|
+
* directly on the MapLibre map canvas instead.
|
|
13
|
+
*/
|
|
14
|
+
export declare function hoverCursor(map: {
|
|
15
|
+
getCanvas: () => HTMLElement;
|
|
16
|
+
}): (info: {
|
|
17
|
+
picked?: boolean;
|
|
18
|
+
}) => void;
|
|
19
|
+
type RGBA = [number, number, number, number];
|
|
20
|
+
/** Distinct fill/line colors per geometry type. */
|
|
21
|
+
export declare const GEOMETRY_COLORS: Record<string, {
|
|
22
|
+
fill: RGBA;
|
|
23
|
+
line: RGBA;
|
|
24
|
+
}>;
|
|
25
|
+
/**
|
|
26
|
+
* GeoJSON accessor: return fill color based on feature geometry type.
|
|
27
|
+
* Used as deck.gl accessor function for getFillColor / getLineColor.
|
|
28
|
+
*/
|
|
29
|
+
export declare function geojsonFillColor(feature: any): RGBA;
|
|
30
|
+
export declare function geojsonLineColor(feature: any): RGBA;
|
|
31
|
+
/** Lazy-load deck.gl modules (MapboxOverlay + GeoJsonLayer). */
|
|
32
|
+
export declare function loadDeckModules(): Promise<{
|
|
33
|
+
MapboxOverlay: typeof import("@deck.gl/mapbox").MapboxOverlay;
|
|
34
|
+
GeoJsonLayer: typeof import("@deck.gl/layers").GeoJsonLayer;
|
|
35
|
+
}>;
|
|
36
|
+
export interface DeckOverlayOptions {
|
|
37
|
+
layerId: string;
|
|
38
|
+
data: GeoJSON.FeatureCollection;
|
|
39
|
+
/** Called with properties and the full GeoJSON Feature (for selection highlight). */
|
|
40
|
+
onClick?: (properties: Record<string, any>, feature: GeoJSON.Feature) => void;
|
|
41
|
+
/** Layer-level onHover — use hoverCursor(map) to toggle pointer on MapLibre canvas. */
|
|
42
|
+
onHover?: (info: {
|
|
43
|
+
picked?: boolean;
|
|
44
|
+
}) => void;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Create a MapboxOverlay with a single GeoJsonLayer.
|
|
48
|
+
* Colors are assigned per-feature based on geometry type.
|
|
49
|
+
*/
|
|
50
|
+
export declare function createDeckOverlay(modules: {
|
|
51
|
+
MapboxOverlay: any;
|
|
52
|
+
GeoJsonLayer: any;
|
|
53
|
+
}, options: DeckOverlayOptions): any;
|
|
54
|
+
/** Lazy-load GeoArrow deck.gl layers + MapboxOverlay + GeoJsonLayer (for selection). */
|
|
55
|
+
export declare function loadGeoArrowModules(): Promise<{
|
|
56
|
+
GeoArrowArcLayer: typeof import("@geoarrow/deck.gl-layers").GeoArrowArcLayer;
|
|
57
|
+
GeoArrowColumnLayer: typeof import("@geoarrow/deck.gl-layers").GeoArrowColumnLayer;
|
|
58
|
+
_GeoArrowH3HexagonLayer: typeof import("@geoarrow/deck.gl-layers")._GeoArrowH3HexagonLayer;
|
|
59
|
+
GeoArrowHeatmapLayer: typeof import("@geoarrow/deck.gl-layers").GeoArrowHeatmapLayer;
|
|
60
|
+
GeoArrowPathLayer: typeof import("@geoarrow/deck.gl-layers").GeoArrowPathLayer;
|
|
61
|
+
GeoArrowPointCloudLayer: typeof import("@geoarrow/deck.gl-layers").GeoArrowPointCloudLayer;
|
|
62
|
+
GeoArrowPolygonLayer: typeof import("@geoarrow/deck.gl-layers").GeoArrowPolygonLayer;
|
|
63
|
+
GeoArrowScatterplotLayer: typeof import("@geoarrow/deck.gl-layers").GeoArrowScatterplotLayer;
|
|
64
|
+
GeoArrowSolidPolygonLayer: typeof import("@geoarrow/deck.gl-layers").GeoArrowSolidPolygonLayer;
|
|
65
|
+
_GeoArrowTextLayer: typeof import("@geoarrow/deck.gl-layers")._GeoArrowTextLayer;
|
|
66
|
+
GeoArrowTripsLayer: typeof import("@geoarrow/deck.gl-layers").GeoArrowTripsLayer;
|
|
67
|
+
MapboxOverlay: typeof import("@deck.gl/mapbox").MapboxOverlay;
|
|
68
|
+
GeoJsonLayer: typeof import("@deck.gl/layers").GeoJsonLayer;
|
|
69
|
+
}>;
|
|
70
|
+
export interface GeoArrowOverlayOptions {
|
|
71
|
+
layerId: string;
|
|
72
|
+
geoArrowResults: GeoArrowResult[];
|
|
73
|
+
/** Called with properties and the original WKB array index (for selection highlight). */
|
|
74
|
+
onClick?: (properties: Record<string, any>, sourceIndex: number) => void;
|
|
75
|
+
/** Layer-level onHover — use hoverCursor(map) to toggle pointer on MapLibre canvas. */
|
|
76
|
+
onHover?: (info: {
|
|
77
|
+
picked?: boolean;
|
|
78
|
+
}) => void;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Create MapboxOverlay with GeoArrow layers — one per geometry type group.
|
|
82
|
+
* Returns both the overlay and the data layers array (for adding selection layers later).
|
|
83
|
+
*/
|
|
84
|
+
export declare function createGeoArrowOverlay(modules: Record<string, any>, options: GeoArrowOverlayOptions): {
|
|
85
|
+
overlay: any;
|
|
86
|
+
layers: any[];
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Create GeoArrow layers without an overlay — for in-place overlay updates.
|
|
90
|
+
*/
|
|
91
|
+
export declare function createGeoArrowLayers(modules: Record<string, any>, options: GeoArrowOverlayOptions): any[];
|
|
92
|
+
/**
|
|
93
|
+
* Build a deck.gl GeoJsonLayer that draws a yellow outline around a single feature.
|
|
94
|
+
* Used for QGIS-style click-selection highlight on the deck.gl canvas (which sits
|
|
95
|
+
* above MapLibre, so a native MapLibre layer would be hidden).
|
|
96
|
+
*/
|
|
97
|
+
export declare function buildSelectionLayer(GeoJsonLayer: any, feature: GeoJSON.Feature | null): any | null;
|
|
98
|
+
export {};
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared deck.gl utilities for map viewers.
|
|
3
|
+
*
|
|
4
|
+
* - GeoJSON overlay: used by FlatGeobufViewer
|
|
5
|
+
* - GeoArrow overlay: used by GeoParquetMapViewer (zero-copy DuckDB → GPU pipeline)
|
|
6
|
+
*/
|
|
7
|
+
// ─── Shared hover cursor helper ─────────────────────────────────────
|
|
8
|
+
/**
|
|
9
|
+
* Create an onHover callback that toggles the cursor on the MapLibre canvas.
|
|
10
|
+
* With `interleaved: false`, deck.gl's own canvas has pointer-events: none,
|
|
11
|
+
* so getCursor on MapboxOverlay has no visible effect — we must set cursor
|
|
12
|
+
* directly on the MapLibre map canvas instead.
|
|
13
|
+
*/
|
|
14
|
+
export function hoverCursor(map) {
|
|
15
|
+
return (info) => {
|
|
16
|
+
map.getCanvas().style.cursor = info.picked ? 'pointer' : '';
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/** Distinct fill/line colors per geometry type. */
|
|
20
|
+
export const GEOMETRY_COLORS = {
|
|
21
|
+
point: { fill: [66, 133, 244, 180], line: [25, 103, 210, 220] },
|
|
22
|
+
linestring: { fill: [0, 172, 193, 160], line: [0, 131, 143, 220] },
|
|
23
|
+
polygon: { fill: [232, 121, 61, 110], line: [230, 81, 0, 220] }
|
|
24
|
+
};
|
|
25
|
+
/** Lookup colors for a geometry type, falling back to polygon palette. */
|
|
26
|
+
function colorsForType(geomType) {
|
|
27
|
+
const t = geomType.toLowerCase().replace('multi', '');
|
|
28
|
+
return GEOMETRY_COLORS[t] ?? GEOMETRY_COLORS.polygon;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* GeoJSON accessor: return fill color based on feature geometry type.
|
|
32
|
+
* Used as deck.gl accessor function for getFillColor / getLineColor.
|
|
33
|
+
*/
|
|
34
|
+
export function geojsonFillColor(feature) {
|
|
35
|
+
return colorsForType(feature.geometry?.type ?? 'polygon').fill;
|
|
36
|
+
}
|
|
37
|
+
export function geojsonLineColor(feature) {
|
|
38
|
+
return colorsForType(feature.geometry?.type ?? 'polygon').line;
|
|
39
|
+
}
|
|
40
|
+
// ─── GeoJSON overlay (FlatGeobufViewer) ──────────────────────────────
|
|
41
|
+
/** Lazy-load deck.gl modules (MapboxOverlay + GeoJsonLayer). */
|
|
42
|
+
export async function loadDeckModules() {
|
|
43
|
+
const [{ MapboxOverlay }, { GeoJsonLayer }] = await Promise.all([
|
|
44
|
+
import('@deck.gl/mapbox'),
|
|
45
|
+
import('@deck.gl/layers')
|
|
46
|
+
]);
|
|
47
|
+
return { MapboxOverlay, GeoJsonLayer };
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Create a MapboxOverlay with a single GeoJsonLayer.
|
|
51
|
+
* Colors are assigned per-feature based on geometry type.
|
|
52
|
+
*/
|
|
53
|
+
export function createDeckOverlay(modules, options) {
|
|
54
|
+
const { MapboxOverlay, GeoJsonLayer } = modules;
|
|
55
|
+
const { layerId, data, onClick, onHover } = options;
|
|
56
|
+
return new MapboxOverlay({
|
|
57
|
+
interleaved: false,
|
|
58
|
+
layers: [
|
|
59
|
+
new GeoJsonLayer({
|
|
60
|
+
id: layerId,
|
|
61
|
+
data,
|
|
62
|
+
pickable: true,
|
|
63
|
+
stroked: true,
|
|
64
|
+
filled: true,
|
|
65
|
+
pointType: 'circle',
|
|
66
|
+
getFillColor: geojsonFillColor,
|
|
67
|
+
getLineColor: geojsonLineColor,
|
|
68
|
+
getPointRadius: 6,
|
|
69
|
+
getLineWidth: 2.5,
|
|
70
|
+
lineWidthMinPixels: 1.5,
|
|
71
|
+
pointRadiusMinPixels: 4,
|
|
72
|
+
pointRadiusMaxPixels: 12,
|
|
73
|
+
autoHighlight: true,
|
|
74
|
+
highlightColor: [255, 255, 255, 100],
|
|
75
|
+
onHover,
|
|
76
|
+
onClick: (info) => {
|
|
77
|
+
if (info.object?.properties && onClick) {
|
|
78
|
+
onClick({ ...info.object.properties }, info.object);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
]
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
// ─── GeoArrow overlay (GeoParquetMapViewer) ──────────────────────────
|
|
86
|
+
/** Lazy-load GeoArrow deck.gl layers + MapboxOverlay + GeoJsonLayer (for selection). */
|
|
87
|
+
export async function loadGeoArrowModules() {
|
|
88
|
+
const [{ MapboxOverlay }, geoarrowLayers, { GeoJsonLayer }] = await Promise.all([
|
|
89
|
+
import('@deck.gl/mapbox'),
|
|
90
|
+
import('@geoarrow/deck.gl-layers'),
|
|
91
|
+
import('@deck.gl/layers')
|
|
92
|
+
]);
|
|
93
|
+
return { MapboxOverlay, GeoJsonLayer, ...geoarrowLayers };
|
|
94
|
+
}
|
|
95
|
+
/** Create a single deck.gl layer for one GeoArrowResult. */
|
|
96
|
+
function createLayerForResult(modules, result, layerId, onClick, onHover) {
|
|
97
|
+
const { GeoArrowScatterplotLayer, GeoArrowPathLayer, GeoArrowPolygonLayer } = modules;
|
|
98
|
+
const { table, geometryType, sourceIndices } = result;
|
|
99
|
+
const { fill, line } = colorsForType(geometryType);
|
|
100
|
+
const handleClick = (info) => {
|
|
101
|
+
if (!onClick)
|
|
102
|
+
return;
|
|
103
|
+
const props = extractPickedProps(info);
|
|
104
|
+
const srcIdx = sourceIndices[info.index] ?? info.index;
|
|
105
|
+
onClick(props, srcIdx);
|
|
106
|
+
};
|
|
107
|
+
if (geometryType === 'point' || geometryType === 'multipoint') {
|
|
108
|
+
return new GeoArrowScatterplotLayer({
|
|
109
|
+
id: layerId,
|
|
110
|
+
data: table,
|
|
111
|
+
getFillColor: fill,
|
|
112
|
+
getRadius: 6,
|
|
113
|
+
radiusUnits: 'pixels',
|
|
114
|
+
radiusMinPixels: 4,
|
|
115
|
+
radiusMaxPixels: 12,
|
|
116
|
+
pickable: true,
|
|
117
|
+
autoHighlight: true,
|
|
118
|
+
highlightColor: [255, 255, 255, 100],
|
|
119
|
+
_validate: false,
|
|
120
|
+
onHover,
|
|
121
|
+
onClick: handleClick
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
else if (geometryType === 'linestring' || geometryType === 'multilinestring') {
|
|
125
|
+
return new GeoArrowPathLayer({
|
|
126
|
+
id: layerId,
|
|
127
|
+
data: table,
|
|
128
|
+
getColor: line,
|
|
129
|
+
getWidth: 2.5,
|
|
130
|
+
widthUnits: 'pixels',
|
|
131
|
+
widthMinPixels: 1.5,
|
|
132
|
+
pickable: true,
|
|
133
|
+
autoHighlight: true,
|
|
134
|
+
highlightColor: [255, 255, 255, 100],
|
|
135
|
+
_validate: false,
|
|
136
|
+
onHover,
|
|
137
|
+
onClick: handleClick
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
return new GeoArrowPolygonLayer({
|
|
142
|
+
id: layerId,
|
|
143
|
+
data: table,
|
|
144
|
+
getFillColor: fill,
|
|
145
|
+
getLineColor: line,
|
|
146
|
+
getLineWidth: 2,
|
|
147
|
+
lineWidthMinPixels: 1.5,
|
|
148
|
+
pickable: true,
|
|
149
|
+
autoHighlight: true,
|
|
150
|
+
highlightColor: [255, 255, 255, 100],
|
|
151
|
+
_validate: false,
|
|
152
|
+
onHover,
|
|
153
|
+
onClick: handleClick
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Create MapboxOverlay with GeoArrow layers — one per geometry type group.
|
|
159
|
+
* Returns both the overlay and the data layers array (for adding selection layers later).
|
|
160
|
+
*/
|
|
161
|
+
export function createGeoArrowOverlay(modules, options) {
|
|
162
|
+
const { MapboxOverlay } = modules;
|
|
163
|
+
const { layerId, geoArrowResults, onClick, onHover } = options;
|
|
164
|
+
const layers = geoArrowResults.map((result) => createLayerForResult(modules, result, `${layerId}-${result.geometryType}`, onClick, onHover));
|
|
165
|
+
return { overlay: new MapboxOverlay({ interleaved: false, layers }), layers };
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Create GeoArrow layers without an overlay — for in-place overlay updates.
|
|
169
|
+
*/
|
|
170
|
+
export function createGeoArrowLayers(modules, options) {
|
|
171
|
+
const { layerId, geoArrowResults, onClick, onHover } = options;
|
|
172
|
+
return geoArrowResults.map((result) => createLayerForResult(modules, result, `${layerId}-${result.geometryType}`, onClick, onHover));
|
|
173
|
+
}
|
|
174
|
+
// ─── Selection highlight layer (shared by deck.gl viewers) ──────────
|
|
175
|
+
/**
|
|
176
|
+
* Build a deck.gl GeoJsonLayer that draws a yellow outline around a single feature.
|
|
177
|
+
* Used for QGIS-style click-selection highlight on the deck.gl canvas (which sits
|
|
178
|
+
* above MapLibre, so a native MapLibre layer would be hidden).
|
|
179
|
+
*/
|
|
180
|
+
export function buildSelectionLayer(GeoJsonLayer, feature) {
|
|
181
|
+
if (!feature)
|
|
182
|
+
return null;
|
|
183
|
+
return new GeoJsonLayer({
|
|
184
|
+
id: 'selection-highlight',
|
|
185
|
+
data: { type: 'FeatureCollection', features: [feature] },
|
|
186
|
+
pickable: false,
|
|
187
|
+
stroked: true,
|
|
188
|
+
filled: false,
|
|
189
|
+
pointType: 'circle',
|
|
190
|
+
getLineColor: [255, 200, 0, 255],
|
|
191
|
+
getLineWidth: 3,
|
|
192
|
+
lineWidthMinPixels: 2,
|
|
193
|
+
getPointRadius: 10,
|
|
194
|
+
pointRadiusMinPixels: 8,
|
|
195
|
+
pointRadiusMaxPixels: 14
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
/** Convert GeoArrow picking result to plain object (skip geometry column). */
|
|
199
|
+
function extractPickedProps(info) {
|
|
200
|
+
if (!info.object)
|
|
201
|
+
return {};
|
|
202
|
+
const props = {};
|
|
203
|
+
for (const key of Object.keys(info.object)) {
|
|
204
|
+
if (key !== 'geometry')
|
|
205
|
+
props[key] = info.object[key];
|
|
206
|
+
}
|
|
207
|
+
return props;
|
|
208
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { QueryResult } from '../query/engine';
|
|
2
|
+
export declare class EvidenceContext {
|
|
3
|
+
private connId;
|
|
4
|
+
private prefix;
|
|
5
|
+
private results;
|
|
6
|
+
constructor(connId: string, prefix?: string);
|
|
7
|
+
/**
|
|
8
|
+
* Execute a SQL query and store the result under the given name.
|
|
9
|
+
*/
|
|
10
|
+
executeSql(sql: string, queryName: string): Promise<Record<string, any>[]>;
|
|
11
|
+
/**
|
|
12
|
+
* Transform relative file paths in SQL to full S3 URLs.
|
|
13
|
+
* e.g., read_parquet('data.parquet') → read_parquet('s3://bucket/prefix/data.parquet')
|
|
14
|
+
*/
|
|
15
|
+
private transformPaths;
|
|
16
|
+
getResult(queryName: string): {
|
|
17
|
+
result: QueryResult;
|
|
18
|
+
rows: Record<string, any>[];
|
|
19
|
+
} | undefined;
|
|
20
|
+
getAllResults(): Map<string, Record<string, any>[]>;
|
|
21
|
+
getColumns(queryName: string): string[];
|
|
22
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { getQueryEngine } from '../query/index.js';
|
|
2
|
+
export class EvidenceContext {
|
|
3
|
+
connId;
|
|
4
|
+
prefix;
|
|
5
|
+
results = new Map();
|
|
6
|
+
constructor(connId, prefix = '') {
|
|
7
|
+
this.connId = connId;
|
|
8
|
+
this.prefix = prefix;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Execute a SQL query and store the result under the given name.
|
|
12
|
+
*/
|
|
13
|
+
async executeSql(sql, queryName) {
|
|
14
|
+
const engine = await getQueryEngine();
|
|
15
|
+
// Transform relative file paths to full paths
|
|
16
|
+
const transformedSql = this.transformPaths(sql);
|
|
17
|
+
const result = await engine.query(this.connId, transformedSql);
|
|
18
|
+
const rows = result.rows ?? [];
|
|
19
|
+
this.results.set(queryName, { result, rows });
|
|
20
|
+
return rows;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Transform relative file paths in SQL to full S3 URLs.
|
|
24
|
+
* e.g., read_parquet('data.parquet') → read_parquet('s3://bucket/prefix/data.parquet')
|
|
25
|
+
*/
|
|
26
|
+
transformPaths(sql) {
|
|
27
|
+
if (!this.connId || !this.prefix)
|
|
28
|
+
return sql;
|
|
29
|
+
// Match read_parquet('path'), read_csv('path'), read_json('path')
|
|
30
|
+
return sql.replace(/(read_(?:parquet|csv|json|csv_auto))\('([^']+)'\)/g, (match, fn, path) => {
|
|
31
|
+
// Skip absolute paths and URLs
|
|
32
|
+
if (path.startsWith('s3://') || path.startsWith('http') || path.startsWith('/')) {
|
|
33
|
+
return match;
|
|
34
|
+
}
|
|
35
|
+
// Resolve relative path
|
|
36
|
+
const fullPath = `s3://${this.prefix}/${path}`;
|
|
37
|
+
return `${fn}('${fullPath}')`;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
getResult(queryName) {
|
|
41
|
+
return this.results.get(queryName);
|
|
42
|
+
}
|
|
43
|
+
getAllResults() {
|
|
44
|
+
const map = new Map();
|
|
45
|
+
for (const [name, { rows }] of this.results) {
|
|
46
|
+
map.set(name, rows);
|
|
47
|
+
}
|
|
48
|
+
return map;
|
|
49
|
+
}
|
|
50
|
+
getColumns(queryName) {
|
|
51
|
+
const entry = this.results.get(queryName);
|
|
52
|
+
if (!entry)
|
|
53
|
+
return [];
|
|
54
|
+
return entry.result.columns;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
function triggerDownload(content, filename, mimeType) {
|
|
2
|
+
const blob = new Blob([content], { type: mimeType });
|
|
3
|
+
const url = URL.createObjectURL(blob);
|
|
4
|
+
const a = document.createElement('a');
|
|
5
|
+
a.href = url;
|
|
6
|
+
a.download = filename;
|
|
7
|
+
document.body.appendChild(a);
|
|
8
|
+
a.click();
|
|
9
|
+
document.body.removeChild(a);
|
|
10
|
+
URL.revokeObjectURL(url);
|
|
11
|
+
}
|
|
12
|
+
function formatValue(value) {
|
|
13
|
+
if (value === null || value === undefined)
|
|
14
|
+
return '';
|
|
15
|
+
if (value instanceof Date)
|
|
16
|
+
return value.toISOString();
|
|
17
|
+
if (typeof value === 'object')
|
|
18
|
+
return JSON.stringify(value);
|
|
19
|
+
return String(value);
|
|
20
|
+
}
|
|
21
|
+
function escapeCsvField(value) {
|
|
22
|
+
if (value.includes(',') || value.includes('"') || value.includes('\n') || value.includes('\r')) {
|
|
23
|
+
return `"${value.replace(/"/g, '""')}"`;
|
|
24
|
+
}
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
export function exportToCsv(columns, rows, filename) {
|
|
28
|
+
const header = columns.map(escapeCsvField).join(',');
|
|
29
|
+
const body = rows
|
|
30
|
+
.map((row) => columns.map((col) => escapeCsvField(formatValue(row[col]))).join(','))
|
|
31
|
+
.join('\n');
|
|
32
|
+
const csv = `${header}\n${body}`;
|
|
33
|
+
triggerDownload(csv, filename.endsWith('.csv') ? filename : `${filename}.csv`, 'text/csv;charset=utf-8;');
|
|
34
|
+
}
|
|
35
|
+
export function exportToJson(columns, rows, filename) {
|
|
36
|
+
const data = rows.map((row) => {
|
|
37
|
+
const obj = {};
|
|
38
|
+
for (const col of columns) {
|
|
39
|
+
const val = row[col];
|
|
40
|
+
if (val instanceof Date) {
|
|
41
|
+
obj[col] = val.toISOString();
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
obj[col] = val ?? null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return obj;
|
|
48
|
+
});
|
|
49
|
+
const json = JSON.stringify(data, null, 2);
|
|
50
|
+
triggerDownload(json, filename.endsWith('.json') ? filename : `${filename}.json`, 'application/json');
|
|
51
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formats a byte count into a human-readable string.
|
|
3
|
+
*/
|
|
4
|
+
export declare function formatFileSize(bytes: number): string;
|
|
5
|
+
/**
|
|
6
|
+
* Formats a unix timestamp (milliseconds) to a human-readable date string.
|
|
7
|
+
* Shows relative time for recent dates, absolute for older ones.
|
|
8
|
+
*/
|
|
9
|
+
export declare function formatDate(timestamp: number): string;
|
|
10
|
+
/**
|
|
11
|
+
* Extracts the file extension from a filename, including the leading dot.
|
|
12
|
+
* Returns an empty string if no extension is found.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getFileExtension(filename: string): string;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formats a byte count into a human-readable string.
|
|
3
|
+
*/
|
|
4
|
+
export function formatFileSize(bytes) {
|
|
5
|
+
if (bytes < 0)
|
|
6
|
+
return '0 B';
|
|
7
|
+
if (bytes === 0)
|
|
8
|
+
return '0 B';
|
|
9
|
+
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
10
|
+
const base = 1024;
|
|
11
|
+
const exponent = Math.min(Math.floor(Math.log(bytes) / Math.log(base)), units.length - 1);
|
|
12
|
+
const value = bytes / base ** exponent;
|
|
13
|
+
// Use integer display for bytes, one decimal for everything else
|
|
14
|
+
if (exponent === 0)
|
|
15
|
+
return `${bytes} B`;
|
|
16
|
+
return `${value.toFixed(1)} ${units[exponent]}`;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Formats a unix timestamp (milliseconds) to a human-readable date string.
|
|
20
|
+
* Shows relative time for recent dates, absolute for older ones.
|
|
21
|
+
*/
|
|
22
|
+
export function formatDate(timestamp) {
|
|
23
|
+
if (!timestamp || timestamp <= 0 || !Number.isFinite(timestamp))
|
|
24
|
+
return '--';
|
|
25
|
+
const date = new Date(timestamp);
|
|
26
|
+
const now = Date.now();
|
|
27
|
+
const diffMs = now - timestamp;
|
|
28
|
+
const diffSeconds = Math.floor(diffMs / 1000);
|
|
29
|
+
const diffMinutes = Math.floor(diffSeconds / 60);
|
|
30
|
+
const diffHours = Math.floor(diffMinutes / 60);
|
|
31
|
+
const diffDays = Math.floor(diffHours / 24);
|
|
32
|
+
if (diffSeconds < 60)
|
|
33
|
+
return 'Just now';
|
|
34
|
+
if (diffMinutes < 60)
|
|
35
|
+
return `${diffMinutes}m ago`;
|
|
36
|
+
if (diffHours < 24)
|
|
37
|
+
return `${diffHours}h ago`;
|
|
38
|
+
if (diffDays < 7)
|
|
39
|
+
return `${diffDays}d ago`;
|
|
40
|
+
// For older dates, show absolute date
|
|
41
|
+
return date.toLocaleDateString(undefined, {
|
|
42
|
+
year: 'numeric',
|
|
43
|
+
month: 'short',
|
|
44
|
+
day: 'numeric'
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Extracts the file extension from a filename, including the leading dot.
|
|
49
|
+
* Returns an empty string if no extension is found.
|
|
50
|
+
*/
|
|
51
|
+
export function getFileExtension(filename) {
|
|
52
|
+
const lastDot = filename.lastIndexOf('.');
|
|
53
|
+
if (lastDot <= 0)
|
|
54
|
+
return '';
|
|
55
|
+
return filename.slice(lastDot).toLowerCase();
|
|
56
|
+
}
|