precision-dashwidgets 0.5.1 → 0.5.3
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/README.md +413 -3
- package/dist/{deflate-BQVLA3Ul.mjs → deflate-CPNmBnej.mjs} +1 -1
- package/dist/index-CRAkqt4--BsX7X3Wy.mjs +4 -0
- package/dist/{index-BHHg5z03.mjs → index-DVfUy50r.mjs} +9 -9
- package/dist/{index-Hx8PFhs9.mjs → index-Dl_ufo4v.mjs} +4730 -4703
- package/dist/index-GF8k2nCC-rI2ZXyL4.mjs +4 -0
- package/dist/{index-Oh_goZGT-H9AAGZr8.mjs → index-Oh_goZGT-DPkK2gVA.mjs} +2 -2
- package/dist/{index-UOUUzHJY-DJVMXBUa.mjs → index-UOUUzHJY-D0LsTUPc.mjs} +1 -1
- package/dist/{index-dhOjlnSX-Biz-kopS.mjs → index-dhOjlnSX---XHbE5y.mjs} +1 -1
- package/dist/{index-u1qleOVs-ZJVnnKAV.mjs → index-u1qleOVs-BH1yx7WW.mjs} +2 -2
- package/dist/{jpeg-l5M1J8Gh.mjs → jpeg-CXAyIdl8.mjs} +1 -1
- package/dist/{lerc-BipMr5R9.mjs → lerc-DmIa8s0n.mjs} +2 -2
- package/dist/{lerc-XufrP0FH-SNCeY3ab.mjs → lerc-XufrP0FH-Cp9B8C70.mjs} +1 -1
- package/dist/{lzw-u9cBMr9g.mjs → lzw-Bh2N3zBo.mjs} +1 -1
- package/dist/{packbits-dQba4PyI.mjs → packbits-DaRNs4L0.mjs} +1 -1
- package/dist/precision-dashwidgets.es.js +11 -7
- package/dist/precision-dashwidgets.umd.js +175 -175
- package/dist/{raw-KFPBw5cQ.mjs → raw-CommQb0l.mjs} +1 -1
- package/dist/style.css +1 -1
- package/dist/{webimage-CBOAIeUr.mjs → webimage-BKZpDwde.mjs} +1 -1
- package/package.json +1 -1
- package/dist/index-CRAkqt4--8ZLRoGIu.mjs +0 -4
- package/dist/index-GF8k2nCC-DnpFPSAr.mjs +0 -4
package/README.md
CHANGED
|
@@ -1,5 +1,415 @@
|
|
|
1
|
-
#
|
|
1
|
+
# precision-dashwidgets
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Interactive genomics visualization widgets built with Vue 3. These components provide gene expression analysis, dimensionality reduction plots (UMAP/tSNE), and distribution visualizations powered by DuckDB WASM for client-side querying of Parquet data files.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Components
|
|
6
|
+
|
|
7
|
+
### GeneExpression
|
|
8
|
+
|
|
9
|
+
Gene co-expression analysis widget. Renders a scatter plot (UMAP or tSNE) colored by the co-expression of two selected genes. Includes autocomplete gene search, dual gene selection, and a statistics panel.
|
|
10
|
+
|
|
11
|
+
| Prop | Type | Description |
|
|
12
|
+
|------|------|-------------|
|
|
13
|
+
| `dataPath` | `string?` | URL to data directory containing Parquet files. Falls back to injected `s3Url`, then the default. |
|
|
14
|
+
| `initialGene1` | `string?` | Pre-selected first gene (e.g. `"CDH9"`) |
|
|
15
|
+
| `initialGene2` | `string?` | Pre-selected second gene (e.g. `"TAC1"`) |
|
|
16
|
+
|
|
17
|
+
### SideBySide
|
|
18
|
+
|
|
19
|
+
Dual-panel comparison widget. Left panel shows a UMAP colored by a selected metadata column (cell type, cluster, etc.). Right panel shows a UMAP colored by expression level of a selected gene. Useful for comparing spatial clustering against gene expression patterns.
|
|
20
|
+
|
|
21
|
+
| Prop | Type | Description |
|
|
22
|
+
|------|------|-------------|
|
|
23
|
+
| `dataPath` | `string?` | URL to data directory containing Parquet files. Falls back to injected `s3Url`, then the default. |
|
|
24
|
+
| `initialGene` | `string?` | Pre-selected gene for the expression panel |
|
|
25
|
+
| `initialMetadataColumn` | `string?` | Pre-selected metadata column for the metadata panel |
|
|
26
|
+
|
|
27
|
+
### ViolinPlot (also exported as `GeneXDistribution`)
|
|
28
|
+
|
|
29
|
+
Gene expression distribution widget. Renders violin or box plots showing the distribution of a gene's expression across metadata categories. Supports toggling between violin and box plot modes, and can overlay individual data points.
|
|
30
|
+
|
|
31
|
+
| Prop | Type | Description |
|
|
32
|
+
|------|------|-------------|
|
|
33
|
+
| `dataPath` | `string?` | URL to data directory containing Parquet files. Falls back to injected `s3Url`, then the default. |
|
|
34
|
+
| `initialGene` | `string?` | Pre-selected gene |
|
|
35
|
+
| `initialMetadataColumn` | `string?` | Pre-selected metadata column for x-axis grouping |
|
|
36
|
+
|
|
37
|
+
### Additional Components
|
|
38
|
+
|
|
39
|
+
- **DataExplorer** - Data exploration interface
|
|
40
|
+
- **UMAP** - Standalone UMAP visualization
|
|
41
|
+
- **ProportionPlot** - Cell proportion visualization
|
|
42
|
+
|
|
43
|
+
## Data Requirements
|
|
44
|
+
|
|
45
|
+
All components use DuckDB WASM to query Parquet files from a remote data path (S3 or any HTTP-accessible location). The data path must contain the following files:
|
|
46
|
+
|
|
47
|
+
| File | Required | Description |
|
|
48
|
+
|------|----------|-------------|
|
|
49
|
+
| `umap_complete.parquet` | Yes | UMAP coordinates + cell metadata |
|
|
50
|
+
| `tsne_complete.parquet` | No | tSNE coordinates (enables tSNE option in GeneExpression) |
|
|
51
|
+
| `gene_locations.parquet` | Yes | Mapping of gene names to their data file locations |
|
|
52
|
+
| `gene_stats.parquet` | Yes | Gene-level statistics used for search/autocomplete |
|
|
53
|
+
| `cells.parquet` | Yes | Cell metadata (cell types, clusters, etc.) |
|
|
54
|
+
| `metadata.parquet` | No | Alternative/extended metadata source |
|
|
55
|
+
| `genes.parquet` | Yes | Gene name to ID mapping |
|
|
56
|
+
|
|
57
|
+
Gene expression values are loaded on-demand from individual or chunked Parquet files referenced in `gene_locations.parquet`.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Use Case 1: Inside the Pennsieve Dashboard
|
|
62
|
+
|
|
63
|
+
When used within the `pennsieve-dashboard`, components are provided context automatically via Vue's `provide`/`inject` and a shared Pinia store.
|
|
64
|
+
|
|
65
|
+
### Install
|
|
66
|
+
|
|
67
|
+
The package is already a workspace dependency. If needed:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npm install precision-dashwidgets
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Import Components
|
|
74
|
+
|
|
75
|
+
```js
|
|
76
|
+
import {
|
|
77
|
+
GeneExpression,
|
|
78
|
+
SideBySide,
|
|
79
|
+
ViolinPlot, // or GeneXDistribution
|
|
80
|
+
} from 'precision-dashwidgets'
|
|
81
|
+
import 'precision-dashwidgets/style.css'
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Register in a Layout
|
|
85
|
+
|
|
86
|
+
The dashboard uses a widget layout system. Register components in your layout config:
|
|
87
|
+
|
|
88
|
+
```js
|
|
89
|
+
const defaultLayout = [
|
|
90
|
+
{
|
|
91
|
+
id: 'GeneExpression-0',
|
|
92
|
+
x: 0, y: 0, w: 3, h: 8,
|
|
93
|
+
componentKey: 'GeneExpression',
|
|
94
|
+
componentName: 'Gene Co-expression',
|
|
95
|
+
component: GeneExpression,
|
|
96
|
+
Props: {
|
|
97
|
+
initialGene1: 'CDH9',
|
|
98
|
+
initialGene2: 'TAC1',
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
id: 'SideBySide-0',
|
|
103
|
+
x: 3, y: 0, w: 3, h: 8,
|
|
104
|
+
componentKey: 'SideBySide',
|
|
105
|
+
componentName: 'Side by Side',
|
|
106
|
+
component: SideBySide,
|
|
107
|
+
Props: {
|
|
108
|
+
initialGene: 'CDH9',
|
|
109
|
+
initialMetadataColumn: 'cell_type',
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
id: 'ViolinPlot-0',
|
|
114
|
+
x: 0, y: 8, w: 3, h: 8,
|
|
115
|
+
componentKey: 'ViolinPlot',
|
|
116
|
+
componentName: 'Gene Distribution',
|
|
117
|
+
component: ViolinPlot,
|
|
118
|
+
Props: {
|
|
119
|
+
initialGene: 'CDH9',
|
|
120
|
+
initialMetadataColumn: 'cell_type',
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
]
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### How State Flows in the Dashboard
|
|
127
|
+
|
|
128
|
+
The dashboard provides two context mechanisms:
|
|
129
|
+
|
|
130
|
+
1. **Global vars injection** (`DASHBOARD_GLOBAL_VARS_KEY`) - provides `s3Url`, `apiUrl`, and shared filters via `provide`/`inject`.
|
|
131
|
+
2. **Pinia store** (`usePrecisionStore`) - shared reactive state for gene and metadata selections across all widgets. When a user selects a gene in one widget, other widgets can react.
|
|
132
|
+
|
|
133
|
+
These are wired automatically when used inside the dashboard framework.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Use Case 2: Standalone (Without Pennsieve Dashboard)
|
|
138
|
+
|
|
139
|
+
You can use these components in any Vue 3 application. This requires setting up the dependencies that the dashboard normally provides.
|
|
140
|
+
|
|
141
|
+
### Install
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
npm install precision-dashwidgets
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Peer Dependencies
|
|
148
|
+
|
|
149
|
+
Install the required peer dependencies:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
npm install vue pinia element-plus @element-plus/icons-vue
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Setup
|
|
156
|
+
|
|
157
|
+
#### 1. Register Pinia and Element Plus
|
|
158
|
+
|
|
159
|
+
```js
|
|
160
|
+
// main.ts
|
|
161
|
+
import { createApp } from 'vue'
|
|
162
|
+
import { createPinia } from 'pinia'
|
|
163
|
+
import ElementPlus from 'element-plus'
|
|
164
|
+
import 'element-plus/dist/index.css'
|
|
165
|
+
import App from './App.vue'
|
|
166
|
+
|
|
167
|
+
const app = createApp(App)
|
|
168
|
+
app.use(createPinia())
|
|
169
|
+
app.use(ElementPlus)
|
|
170
|
+
app.mount('#app')
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
#### 2. Import Styles
|
|
174
|
+
|
|
175
|
+
```js
|
|
176
|
+
import 'precision-dashwidgets/style.css'
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
#### 3. Use the Components
|
|
180
|
+
|
|
181
|
+
The simplest approach is to pass your data URL directly via the `dataPath` prop. Your directory must contain the same Parquet file names listed in [Data Requirements](#data-requirements).
|
|
182
|
+
|
|
183
|
+
```vue
|
|
184
|
+
<template>
|
|
185
|
+
<div style="height: 600px; width: 100%;">
|
|
186
|
+
<GeneExpression
|
|
187
|
+
dataPath="https://your-bucket.s3.amazonaws.com/your-dataset"
|
|
188
|
+
initialGene1="CDH9"
|
|
189
|
+
initialGene2="TAC1"
|
|
190
|
+
/>
|
|
191
|
+
</div>
|
|
192
|
+
|
|
193
|
+
<div style="height: 600px; width: 100%;">
|
|
194
|
+
<SideBySide
|
|
195
|
+
dataPath="https://your-bucket.s3.amazonaws.com/your-dataset"
|
|
196
|
+
initialGene="CDH9"
|
|
197
|
+
initialMetadataColumn="cell_type"
|
|
198
|
+
/>
|
|
199
|
+
</div>
|
|
200
|
+
|
|
201
|
+
<div style="height: 500px; width: 100%;">
|
|
202
|
+
<ViolinPlot
|
|
203
|
+
dataPath="https://your-bucket.s3.amazonaws.com/your-dataset"
|
|
204
|
+
initialGene="CDH9"
|
|
205
|
+
initialMetadataColumn="cell_type"
|
|
206
|
+
/>
|
|
207
|
+
</div>
|
|
208
|
+
</template>
|
|
209
|
+
|
|
210
|
+
<script setup>
|
|
211
|
+
import {
|
|
212
|
+
GeneExpression,
|
|
213
|
+
SideBySide,
|
|
214
|
+
ViolinPlot,
|
|
215
|
+
} from 'precision-dashwidgets'
|
|
216
|
+
</script>
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
#### Alternative: Provide Global Vars (set data path once)
|
|
220
|
+
|
|
221
|
+
Instead of passing `dataPath` to every component, you can provide `DASHBOARD_GLOBAL_VARS_KEY` in an ancestor component. All widgets will inherit the `s3Url` from it:
|
|
222
|
+
|
|
223
|
+
```vue
|
|
224
|
+
<script setup>
|
|
225
|
+
import { provide, ref } from 'vue'
|
|
226
|
+
import { DASHBOARD_GLOBAL_VARS_KEY } from 'precision-dashwidgets'
|
|
227
|
+
|
|
228
|
+
provide(DASHBOARD_GLOBAL_VARS_KEY, {
|
|
229
|
+
s3Url: ref('https://your-bucket.s3.amazonaws.com/your-dataset'),
|
|
230
|
+
apiUrl: ref(''),
|
|
231
|
+
filters: ref({}),
|
|
232
|
+
setFilter: () => {},
|
|
233
|
+
clearFilter: () => {},
|
|
234
|
+
})
|
|
235
|
+
</script>
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
**Resolution order:** `dataPath` prop > injected `s3Url` > built-in default URL.
|
|
239
|
+
|
|
240
|
+
### Accessing Shared State
|
|
241
|
+
|
|
242
|
+
If you need to read or control widget selections programmatically, import the Pinia store:
|
|
243
|
+
|
|
244
|
+
```js
|
|
245
|
+
import { usePrecisionStore } from 'precision-dashwidgets'
|
|
246
|
+
|
|
247
|
+
const store = usePrecisionStore()
|
|
248
|
+
|
|
249
|
+
// Read current selections
|
|
250
|
+
console.log(store.selectedGene)
|
|
251
|
+
console.log(store.selectedMetadataColumn)
|
|
252
|
+
|
|
253
|
+
// Set selections programmatically
|
|
254
|
+
store.setSelectedGene('TAC1')
|
|
255
|
+
store.setSelectedMetadataColumn('cluster')
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
#### Store Properties
|
|
259
|
+
|
|
260
|
+
| Property | Used By | Description |
|
|
261
|
+
|----------|---------|-------------|
|
|
262
|
+
| `selectedGene` | SideBySide | Currently selected gene |
|
|
263
|
+
| `selectedMetadataColumn` | SideBySide, ViolinPlot | Currently selected metadata column |
|
|
264
|
+
| `selectedGene1` | GeneExpression | First gene in co-expression |
|
|
265
|
+
| `selectedGene2` | GeneExpression | Second gene in co-expression |
|
|
266
|
+
| `selectedGeneX` | ViolinPlot | Selected gene for distribution plot |
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## Exports
|
|
271
|
+
|
|
272
|
+
```js
|
|
273
|
+
// Components
|
|
274
|
+
export { GeneExpression } // Gene co-expression analysis
|
|
275
|
+
export { SideBySide } // Dual UMAP comparison
|
|
276
|
+
export { ViolinPlot } // Violin/box plot (alias for GeneXDistribution)
|
|
277
|
+
export { GeneXDistribution } // Violin/box plot (original name)
|
|
278
|
+
export { DataExplorer } // Data exploration
|
|
279
|
+
export { UMAP } // Standalone UMAP
|
|
280
|
+
export { ProportionPlot } // Proportion visualization
|
|
281
|
+
|
|
282
|
+
// Utilities
|
|
283
|
+
export { usePrecisionStore } // Pinia store for shared widget state
|
|
284
|
+
export { useDashboardGlobalVars } // Composable to access injected global vars
|
|
285
|
+
export { DASHBOARD_GLOBAL_VARS_KEY } // Injection key for providing global vars
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## Bringing Your Own Data
|
|
289
|
+
|
|
290
|
+
You can point the widgets at any HTTP-accessible directory, as long as it contains Parquet files with the **exact names** listed in [Data Requirements](#data-requirements). The internal `dataManager` appends those filenames to whatever base path you provide (e.g. `{dataPath}/umap_complete.parquet`).
|
|
291
|
+
|
|
292
|
+
Currently there is no way to customize file names, column mappings, or the data schema. See the roadmap below for planned support.
|
|
293
|
+
|
|
294
|
+
## Known Limitations
|
|
295
|
+
|
|
296
|
+
- **Fixed Parquet file names**: Your data directory must use the exact file names the `dataManager` expects (`umap_complete.parquet`, `genes.parquet`, etc.). Custom naming is not yet supported.
|
|
297
|
+
- **Fixed column schema**: The components expect specific column names inside the Parquet files (e.g. UMAP coordinates, gene expression values). These cannot be remapped yet.
|
|
298
|
+
- **DuckDB WASM**: Components initialize a DuckDB WASM instance at mount time, which downloads the DuckDB worker from jsDelivr CDN. Ensure your environment allows loading scripts from `cdn.jsdelivr.net`.
|
|
299
|
+
- **Sizing**: Components expand to fill their parent container. Wrap them in a container with explicit `height` and `width`.
|
|
300
|
+
- **One DuckDB instance per component**: Each widget creates its own `UMAPGeneViewer` / DuckDB instance. If you mount multiple widgets, they each load data independently.
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Roadmap: Configurable Data Schema
|
|
305
|
+
|
|
306
|
+
Currently the `dataManager` has hardcoded file names and column expectations. The plan for making this fully configurable:
|
|
307
|
+
|
|
308
|
+
### Phase 1 - Data Config Object
|
|
309
|
+
|
|
310
|
+
Introduce a `DataConfig` type that maps logical data roles to actual file paths and column names:
|
|
311
|
+
|
|
312
|
+
```ts
|
|
313
|
+
interface DataConfig {
|
|
314
|
+
// Base URL for all data files
|
|
315
|
+
basePath: string
|
|
316
|
+
|
|
317
|
+
// File name overrides (defaults to current names)
|
|
318
|
+
files: {
|
|
319
|
+
umap?: string // default: "umap_complete.parquet"
|
|
320
|
+
tsne?: string // default: "tsne_complete.parquet"
|
|
321
|
+
geneLocations?: string // default: "gene_locations.parquet"
|
|
322
|
+
geneStats?: string // default: "gene_stats.parquet"
|
|
323
|
+
cells?: string // default: "cells.parquet"
|
|
324
|
+
metadata?: string // default: "metadata.parquet"
|
|
325
|
+
genes?: string // default: "genes.parquet"
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Column name mappings per file
|
|
329
|
+
columns: {
|
|
330
|
+
umap?: {
|
|
331
|
+
x?: string // default: "umap_1"
|
|
332
|
+
y?: string // default: "umap_2"
|
|
333
|
+
cellId?: string // default: "cell_id"
|
|
334
|
+
}
|
|
335
|
+
tsne?: {
|
|
336
|
+
x?: string // default: "tsne_1"
|
|
337
|
+
y?: string // default: "tsne_2"
|
|
338
|
+
}
|
|
339
|
+
genes?: {
|
|
340
|
+
name?: string // default: "gene_name"
|
|
341
|
+
id?: string // default: "gene_id"
|
|
342
|
+
}
|
|
343
|
+
// ... etc for each file
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Phase 2 - Update dataManager.js
|
|
349
|
+
|
|
350
|
+
Refactor `UMAPGeneViewer` to accept a `DataConfig` instead of a plain `basePath` string:
|
|
351
|
+
|
|
352
|
+
1. `loadEssentialData()` reads file paths from `config.files` instead of hardcoded names.
|
|
353
|
+
2. All SQL queries use `config.columns` mappings instead of hardcoded column names.
|
|
354
|
+
3. Merge user-provided config with defaults so only overrides need to be specified.
|
|
355
|
+
|
|
356
|
+
### Phase 3 - Shared DuckDB Instance
|
|
357
|
+
|
|
358
|
+
Instead of each component creating its own DuckDB instance:
|
|
359
|
+
|
|
360
|
+
1. Create a `useDataManager()` composable that provides a singleton `UMAPGeneViewer` via `provide`/`inject`.
|
|
361
|
+
2. Components call `useDataManager()` to get the shared instance.
|
|
362
|
+
3. The config is set once at the provider level, all widgets share the connection and cache.
|
|
363
|
+
|
|
364
|
+
### Phase 4 - Component Props
|
|
365
|
+
|
|
366
|
+
Wire the config through the component layer:
|
|
367
|
+
|
|
368
|
+
1. Wrapper components accept an optional `dataConfig` prop.
|
|
369
|
+
2. If not provided, fall back to the injected shared instance.
|
|
370
|
+
3. The `provide` approach from Phase 3 becomes the recommended setup for standalone users.
|
|
371
|
+
|
|
372
|
+
This would let standalone users do:
|
|
373
|
+
|
|
374
|
+
```vue
|
|
375
|
+
<script setup>
|
|
376
|
+
import { provide } from 'vue'
|
|
377
|
+
import { createDataProvider } from 'precision-dashwidgets'
|
|
378
|
+
|
|
379
|
+
const dataProvider = createDataProvider({
|
|
380
|
+
basePath: 'https://my-bucket.s3.amazonaws.com/my-data',
|
|
381
|
+
files: {
|
|
382
|
+
umap: 'embeddings.parquet',
|
|
383
|
+
genes: 'gene_index.parquet',
|
|
384
|
+
},
|
|
385
|
+
columns: {
|
|
386
|
+
umap: { x: 'dim1', y: 'dim2' },
|
|
387
|
+
},
|
|
388
|
+
})
|
|
389
|
+
|
|
390
|
+
provide('precision:data', dataProvider)
|
|
391
|
+
</script>
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
## Development
|
|
395
|
+
|
|
396
|
+
```bash
|
|
397
|
+
# Start dev server
|
|
398
|
+
npm run dev
|
|
399
|
+
|
|
400
|
+
# Build library
|
|
401
|
+
npm run build
|
|
402
|
+
|
|
403
|
+
# Preview build
|
|
404
|
+
npm run preview
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
## Tech Stack
|
|
408
|
+
|
|
409
|
+
- **Vue 3** - Component framework
|
|
410
|
+
- **DuckDB WASM** - Client-side SQL engine for Parquet file queries
|
|
411
|
+
- **D3.js** - SVG-based visualizations (violin plots, axes, legends)
|
|
412
|
+
- **regl** - WebGL rendering for high-performance scatter plots
|
|
413
|
+
- **Pinia** - State management across widgets
|
|
414
|
+
- **Element Plus** - UI components (dropdowns, inputs)
|
|
415
|
+
- **Vite** - Build tooling (library mode)
|
|
@@ -2,7 +2,7 @@ var Ky = Object.defineProperty;
|
|
|
2
2
|
var Oy = (t, A, e) => A in t ? Ky(t, A, { enumerable: !0, configurable: !0, writable: !0, value: e }) : t[A] = e;
|
|
3
3
|
var f = (t, A, e) => Oy(t, typeof A != "symbol" ? A + "" : A, e);
|
|
4
4
|
import { defineComponent as pC, ref as ee, watch as jI, onMounted as Hf, onUnmounted as Yf, openBlock as Ne, createElementBlock as ve, unref as Bo, createElementVNode as _A, createCommentVNode as vt, toDisplayString as Mo, Fragment as Wy, createVNode as Vy, nextTick as zy, normalizeStyle as Xy, computed as ll, createTextVNode as El, normalizeClass as jy } from "vue";
|
|
5
|
-
import { g as Zy } from "./index-
|
|
5
|
+
import { g as Zy } from "./index-Dl_ufo4v.mjs";
|
|
6
6
|
function sa(t, A) {
|
|
7
7
|
if (!t)
|
|
8
8
|
throw new Error(A || "loader assertion failed.");
|
|
@@ -28949,19 +28949,19 @@ const U0 = {
|
|
|
28949
28949
|
function Ht(t, A) {
|
|
28950
28950
|
Array.isArray(t) || (t = [t]), t.forEach((e) => Jk.set(e, A));
|
|
28951
28951
|
}
|
|
28952
|
-
Ht([void 0, 1], () => import("./raw-
|
|
28953
|
-
Ht(5, () => import("./lzw-
|
|
28952
|
+
Ht([void 0, 1], () => import("./raw-CommQb0l.mjs").then((t) => t.default));
|
|
28953
|
+
Ht(5, () => import("./lzw-Bh2N3zBo.mjs").then((t) => t.default));
|
|
28954
28954
|
Ht(6, () => {
|
|
28955
28955
|
throw new Error("old style JPEG compression is not supported.");
|
|
28956
28956
|
});
|
|
28957
|
-
Ht(7, () => import("./jpeg-
|
|
28958
|
-
Ht([8, 32946], () => import("./deflate-
|
|
28959
|
-
Ht(32773, () => import("./packbits-
|
|
28957
|
+
Ht(7, () => import("./jpeg-CXAyIdl8.mjs").then((t) => t.default));
|
|
28958
|
+
Ht([8, 32946], () => import("./deflate-CPNmBnej.mjs").then((t) => t.default));
|
|
28959
|
+
Ht(32773, () => import("./packbits-DaRNs4L0.mjs").then((t) => t.default));
|
|
28960
28960
|
Ht(
|
|
28961
28961
|
34887,
|
|
28962
|
-
() => import("./lerc-
|
|
28962
|
+
() => import("./lerc-DmIa8s0n.mjs").then(async (t) => (await t.zstd.init(), t)).then((t) => t.default)
|
|
28963
28963
|
);
|
|
28964
|
-
Ht(50001, () => import("./webimage-
|
|
28964
|
+
Ht(50001, () => import("./webimage-BKZpDwde.mjs").then((t) => t.default));
|
|
28965
28965
|
function Hk(t, A) {
|
|
28966
28966
|
let e = t.length - A, i = 0;
|
|
28967
28967
|
do {
|
|
@@ -44756,7 +44756,7 @@ Si([8, 32946], () => import("./deflate-DbhbvOaP-D8NSBt31.mjs").then((t) => t.def
|
|
|
44756
44756
|
Si(32773, () => import("./packbits-BuzK6gM3-6Um4hupZ.mjs").then((t) => t.default));
|
|
44757
44757
|
Si(
|
|
44758
44758
|
34887,
|
|
44759
|
-
() => import("./lerc-XufrP0FH-
|
|
44759
|
+
() => import("./lerc-XufrP0FH-Cp9B8C70.mjs").then(async (t) => (await t.zstd.init(), t)).then((t) => t.default)
|
|
44760
44760
|
);
|
|
44761
44761
|
Si(50001, () => import("./webimage--SJddlky-F_hESl4q.mjs").then((t) => t.default));
|
|
44762
44762
|
function xg(t, A, e, i = 1) {
|