@walkthru-earth/objex 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/README.md +11 -2
  2. package/dist/components/browser/FileBrowser.svelte +41 -54
  3. package/dist/components/browser/FileTreeSidebar.svelte +43 -7
  4. package/dist/components/layout/ConnectionDialog.svelte +100 -1
  5. package/dist/components/layout/Sidebar.svelte +43 -25
  6. package/dist/components/viewers/CodeViewer.svelte +23 -0
  7. package/dist/components/viewers/CogControls.svelte +208 -0
  8. package/dist/components/viewers/CogControls.svelte.d.ts +12 -0
  9. package/dist/components/viewers/CogViewer.svelte +353 -1160
  10. package/dist/components/viewers/CogViewer.svelte.d.ts +1 -1
  11. package/dist/components/viewers/DatabaseViewer.svelte +345 -37
  12. package/dist/components/viewers/MarkdownViewer.svelte +1 -1
  13. package/dist/components/viewers/TableViewer.svelte +123 -41
  14. package/dist/components/viewers/ZarrMapViewer.svelte +29 -0
  15. package/dist/components/viewers/ZarrViewer.svelte +1 -4
  16. package/dist/constants.d.ts +6 -2
  17. package/dist/constants.js +6 -2
  18. package/dist/file-icons/index.d.ts +1 -1
  19. package/dist/file-icons/index.js +12 -2
  20. package/dist/i18n/ar.js +24 -0
  21. package/dist/i18n/en.js +24 -0
  22. package/dist/i18n/index.svelte.d.ts +0 -1
  23. package/dist/i18n/index.svelte.js +0 -3
  24. package/dist/index.d.ts +11 -0
  25. package/dist/index.js +10 -0
  26. package/dist/query/engine.d.ts +20 -4
  27. package/dist/query/index.d.ts +2 -1
  28. package/dist/query/index.js +1 -0
  29. package/dist/query/source.d.ts +30 -0
  30. package/dist/query/source.js +37 -0
  31. package/dist/query/wasm.d.ts +7 -5
  32. package/dist/query/wasm.js +138 -85
  33. package/dist/storage/providers.d.ts +47 -0
  34. package/dist/storage/providers.js +160 -0
  35. package/dist/stores/connections.svelte.js +5 -31
  36. package/dist/stores/files.svelte.d.ts +2 -8
  37. package/dist/stores/files.svelte.js +5 -38
  38. package/dist/stores/query-history.svelte.js +3 -25
  39. package/dist/stores/settings.svelte.d.ts +1 -0
  40. package/dist/stores/settings.svelte.js +10 -30
  41. package/dist/stores/tabs.svelte.d.ts +9 -2
  42. package/dist/stores/tabs.svelte.js +11 -2
  43. package/dist/types.d.ts +11 -0
  44. package/dist/utils/cloud-url.d.ts +27 -0
  45. package/dist/utils/cloud-url.js +61 -0
  46. package/dist/utils/cog.d.ts +244 -0
  47. package/dist/utils/cog.js +1039 -0
  48. package/dist/utils/deck.d.ts +0 -18
  49. package/dist/utils/deck.js +0 -36
  50. package/dist/utils/export.d.ts +22 -2
  51. package/dist/utils/export.js +35 -10
  52. package/dist/utils/file-sort.d.ts +20 -0
  53. package/dist/utils/file-sort.js +41 -0
  54. package/dist/utils/geometry-type.d.ts +52 -0
  55. package/dist/utils/geometry-type.js +76 -0
  56. package/dist/utils/local-storage.d.ts +16 -0
  57. package/dist/utils/local-storage.js +37 -0
  58. package/dist/utils/markdown-sql.d.ts +1 -1
  59. package/dist/utils/markdown-sql.js +3 -4
  60. package/dist/utils/pmtiles-tile.d.ts +0 -2
  61. package/dist/utils/pmtiles-tile.js +0 -8
  62. package/dist/utils/url-state.d.ts +6 -0
  63. package/dist/utils/url-state.js +34 -26
  64. package/dist/utils/url.d.ts +13 -25
  65. package/dist/utils/url.js +17 -78
  66. package/dist/utils/zarr-tab.d.ts +22 -0
  67. package/dist/utils/zarr-tab.js +30 -0
  68. package/dist/utils/zarr.d.ts +0 -2
  69. package/dist/utils/zarr.js +73 -44
  70. package/package.json +50 -46
  71. package/dist/components/ui/tabs/index.d.ts +0 -5
  72. package/dist/components/ui/tabs/index.js +0 -7
  73. package/dist/components/ui/tabs/tabs-content.svelte +0 -17
  74. package/dist/components/ui/tabs/tabs-content.svelte.d.ts +0 -4
  75. package/dist/components/ui/tabs/tabs-list.svelte +0 -16
  76. package/dist/components/ui/tabs/tabs-list.svelte.d.ts +0 -4
  77. package/dist/components/ui/tabs/tabs-trigger.svelte +0 -20
  78. package/dist/components/ui/tabs/tabs-trigger.svelte.d.ts +0 -4
  79. package/dist/components/ui/tabs/tabs.svelte +0 -19
  80. package/dist/components/ui/tabs/tabs.svelte.d.ts +0 -4
  81. package/dist/components/viewers/MapViewer.svelte +0 -234
  82. package/dist/components/viewers/MapViewer.svelte.d.ts +0 -7
  83. package/dist/components/viewers/StyleEditorOverlay.svelte +0 -27
  84. package/dist/components/viewers/StyleEditorOverlay.svelte.d.ts +0 -7
package/dist/utils/url.js CHANGED
@@ -1,6 +1,7 @@
1
- import { buildProviderBaseUrl, PROVIDERS } from '../storage/providers.js';
1
+ import { buildProviderBaseUrl, isPubliclyStreamable } from '../storage/providers.js';
2
2
  import { connections } from '../stores/connections.svelte.js';
3
3
  import { credentialStore } from '../stores/credentials.svelte.js';
4
+ import { getNativeScheme, safeDecodeURIComponent } from './cloud-url.js';
4
5
  /**
5
6
  * Build an HTTPS URL for a tab's file.
6
7
  * Works for any viewer that needs an HTTP-accessible URL (COG, PMTiles, Zarr, etc.)
@@ -19,17 +20,6 @@ export function buildHttpsUrl(tab) {
19
20
  }
20
21
  return `${buildProviderBaseUrl(conn.provider, conn.endpoint, conn.bucket, conn.region)}/${cleanPath}`;
21
22
  }
22
- /**
23
- * Map provider to its native URI scheme prefix.
24
- * Derived from the registry's `schemes` array (first entry is the primary scheme).
25
- * Falls back to 's3' for providers without a scheme (S3-compatible).
26
- */
27
- export function getNativeScheme(provider) {
28
- const def = PROVIDERS[provider];
29
- if (def?.schemes.length)
30
- return def.schemes[0];
31
- return 's3';
32
- }
33
23
  /**
34
24
  * Build a provider-native protocol URL (s3://bucket/path, sj://bucket/path, etc.).
35
25
  */
@@ -41,45 +31,32 @@ export function buildStorageUrl(tab) {
41
31
  return `${scheme}://${conn.bucket}/${tab.path.replace(/^\//, '')}`;
42
32
  }
43
33
  /**
44
- * Build the URL that DuckDB should use for queries.
45
- * - Azure: always HTTPS URL with SAS token appended
46
- * - Anonymous with custom endpoint (Storj, R2, etc.): HTTPS URL — no S3 config needed,
47
- * avoids endpoint/auth complexity, works directly via httpfs
48
- * - AWS S3 (no endpoint): s3:// DuckDB routes via configured region
49
- * - Authenticated with endpoint: s3:// needs S3 endpoint config for SigV4 signing
34
+ * Build the URL DuckDB should query. Derived from the connection's access mode:
35
+ *
36
+ * | Access mode | DuckDB URL | Why |
37
+ * |-----------------|-----------------------------------|-------------------------------------------|
38
+ * | `sas-https` | HTTPS with SAS token | No DuckDB Azure support; SAS in URL works |
39
+ * | `public-https` | HTTPS (no auth) | httpfs fetches directly, no signing needed|
40
+ * | `signed-s3` | `s3://bucket/key` | DuckDB signs with configured S3 settings |
41
+ *
42
+ * Path is percent-decoded so DuckDB's httpfs doesn't double-encode
43
+ * (e.g. Arabic filenames `%D9%85` → `%25D9%2585`).
50
44
  */
51
45
  export function buildDuckDbUrl(tab) {
52
46
  const conn = tab.connectionId ? connections.getById(tab.connectionId) : null;
53
47
  if (!conn)
54
48
  return tab.path;
55
- // Azure always uses HTTPS (DuckDB doesn't have native Azure Blob support)
56
- if (conn.provider === 'azure') {
57
- return buildHttpsUrl(tab);
58
- }
59
- // Anonymous connections with custom endpoints (Storj, R2, Wasabi, etc.)
60
- // use HTTPS directly — simpler and avoids S3 endpoint configuration.
61
- if (conn.anonymous && conn.endpoint) {
49
+ if (isPubliclyStreamable(conn))
62
50
  return buildHttpsUrl(tab);
63
- }
64
- // S3-compatible with credentials: use s3:// protocol so DuckDB uses its
65
- // configured S3 settings (region, endpoint, url_style) for SigV4 signing.
66
51
  // Decode percent-encoded paths (e.g. Arabic filenames) so DuckDB's httpfs
67
52
  // doesn't double-encode them (%D9%85 → %25D9%2585).
68
53
  const rawPath = safeDecodeURIComponent(tab.path.replace(/^\//, ''));
69
54
  return `s3://${conn.bucket}/${rawPath}`;
70
55
  }
71
- function safeDecodeURIComponent(s) {
72
- try {
73
- return decodeURIComponent(s);
74
- }
75
- catch {
76
- return s;
77
- }
78
- }
79
56
  /**
80
- * Check if a tab's file can be loaded directly via HTTPS URL (streaming).
81
- * True for URL-sourced tabs, anonymous buckets, and Azure (SAS token in URL).
82
- * False for authenticated S3 (needs signed URLs or blob download via adapter).
57
+ * True when any HTTP client (fetch/img/video/deck.gl/COG/Zarr/PMTiles) can
58
+ * load the tab's file directly via its HTTPS URL. False when SigV4 signing
59
+ * is required and the viewer must go through the storage adapter instead.
83
60
  */
84
61
  export function canStreamDirectly(tab) {
85
62
  if (tab.source === 'url')
@@ -87,11 +64,7 @@ export function canStreamDirectly(tab) {
87
64
  const conn = tab.connectionId ? connections.getById(tab.connectionId) : null;
88
65
  if (!conn)
89
66
  return true;
90
- if (conn.anonymous)
91
- return true;
92
- if (conn.provider === 'azure')
93
- return true;
94
- return false;
67
+ return isPubliclyStreamable(conn);
95
68
  }
96
69
  /**
97
70
  * Append Azure SAS token to a URL if available.
@@ -105,37 +78,3 @@ function appendAzureSas(url, connectionId) {
105
78
  const sep = url.includes('?') ? '&' : '?';
106
79
  return `${url}${sep}${cleanToken}`;
107
80
  }
108
- // ---------------------------------------------------------------------------
109
- // Cloud protocol URL → HTTPS conversion
110
- // ---------------------------------------------------------------------------
111
- /** AWS region pattern — matches prefixes like "us-west-2", "eu-central-1", etc. */
112
- const AWS_REGION_RE = /^(us|eu|ap|sa|ca|me|af|il)-(north|south|east|west|central|northeast|southeast|northwest|southwest)-\d+/;
113
- /**
114
- * Convert a cloud storage protocol URL (s3://, gs://) to an HTTPS URL
115
- * for browser access. Returns the original URL if already HTTP(S) or unknown.
116
- *
117
- * Supported:
118
- * - `s3://bucket/key` → `https://s3.{region}.amazonaws.com/{bucket}/{key}`
119
- * (region auto-detected from bucket name when possible, e.g. "us-west-2.opendata.source.coop")
120
- * - `gs://bucket/key` → `https://storage.googleapis.com/{bucket}/{key}`
121
- */
122
- export function resolveCloudUrl(url) {
123
- // S3 / S3-compatible: s3://, s3a://, s3n://
124
- const s3Match = url.match(/^s3[an]?:\/\/([^/]+)\/?(.*)$/);
125
- if (s3Match) {
126
- const [, bucket, key] = s3Match;
127
- // Detect region from bucket name (e.g. "us-west-2.opendata.source.coop")
128
- const regionMatch = bucket.match(AWS_REGION_RE);
129
- const region = regionMatch ? regionMatch[0] : 'us-east-1';
130
- const base = buildProviderBaseUrl('s3', '', bucket, region);
131
- return key ? `${base}/${key}` : base;
132
- }
133
- // Google Cloud Storage: gs://, gcs://
134
- const gcsMatch = url.match(/^gcs?:\/\/([^/]+)\/?(.*)$/);
135
- if (gcsMatch) {
136
- const [, bucket, key] = gcsMatch;
137
- const base = buildProviderBaseUrl('gcs', '', bucket, '');
138
- return key ? `${base}/${key}` : base;
139
- }
140
- return url;
141
- }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Zarr tab-opening helper.
3
+ * Centralizes Zarr store tab creation to avoid duplicating the same logic
4
+ * across FileBrowser, FileRow, FileTreeSidebar, and +page.svelte.
5
+ *
6
+ * Kept separate from zarr.ts to avoid adding a store dependency to a pure utility.
7
+ */
8
+ interface ZarrTabContext {
9
+ /** 'remote' for object-storage connections, 'url' for direct URL tabs. */
10
+ source: 'remote' | 'url';
11
+ /** Connection ID — required for remote sources. */
12
+ connectionId?: string;
13
+ /** Fallback name when the path has no meaningful last segment (e.g. bucket root). */
14
+ bucketFallback?: string;
15
+ }
16
+ /**
17
+ * Open a directory path as a Zarr store tab.
18
+ * Normalizes the path, derives a display name, and deduplicates via a
19
+ * deterministic tab ID so calling this twice with the same path is a no-op.
20
+ */
21
+ export declare function openZarrTab(dirPath: string, ctx: ZarrTabContext): void;
22
+ export {};
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Zarr tab-opening helper.
3
+ * Centralizes Zarr store tab creation to avoid duplicating the same logic
4
+ * across FileBrowser, FileRow, FileTreeSidebar, and +page.svelte.
5
+ *
6
+ * Kept separate from zarr.ts to avoid adding a store dependency to a pure utility.
7
+ */
8
+ import { tabs } from '../stores/tabs.svelte.js';
9
+ /**
10
+ * Open a directory path as a Zarr store tab.
11
+ * Normalizes the path, derives a display name, and deduplicates via a
12
+ * deterministic tab ID so calling this twice with the same path is a no-op.
13
+ */
14
+ export function openZarrTab(dirPath, ctx) {
15
+ const path = ctx.source === 'remote'
16
+ ? dirPath.endsWith('/')
17
+ ? dirPath
18
+ : `${dirPath}/`
19
+ : dirPath.replace(/\/+$/, '');
20
+ const name = path.replace(/\/+$/, '').split('/').pop()?.split('?')[0] || ctx.bucketFallback || 'zarr';
21
+ const id = ctx.connectionId ? `${ctx.connectionId}:${path}` : `url:${path}`;
22
+ tabs.open({
23
+ id,
24
+ name,
25
+ path,
26
+ source: ctx.source,
27
+ ...(ctx.connectionId ? { connectionId: ctx.connectionId } : {}),
28
+ extension: 'zarr'
29
+ });
30
+ }
@@ -62,8 +62,6 @@ export declare function computeUncompressed(shape: number[] | undefined, dtype:
62
62
  export declare function formatCodecs(node: ZarrNode): string | null;
63
63
  /** Format chunk_key_encoding for display: `"default (sep: "/")"` */
64
64
  export declare function formatChunkKeys(node: ZarrNode): string | null;
65
- /** Find a node by slash-delimited path. */
66
- export declare function findNodeByPath(root: ZarrNode, path: string): ZarrNode | null;
67
65
  /** Build tree from Zarr v3 consolidated metadata (zarr.json). */
68
66
  export declare function buildV3Tree(data: any): ZarrHierarchy;
69
67
  /** Build tree from Zarr v2 consolidated metadata (.zmetadata). */
@@ -238,20 +238,6 @@ export function formatCodecs(node) {
238
238
  export function formatChunkKeys(node) {
239
239
  return node.chunkKeyEncoding ?? null;
240
240
  }
241
- /** Find a node by slash-delimited path. */
242
- export function findNodeByPath(root, path) {
243
- if (path === '/' || path === '')
244
- return root;
245
- const parts = path.replace(/^\//, '').split('/');
246
- let current = root;
247
- for (const part of parts) {
248
- const child = current.children.find((c) => c.name === part);
249
- if (!child)
250
- return null;
251
- current = child;
252
- }
253
- return current;
254
- }
255
241
  // ---------------------------------------------------------------------------
256
242
  // Tree builders
257
243
  // ---------------------------------------------------------------------------
@@ -462,37 +448,14 @@ async function discoverV3Children(storeUrl, rootData, signal) {
462
448
  candidates.add(String(entry.asset));
463
449
  }
464
450
  }
451
+ // If no candidates from conventions, discover via S3 XML listing
452
+ if (candidates.size === 0) {
453
+ const discovered = await listS3Children(storeUrl, signal);
454
+ for (const name of discovered)
455
+ candidates.add(name);
456
+ }
465
457
  // Probe each candidate path for zarr.json
466
- const probes = [...candidates].map(async (name) => {
467
- try {
468
- const res = await fetch(`${storeUrl}/${name}/zarr.json`, { signal });
469
- if (!res.ok)
470
- return null;
471
- const data = await res.json();
472
- if (data.node_type === 'array' && data.shape) {
473
- const node = makeNode(`/${name}`, 'array', data.attributes ?? {});
474
- node.shape = data.shape;
475
- node.dtype = data.data_type ?? 'unknown';
476
- node.dims = data.dimension_names ?? inferDims(name, data.shape);
477
- node.chunks = data.chunk_grid?.configuration?.chunk_shape ?? [];
478
- node.fillValue = data.fill_value;
479
- node.codecs = data.codecs ?? [];
480
- const cke = data.chunk_key_encoding;
481
- if (cke) {
482
- const sep = cke.configuration?.separator ?? '/';
483
- node.chunkKeyEncoding = `${cke.name ?? 'default'} (sep: "${sep}")`;
484
- }
485
- return node;
486
- }
487
- if (data.node_type === 'group') {
488
- return makeNode(`/${name}`, 'group', data.attributes ?? {});
489
- }
490
- return null;
491
- }
492
- catch {
493
- return null;
494
- }
495
- });
458
+ const probes = [...candidates].map((name) => probeV3Child(storeUrl, name, signal));
496
459
  const results = await Promise.all(probes);
497
460
  for (const node of results) {
498
461
  if (node) {
@@ -509,6 +472,72 @@ async function discoverV3Children(storeUrl, rootData, signal) {
509
472
  spatialRefAttrs: null
510
473
  };
511
474
  }
475
+ /** Probe a single v3 child path and return a ZarrNode or null. */
476
+ async function probeV3Child(storeUrl, name, signal) {
477
+ try {
478
+ const res = await fetch(`${storeUrl}/${name}/zarr.json`, { signal });
479
+ if (!res.ok)
480
+ return null;
481
+ const data = await res.json();
482
+ if (data.node_type === 'array' && data.shape) {
483
+ const node = makeNode(`/${name}`, 'array', data.attributes ?? {});
484
+ node.shape = data.shape;
485
+ node.dtype = data.data_type ?? 'unknown';
486
+ node.dims = data.dimension_names ?? inferDims(name, data.shape);
487
+ node.chunks = data.chunk_grid?.configuration?.chunk_shape ?? [];
488
+ node.fillValue = data.fill_value;
489
+ node.codecs = data.codecs ?? [];
490
+ const cke = data.chunk_key_encoding;
491
+ if (cke) {
492
+ const sep = cke.configuration?.separator ?? '/';
493
+ node.chunkKeyEncoding = `${cke.name ?? 'default'} (sep: "${sep}")`;
494
+ }
495
+ return node;
496
+ }
497
+ if (data.node_type === 'group') {
498
+ return makeNode(`/${name}`, 'group', data.attributes ?? {});
499
+ }
500
+ return null;
501
+ }
502
+ catch {
503
+ return null;
504
+ }
505
+ }
506
+ /**
507
+ * Discover child directory names via S3 XML listing.
508
+ * Parses the HTTPS store URL to extract bucket and prefix, then issues
509
+ * a `list-type=2&delimiter=/` request to find sub-prefixes.
510
+ * Returns directory names (without trailing slash) that are NOT hidden (no leading dot).
511
+ */
512
+ async function listS3Children(storeUrl, signal) {
513
+ try {
514
+ const url = new URL(storeUrl);
515
+ // S3-style: bucket is first path segment, rest is prefix
516
+ const pathParts = url.pathname.replace(/^\//, '').split('/');
517
+ const bucket = pathParts[0];
518
+ const prefix = `${pathParts.slice(1).join('/').replace(/\/$/, '')}/`;
519
+ const listUrl = `${url.origin}/${bucket}/?list-type=2&prefix=${encodeURIComponent(prefix)}&delimiter=/`;
520
+ const res = await fetch(listUrl, { signal });
521
+ if (!res.ok)
522
+ return [];
523
+ const xml = await res.text();
524
+ const names = [];
525
+ // Parse <CommonPrefixes><Prefix>...</Prefix></CommonPrefixes>
526
+ const prefixRegex = /<Prefix>([^<]+)<\/Prefix>/g;
527
+ for (let match = prefixRegex.exec(xml); match; match = prefixRegex.exec(xml)) {
528
+ const fullPrefix = match[1];
529
+ // Strip parent prefix and trailing slash to get child name
530
+ const child = fullPrefix.slice(prefix.length).replace(/\/$/, '');
531
+ if (child && !child.startsWith('.')) {
532
+ names.push(child);
533
+ }
534
+ }
535
+ return names;
536
+ }
537
+ catch {
538
+ return [];
539
+ }
540
+ }
512
541
  /**
513
542
  * Fallback: probe a Zarr store using zarrita when consolidated metadata is unavailable.
514
543
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@walkthru-earth/objex",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "Svelte 5 components and utilities for exploring geospatial object storage — S3, GCS, Azure, R2",
5
5
  "author": "Youssef Harby <yharby@walkthru.earth>",
6
6
  "license": "CC-BY-4.0",
@@ -123,81 +123,84 @@
123
123
  }
124
124
  },
125
125
  "devDependencies": {
126
- "@biomejs/biome": "^2.4.6",
126
+ "@biomejs/biome": "^2.4.12",
127
127
  "@changesets/changelog-github": "^0.5.2",
128
- "@changesets/cli": "^2.30.0",
129
- "@internationalized/date": "^3.12.0",
128
+ "@changesets/cli": "^2.31.0",
129
+ "@fontsource/cairo": "^5.2.7",
130
+ "@internationalized/date": "^3.12.1",
130
131
  "@lucide/svelte": "^0.561.0",
131
132
  "@sveltejs/adapter-static": "^3.0.10",
132
- "@sveltejs/kit": "^2.53.4",
133
+ "@sveltejs/kit": "^2.57.1",
133
134
  "@sveltejs/package": "^2.5.7",
134
135
  "@sveltejs/vite-plugin-svelte": "^6.2.4",
135
136
  "@tailwindcss/forms": "^0.5.11",
136
137
  "@tailwindcss/typography": "^0.5.19",
137
- "@tailwindcss/vite": "^4.2.1",
138
- "bits-ui": "^2.16.3",
138
+ "@tailwindcss/vite": "^4.2.4",
139
+ "bits-ui": "^2.18.0",
139
140
  "clsx": "^2.1.1",
140
- "@fontsource/cairo": "^5.2.7",
141
- "lefthook": "^2.1.3",
141
+ "knip": "^6.6.0",
142
+ "lefthook": "^2.1.6",
142
143
  "paneforge": "^1.0.2",
143
- "posthog-js": "^1.360.0",
144
+ "posthog-js": "^1.369.5",
144
145
  "publint": "^0.3.18",
145
- "svelte": "^5.53.9",
146
- "svelte-check": "^4.4.5",
146
+ "svelte": "^5.55.4",
147
+ "svelte-check": "^4.4.6",
147
148
  "tailwind-merge": "^3.5.0",
148
149
  "tailwind-variants": "^3.2.2",
149
- "tailwindcss": "^4.2.1",
150
+ "tailwindcss": "^4.2.4",
150
151
  "tw-animate-css": "^1.4.0",
151
152
  "typescript": "^5.9.3",
152
- "vite": "^7.3.1"
153
+ "vite": "^7.3.2"
153
154
  },
154
155
  "dependencies": {
155
- "@babylonjs/core": "^8.54.1",
156
- "@babylonjs/loaders": "^8.54.1",
157
- "@carbonplan/zarr-layer": "^0.3.1",
156
+ "@babylonjs/core": "^8.56.2",
157
+ "@babylonjs/loaders": "^8.56.2",
158
+ "@carbonplan/zarr-layer": "^0.4.3",
158
159
  "@codemirror/autocomplete": "^6.20.1",
159
- "@codemirror/commands": "^6.10.2",
160
+ "@codemirror/commands": "^6.10.3",
160
161
  "@codemirror/lang-sql": "^6.10.0",
161
- "@codemirror/language": "^6.12.2",
162
- "@codemirror/state": "^6.5.4",
162
+ "@codemirror/language": "^6.12.3",
163
+ "@codemirror/state": "^6.6.0",
163
164
  "@codemirror/theme-one-dark": "^6.1.3",
164
- "@codemirror/view": "^6.39.16",
165
- "@deck.gl/core": "^9.2.11",
166
- "@deck.gl/geo-layers": "^9.2.11",
167
- "@deck.gl/layers": "^9.2.11",
168
- "@deck.gl/mapbox": "^9.2.11",
169
- "@deck.gl/mesh-layers": "^9.2.11",
170
- "@developmentseed/deck.gl-geotiff": "^0.2.0",
171
- "@duckdb/duckdb-wasm": "1.33.1-dev34.0",
172
- "@geoarrow/deck.gl-layers": "^0.3.1",
173
- "@luma.gl/core": "^9.2.6",
165
+ "@codemirror/view": "^6.41.1",
166
+ "@deck.gl/core": "^9.3.1",
167
+ "@deck.gl/geo-layers": "^9.3.1",
168
+ "@deck.gl/layers": "^9.3.1",
169
+ "@deck.gl/mapbox": "^9.3.1",
170
+ "@deck.gl/mesh-layers": "^9.3.1",
171
+ "@developmentseed/deck.gl-geotiff": "^0.5.0",
172
+ "@developmentseed/deck.gl-raster": "^0.5.0",
173
+ "@developmentseed/epsg": "^0.5.0",
174
+ "@developmentseed/geotiff": "^0.5.0",
175
+ "@developmentseed/proj": "^0.5.0",
176
+ "@duckdb/duckdb-wasm": "1.33.1-dev53.0",
177
+ "@geoarrow/deck.gl-layers": "^0.3.2",
178
+ "@luma.gl/core": "^9.3.3",
174
179
  "@mapbox/vector-tile": "^2.0.4",
175
- "@milkdown/kit": "^7.19.0",
176
- "@milkdown/theme-nord": "^7.19.0",
180
+ "@milkdown/kit": "^7.20.0",
181
+ "@milkdown/theme-nord": "^7.20.0",
177
182
  "@repeaterjs/repeater": "^3.0.6",
178
- "@zip.js/zip.js": "^2.8.23",
183
+ "@zip.js/zip.js": "^2.8.26",
179
184
  "ansi_up": "^6.0.6",
180
185
  "apache-arrow": "^21.1.0",
181
186
  "aws4fetch": "^1.0.20",
182
187
  "chart.js": "^4.5.1",
183
- "deck.gl": "^9.2.11",
188
+ "deck.gl": "^9.3.1",
184
189
  "flatgeobuf": "^4.4.0",
185
- "geotiff": "^3.0.4",
186
- "geotiff-geokeys-to-proj4": "^2024.4.13",
187
- "hyparquet": "^1.25.1",
190
+ "hyparquet": "^1.25.6",
188
191
  "hyparquet-compressors": "^1.1.1",
189
192
  "lz-string": "^1.5.0",
190
- "maplibre-gl": "^5.19.0",
191
- "marked": "^17.0.4",
192
- "mermaid": "^11.13.0",
193
+ "maplibre-gl": "^5.23.0",
194
+ "marked": "^17.0.6",
195
+ "mermaid": "^11.14.0",
193
196
  "pbf": "^4.0.1",
194
- "pdfjs-dist": "^5.5.207",
195
- "pmtiles": "^4.4.0",
196
- "proj4": "^2.20.4",
197
+ "pdfjs-dist": "^5.6.205",
198
+ "pmtiles": "^4.4.1",
199
+ "proj4": "^2.20.8",
197
200
  "shiki": "^3.23.0",
198
- "sql-formatter": "^15.7.2",
199
- "yaml": "^2.8.2",
200
- "zarrita": "^0.6.1"
201
+ "sql-formatter": "^15.7.3",
202
+ "yaml": "^2.8.3",
203
+ "zarrita": "^0.6.2"
201
204
  },
202
205
  "scripts": {
203
206
  "dev": "vite dev",
@@ -210,6 +213,7 @@
210
213
  "lint:fix": "biome lint --fix src/ packages/",
211
214
  "format": "biome format --write src/ packages/",
212
215
  "format:check": "biome format src/ packages/",
216
+ "deadcode": "knip",
213
217
  "ci:publish": "pnpm run package && pnpm --filter @walkthru-earth/objex-utils run build && pnpm publish -r --access public --no-git-checks --provenance"
214
218
  }
215
219
  }
@@ -1,5 +0,0 @@
1
- import Root from './tabs.svelte';
2
- import Content from './tabs-content.svelte';
3
- import List from './tabs-list.svelte';
4
- import Trigger from './tabs-trigger.svelte';
5
- export { Root, Content, List, Trigger, Root as Tabs, Content as TabsContent, List as TabsList, Trigger as TabsTrigger };
@@ -1,7 +0,0 @@
1
- import Root from './tabs.svelte';
2
- import Content from './tabs-content.svelte';
3
- import List from './tabs-list.svelte';
4
- import Trigger from './tabs-trigger.svelte';
5
- export { Root, Content, List, Trigger,
6
- //
7
- Root as Tabs, Content as TabsContent, List as TabsList, Trigger as TabsTrigger };
@@ -1,17 +0,0 @@
1
- <script lang="ts">
2
- import { Tabs as TabsPrimitive } from 'bits-ui';
3
- import { cn } from '../../../utils.js';
4
-
5
- let {
6
- ref = $bindable(null),
7
- class: className,
8
- ...restProps
9
- }: TabsPrimitive.ContentProps = $props();
10
- </script>
11
-
12
- <TabsPrimitive.Content
13
- bind:ref
14
- data-slot="tabs-content"
15
- class={cn("flex-1 outline-none", className)}
16
- {...restProps}
17
- />
@@ -1,4 +0,0 @@
1
- import { Tabs as TabsPrimitive } from 'bits-ui';
2
- declare const TabsContent: import("svelte").Component<TabsPrimitive.ContentProps, {}, "ref">;
3
- type TabsContent = ReturnType<typeof TabsContent>;
4
- export default TabsContent;
@@ -1,16 +0,0 @@
1
- <script lang="ts">
2
- import { Tabs as TabsPrimitive } from 'bits-ui';
3
- import { cn } from '../../../utils.js';
4
-
5
- let { ref = $bindable(null), class: className, ...restProps }: TabsPrimitive.ListProps = $props();
6
- </script>
7
-
8
- <TabsPrimitive.List
9
- bind:ref
10
- data-slot="tabs-list"
11
- class={cn(
12
- "bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
13
- className
14
- )}
15
- {...restProps}
16
- />
@@ -1,4 +0,0 @@
1
- import { Tabs as TabsPrimitive } from 'bits-ui';
2
- declare const TabsList: import("svelte").Component<TabsPrimitive.ListProps, {}, "ref">;
3
- type TabsList = ReturnType<typeof TabsList>;
4
- export default TabsList;
@@ -1,20 +0,0 @@
1
- <script lang="ts">
2
- import { Tabs as TabsPrimitive } from 'bits-ui';
3
- import { cn } from '../../../utils.js';
4
-
5
- let {
6
- ref = $bindable(null),
7
- class: className,
8
- ...restProps
9
- }: TabsPrimitive.TriggerProps = $props();
10
- </script>
11
-
12
- <TabsPrimitive.Trigger
13
- bind:ref
14
- data-slot="tabs-trigger"
15
- class={cn(
16
- "data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
17
- className
18
- )}
19
- {...restProps}
20
- />
@@ -1,4 +0,0 @@
1
- import { Tabs as TabsPrimitive } from 'bits-ui';
2
- declare const TabsTrigger: import("svelte").Component<TabsPrimitive.TriggerProps, {}, "ref">;
3
- type TabsTrigger = ReturnType<typeof TabsTrigger>;
4
- export default TabsTrigger;
@@ -1,19 +0,0 @@
1
- <script lang="ts">
2
- import { Tabs as TabsPrimitive } from 'bits-ui';
3
- import { cn } from '../../../utils.js';
4
-
5
- let {
6
- ref = $bindable(null),
7
- value = $bindable(''),
8
- class: className,
9
- ...restProps
10
- }: TabsPrimitive.RootProps = $props();
11
- </script>
12
-
13
- <TabsPrimitive.Root
14
- bind:ref
15
- bind:value
16
- data-slot="tabs"
17
- class={cn("flex flex-col gap-2", className)}
18
- {...restProps}
19
- />
@@ -1,4 +0,0 @@
1
- import { Tabs as TabsPrimitive } from 'bits-ui';
2
- declare const Tabs: import("svelte").Component<TabsPrimitive.RootProps, {}, "value" | "ref">;
3
- type Tabs = ReturnType<typeof Tabs>;
4
- export default Tabs;