juxscript 1.1.239 → 1.1.243
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/index.js +7 -137
- package/lib/components/dataframe.ts +0 -569
- package/lib/components/tag.ts +68 -0
- package/lib/styles/shadcn.css +20 -7
- package/lib/utils/idgen.ts +6 -0
- package/package.json +5 -6
- package/index.d.ts +0 -239
- package/index.d.ts.map +0 -1
- package/lib/components/alert.d.ts +0 -36
- package/lib/components/alert.d.ts.map +0 -1
- package/lib/components/alert.js +0 -172
- package/lib/components/alert.ts +0 -219
- package/lib/components/app.d.ts +0 -89
- package/lib/components/app.d.ts.map +0 -1
- package/lib/components/app.js +0 -175
- package/lib/components/app.ts +0 -247
- package/lib/components/badge.d.ts +0 -26
- package/lib/components/badge.d.ts.map +0 -1
- package/lib/components/badge.js +0 -91
- package/lib/components/badge.ts +0 -118
- package/lib/components/base/Animations.d.ts +0 -36
- package/lib/components/base/Animations.d.ts.map +0 -1
- package/lib/components/base/Animations.js +0 -70
- package/lib/components/base/Animations.ts +0 -112
- package/lib/components/base/BaseComponent.d.ts +0 -294
- package/lib/components/base/BaseComponent.d.ts.map +0 -1
- package/lib/components/base/BaseComponent.js +0 -735
- package/lib/components/base/BaseComponent.ts +0 -884
- package/lib/components/base/FormInput.d.ts +0 -77
- package/lib/components/base/FormInput.d.ts.map +0 -1
- package/lib/components/base/FormInput.js +0 -171
- package/lib/components/base/FormInput.ts +0 -237
- package/lib/components/blueprint.d.ts +0 -40
- package/lib/components/blueprint.d.ts.map +0 -1
- package/lib/components/blueprint.js +0 -327
- package/lib/components/button.d.ts +0 -70
- package/lib/components/button.d.ts.map +0 -1
- package/lib/components/button.js +0 -177
- package/lib/components/button.ts +0 -237
- package/lib/components/card.d.ts +0 -35
- package/lib/components/card.d.ts.map +0 -1
- package/lib/components/card.js +0 -130
- package/lib/components/card.ts +0 -177
- package/lib/components/chart.d.ts +0 -49
- package/lib/components/chart.d.ts.map +0 -1
- package/lib/components/chart.js +0 -205
- package/lib/components/chart.ts +0 -254
- package/lib/components/checkbox.d.ts +0 -33
- package/lib/components/checkbox.d.ts.map +0 -1
- package/lib/components/checkbox.js +0 -202
- package/lib/components/checkbox.ts +0 -260
- package/lib/components/code.d.ts +0 -52
- package/lib/components/code.d.ts.map +0 -1
- package/lib/components/code.js +0 -201
- package/lib/components/code.ts +0 -260
- package/lib/components/container.d.ts +0 -60
- package/lib/components/container.d.ts.map +0 -1
- package/lib/components/container.js +0 -195
- package/lib/components/container.ts +0 -259
- package/lib/components/data.d.ts +0 -36
- package/lib/components/data.d.ts.map +0 -1
- package/lib/components/data.js +0 -110
- package/lib/components/data.ts +0 -135
- package/lib/components/dataframe/DataFrameSource.d.ts +0 -118
- package/lib/components/dataframe/DataFrameSource.d.ts.map +0 -1
- package/lib/components/dataframe/DataFrameSource.js +0 -421
- package/lib/components/dataframe/DataFrameSource.ts +0 -532
- package/lib/components/dataframe/ImportSettingsModal.d.ts +0 -60
- package/lib/components/dataframe/ImportSettingsModal.d.ts.map +0 -1
- package/lib/components/dataframe/ImportSettingsModal.js +0 -442
- package/lib/components/dataframe/ImportSettingsModal.ts +0 -531
- package/lib/components/dataframe.d.ts +0 -110
- package/lib/components/dataframe.d.ts.map +0 -1
- package/lib/components/dataframe.js +0 -470
- package/lib/components/datepicker.d.ts +0 -40
- package/lib/components/datepicker.d.ts.map +0 -1
- package/lib/components/datepicker.js +0 -193
- package/lib/components/datepicker.ts +0 -251
- package/lib/components/dialog.d.ts +0 -39
- package/lib/components/dialog.d.ts.map +0 -1
- package/lib/components/dialog.js +0 -131
- package/lib/components/dialog.ts +0 -178
- package/lib/components/divider.d.ts +0 -31
- package/lib/components/divider.d.ts.map +0 -1
- package/lib/components/divider.js +0 -72
- package/lib/components/divider.ts +0 -104
- package/lib/components/dropdown-menu.d.ts +0 -42
- package/lib/components/dropdown-menu.d.ts.map +0 -1
- package/lib/components/dropdown-menu.js +0 -177
- package/lib/components/dropdown-menu.ts +0 -214
- package/lib/components/dropdown.d.ts +0 -41
- package/lib/components/dropdown.d.ts.map +0 -1
- package/lib/components/dropdown.js +0 -136
- package/lib/components/dropdown.ts +0 -188
- package/lib/components/element.d.ts +0 -51
- package/lib/components/element.d.ts.map +0 -1
- package/lib/components/element.js +0 -209
- package/lib/components/element.ts +0 -271
- package/lib/components/event-chain.d.ts +0 -9
- package/lib/components/event-chain.d.ts.map +0 -1
- package/lib/components/event-chain.js +0 -33
- package/lib/components/fileupload.d.ts +0 -98
- package/lib/components/fileupload.d.ts.map +0 -1
- package/lib/components/fileupload.js +0 -351
- package/lib/components/fileupload.ts +0 -449
- package/lib/components/grid.d.ts +0 -88
- package/lib/components/grid.d.ts.map +0 -1
- package/lib/components/grid.js +0 -208
- package/lib/components/grid.ts +0 -295
- package/lib/components/heading.d.ts +0 -25
- package/lib/components/heading.d.ts.map +0 -1
- package/lib/components/heading.js +0 -83
- package/lib/components/heading.ts +0 -113
- package/lib/components/helpers.d.ts +0 -9
- package/lib/components/helpers.d.ts.map +0 -1
- package/lib/components/helpers.js +0 -30
- package/lib/components/helpers.ts +0 -41
- package/lib/components/hero.d.ts +0 -60
- package/lib/components/hero.d.ts.map +0 -1
- package/lib/components/hero.js +0 -239
- package/lib/components/hero.ts +0 -302
- package/lib/components/history/StateHistory.d.ts +0 -91
- package/lib/components/history/StateHistory.d.ts.map +0 -1
- package/lib/components/history/StateHistory.js +0 -154
- package/lib/components/history/StateHistory.ts +0 -200
- package/lib/components/icon.d.ts +0 -36
- package/lib/components/icon.d.ts.map +0 -1
- package/lib/components/icon.js +0 -135
- package/lib/components/icon.ts +0 -182
- package/lib/components/icons.d.ts +0 -25
- package/lib/components/icons.d.ts.map +0 -1
- package/lib/components/icons.js +0 -440
- package/lib/components/icons.ts +0 -464
- package/lib/components/image.d.ts +0 -42
- package/lib/components/image.d.ts.map +0 -1
- package/lib/components/image.js +0 -204
- package/lib/components/image.ts +0 -260
- package/lib/components/include.d.ts +0 -86
- package/lib/components/include.d.ts.map +0 -1
- package/lib/components/include.js +0 -238
- package/lib/components/include.ts +0 -281
- package/lib/components/input.d.ts +0 -85
- package/lib/components/input.d.ts.map +0 -1
- package/lib/components/input.js +0 -362
- package/lib/components/input.ts +0 -473
- package/lib/components/layer.d.ts +0 -72
- package/lib/components/layer.d.ts.map +0 -1
- package/lib/components/layer.js +0 -219
- package/lib/components/layer.ts +0 -304
- package/lib/components/link.d.ts +0 -41
- package/lib/components/link.d.ts.map +0 -1
- package/lib/components/link.js +0 -216
- package/lib/components/link.ts +0 -268
- package/lib/components/list.d.ts +0 -83
- package/lib/components/list.d.ts.map +0 -1
- package/lib/components/list.js +0 -314
- package/lib/components/list.ts +0 -423
- package/lib/components/loading.d.ts +0 -25
- package/lib/components/loading.d.ts.map +0 -1
- package/lib/components/loading.js +0 -76
- package/lib/components/loading.ts +0 -104
- package/lib/components/menu.d.ts +0 -38
- package/lib/components/menu.d.ts.map +0 -1
- package/lib/components/menu.js +0 -205
- package/lib/components/menu.ts +0 -279
- package/lib/components/modal.d.ts +0 -97
- package/lib/components/modal.d.ts.map +0 -1
- package/lib/components/modal.js +0 -463
- package/lib/components/modal.ts +0 -576
- package/lib/components/nav.d.ts +0 -46
- package/lib/components/nav.d.ts.map +0 -1
- package/lib/components/nav.js +0 -193
- package/lib/components/nav.ts +0 -261
- package/lib/components/paragraph.d.ts +0 -30
- package/lib/components/paragraph.d.ts.map +0 -1
- package/lib/components/paragraph.js +0 -93
- package/lib/components/paragraph.ts +0 -123
- package/lib/components/pen.d.ts +0 -125
- package/lib/components/pen.d.ts.map +0 -1
- package/lib/components/pen.js +0 -443
- package/lib/components/pen.ts +0 -567
- package/lib/components/progress.d.ts +0 -40
- package/lib/components/progress.d.ts.map +0 -1
- package/lib/components/progress.js +0 -116
- package/lib/components/progress.ts +0 -163
- package/lib/components/radio.d.ts +0 -43
- package/lib/components/radio.d.ts.map +0 -1
- package/lib/components/radio.js +0 -226
- package/lib/components/radio.ts +0 -303
- package/lib/components/registry.d.ts +0 -34
- package/lib/components/registry.d.ts.map +0 -1
- package/lib/components/registry.js +0 -163
- package/lib/components/registry.ts +0 -193
- package/lib/components/req.d.ts +0 -155
- package/lib/components/req.d.ts.map +0 -1
- package/lib/components/req.js +0 -253
- package/lib/components/req.ts +0 -303
- package/lib/components/script.d.ts +0 -14
- package/lib/components/script.d.ts.map +0 -1
- package/lib/components/script.js +0 -33
- package/lib/components/script.ts +0 -41
- package/lib/components/select.d.ts +0 -42
- package/lib/components/select.d.ts.map +0 -1
- package/lib/components/select.js +0 -209
- package/lib/components/select.ts +0 -281
- package/lib/components/sidebar.d.ts +0 -59
- package/lib/components/sidebar.d.ts.map +0 -1
- package/lib/components/sidebar.js +0 -298
- package/lib/components/sidebar.ts +0 -395
- package/lib/components/stack/BaseStack.d.ts +0 -65
- package/lib/components/stack/BaseStack.d.ts.map +0 -1
- package/lib/components/stack/BaseStack.js +0 -274
- package/lib/components/stack/BaseStack.ts +0 -328
- package/lib/components/stack/HStack.d.ts +0 -18
- package/lib/components/stack/HStack.d.ts.map +0 -1
- package/lib/components/stack/HStack.js +0 -22
- package/lib/components/stack/HStack.ts +0 -25
- package/lib/components/stack/VStack.d.ts +0 -19
- package/lib/components/stack/VStack.d.ts.map +0 -1
- package/lib/components/stack/VStack.js +0 -23
- package/lib/components/stack/VStack.ts +0 -26
- package/lib/components/stack/ZStack.d.ts +0 -18
- package/lib/components/stack/ZStack.d.ts.map +0 -1
- package/lib/components/stack/ZStack.js +0 -22
- package/lib/components/stack/ZStack.ts +0 -25
- package/lib/components/style.d.ts +0 -14
- package/lib/components/style.d.ts.map +0 -1
- package/lib/components/style.js +0 -33
- package/lib/components/style.ts +0 -41
- package/lib/components/switch.d.ts +0 -34
- package/lib/components/switch.d.ts.map +0 -1
- package/lib/components/switch.js +0 -209
- package/lib/components/switch.ts +0 -272
- package/lib/components/table.d.ts +0 -137
- package/lib/components/table.d.ts.map +0 -1
- package/lib/components/table.js +0 -1019
- package/lib/components/table.ts +0 -1225
- package/lib/components/tabs.d.ts +0 -53
- package/lib/components/tabs.d.ts.map +0 -1
- package/lib/components/tabs.js +0 -275
- package/lib/components/tabs.ts +0 -349
- package/lib/components/theme-toggle.d.ts +0 -45
- package/lib/components/theme-toggle.d.ts.map +0 -1
- package/lib/components/theme-toggle.js +0 -218
- package/lib/components/theme-toggle.ts +0 -297
- package/lib/components/tooltip.d.ts +0 -31
- package/lib/components/tooltip.d.ts.map +0 -1
- package/lib/components/tooltip.js +0 -112
- package/lib/components/tooltip.ts +0 -148
- package/lib/components/watcher.d.ts +0 -195
- package/lib/components/watcher.d.ts.map +0 -1
- package/lib/components/watcher.js +0 -241
- package/lib/components/watcher.ts +0 -261
- package/lib/components/write.d.ts +0 -107
- package/lib/components/write.d.ts.map +0 -1
- package/lib/components/write.js +0 -222
- package/lib/components/write.ts +0 -272
- package/lib/data/DataPipeline.d.ts +0 -113
- package/lib/data/DataPipeline.d.ts.map +0 -1
- package/lib/data/DataPipeline.js +0 -359
- package/lib/data/DataPipeline.ts +0 -452
- package/lib/facades/dataframe.jux +0 -0
- package/lib/globals.d.ts +0 -21
- package/lib/reactivity/state.d.ts +0 -36
- package/lib/reactivity/state.d.ts.map +0 -1
- package/lib/reactivity/state.js +0 -67
- package/lib/reactivity/state.ts +0 -78
- package/lib/storage/DataFrame.d.ts +0 -284
- package/lib/storage/DataFrame.d.ts.map +0 -1
- package/lib/storage/DataFrame.js +0 -1022
- package/lib/storage/DataFrame.ts +0 -1195
- package/lib/storage/DataFrameSource.d.ts +0 -158
- package/lib/storage/DataFrameSource.d.ts.map +0 -1
- package/lib/storage/DataFrameSource.js +0 -409
- package/lib/storage/DataFrameSource.ts +0 -556
- package/lib/storage/FileStorage.d.ts +0 -53
- package/lib/storage/FileStorage.d.ts.map +0 -1
- package/lib/storage/FileStorage.js +0 -80
- package/lib/storage/FileStorage.ts +0 -95
- package/lib/storage/IndexedDBDriver.d.ts +0 -75
- package/lib/storage/IndexedDBDriver.d.ts.map +0 -1
- package/lib/storage/IndexedDBDriver.js +0 -177
- package/lib/storage/IndexedDBDriver.ts +0 -226
- package/lib/storage/TabularDriver.d.ts +0 -118
- package/lib/storage/TabularDriver.d.ts.map +0 -1
- package/lib/storage/TabularDriver.js +0 -731
- package/lib/storage/TabularDriver.ts +0 -874
- package/lib/utils/codeparser.d.ts +0 -29
- package/lib/utils/codeparser.d.ts.map +0 -1
- package/lib/utils/codeparser.js +0 -409
- package/lib/utils/fetch.d.ts +0 -176
- package/lib/utils/fetch.d.ts.map +0 -1
- package/lib/utils/fetch.js +0 -427
- package/lib/utils/formatId.d.ts +0 -16
- package/lib/utils/formatId.d.ts.map +0 -1
- package/lib/utils/formatId.js +0 -27
- package/lib/utils/path-resolver.js +0 -23
|
@@ -1,532 +0,0 @@
|
|
|
1
|
-
import { DataFrame } from '../../storage/DataFrame.js';
|
|
2
|
-
import { TabularDriver } from '../../storage/TabularDriver.js';
|
|
3
|
-
import { FileUpload } from '../fileupload.js';
|
|
4
|
-
|
|
5
|
-
export interface DataFrameSourceOptions {
|
|
6
|
-
maxFileSize?: number; // MB
|
|
7
|
-
maxSheetSize?: number; // rows per sheet
|
|
8
|
-
sheetChunkSize?: number;
|
|
9
|
-
persistToIndexedDB?: boolean;
|
|
10
|
-
dbName?: string;
|
|
11
|
-
storeName?: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface LoadResult {
|
|
15
|
-
df: DataFrame | null;
|
|
16
|
-
sheets?: Record<string, DataFrame>;
|
|
17
|
-
sourceName: string;
|
|
18
|
-
isMultiSheet: boolean;
|
|
19
|
-
error?: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface RawFileData {
|
|
23
|
-
file: File;
|
|
24
|
-
text?: string;
|
|
25
|
-
isExcel?: boolean;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
type SourceCallback = (result: LoadResult) => void;
|
|
29
|
-
type ProgressCallback = (loaded: number, total: number) => void;
|
|
30
|
-
type ErrorCallback = (message: string) => void;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* DataFrameSource - Handles data acquisition from various sources
|
|
34
|
-
*
|
|
35
|
-
* Responsibilities:
|
|
36
|
-
* - Load data from files (CSV, Excel)
|
|
37
|
-
* - Load data from URLs
|
|
38
|
-
* - Load data from IndexedDB storage
|
|
39
|
-
* - Load data from inline arrays/objects
|
|
40
|
-
* - Validate and detect malformed data
|
|
41
|
-
* - Persist to storage if configured
|
|
42
|
-
*
|
|
43
|
-
* Does NOT handle:
|
|
44
|
-
* - UI rendering
|
|
45
|
-
* - User interactions
|
|
46
|
-
* - Modals/dialogs
|
|
47
|
-
*/
|
|
48
|
-
export class DataFrameSource {
|
|
49
|
-
private _driver: TabularDriver;
|
|
50
|
-
private _options: Required<DataFrameSourceOptions>;
|
|
51
|
-
private _df: DataFrame | null = null;
|
|
52
|
-
private _sheets: Map<string, DataFrame> = new Map();
|
|
53
|
-
private _rawFileData: RawFileData | null = null;
|
|
54
|
-
private _sourceName: string = '';
|
|
55
|
-
private _onLoad: SourceCallback | null = null;
|
|
56
|
-
private _onProgress: ProgressCallback | null = null;
|
|
57
|
-
private _onError: ErrorCallback | null = null;
|
|
58
|
-
|
|
59
|
-
constructor(options: DataFrameSourceOptions = {}) {
|
|
60
|
-
this._options = {
|
|
61
|
-
maxFileSize: options.maxFileSize ?? 50,
|
|
62
|
-
maxSheetSize: options.maxSheetSize ?? 100000,
|
|
63
|
-
sheetChunkSize: options.sheetChunkSize ?? 10000,
|
|
64
|
-
persistToIndexedDB: options.persistToIndexedDB ?? false,
|
|
65
|
-
dbName: options.dbName ?? 'jux-dataframes',
|
|
66
|
-
storeName: options.storeName ?? 'frames'
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
this._driver = new TabularDriver(
|
|
70
|
-
this._options.dbName,
|
|
71
|
-
this._options.storeName
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/* ═══════════════════════════════════════════════════
|
|
76
|
-
* CALLBACKS
|
|
77
|
-
* ═══════════════════════════════════════════════════ */
|
|
78
|
-
|
|
79
|
-
onLoad(callback: SourceCallback): this {
|
|
80
|
-
this._onLoad = callback;
|
|
81
|
-
return this;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
onProgress(callback: ProgressCallback): this {
|
|
85
|
-
this._onProgress = callback;
|
|
86
|
-
return this;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
onError(callback: ErrorCallback): this {
|
|
90
|
-
this._onError = callback;
|
|
91
|
-
return this;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/* ═══════════════════════════════════════════════════
|
|
95
|
-
* DATA SOURCES
|
|
96
|
-
* ═══════════════════════════════════════════════════ */
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Load from a FileUpload component
|
|
100
|
-
*/
|
|
101
|
-
fromUpload(upload: FileUpload): this {
|
|
102
|
-
upload.bind('change', async (files: File[]) => {
|
|
103
|
-
if (!files || files.length === 0) {
|
|
104
|
-
this.clear();
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
await this.fromFile(files[0]);
|
|
108
|
-
});
|
|
109
|
-
return this;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Load from a File object directly
|
|
114
|
-
*/
|
|
115
|
-
async fromFile(file: File): Promise<LoadResult> {
|
|
116
|
-
const fileSizeMB = file.size / (1024 * 1024);
|
|
117
|
-
|
|
118
|
-
if (fileSizeMB > this._options.maxFileSize) {
|
|
119
|
-
const error = `File too large (${fileSizeMB.toFixed(1)}MB). Max: ${this._options.maxFileSize}MB`;
|
|
120
|
-
this._onError?.(error);
|
|
121
|
-
return { df: null, sourceName: file.name, isMultiSheet: false, error };
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
try {
|
|
125
|
-
const isExcel = /\.(xlsx?|xls)$/i.test(file.name);
|
|
126
|
-
|
|
127
|
-
if (isExcel) {
|
|
128
|
-
return await this._loadExcel(file);
|
|
129
|
-
} else {
|
|
130
|
-
return await this._loadCSV(file);
|
|
131
|
-
}
|
|
132
|
-
} catch (err: any) {
|
|
133
|
-
const error = `Error parsing ${file.name}: ${err.message}`;
|
|
134
|
-
this._onError?.(error);
|
|
135
|
-
return { df: null, sourceName: file.name, isMultiSheet: false, error };
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Load from a URL
|
|
141
|
-
*/
|
|
142
|
-
async fromUrl(url: string): Promise<LoadResult> {
|
|
143
|
-
try {
|
|
144
|
-
this._onProgress?.(0, 100);
|
|
145
|
-
|
|
146
|
-
const df = await this._driver.fetch(url, {
|
|
147
|
-
autoDetectDelimiter: true,
|
|
148
|
-
hasHeader: true,
|
|
149
|
-
onProgress: (loaded, total) => {
|
|
150
|
-
this._onProgress?.(loaded, total ?? 100);
|
|
151
|
-
}
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
this._df = df;
|
|
155
|
-
this._sourceName = url.split('/').pop() || url;
|
|
156
|
-
|
|
157
|
-
const result: LoadResult = {
|
|
158
|
-
df,
|
|
159
|
-
sourceName: this._sourceName,
|
|
160
|
-
isMultiSheet: false
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
if (this._options.persistToIndexedDB) {
|
|
164
|
-
await this._driver.store(this._sourceName, df, { source: url });
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
this._onLoad?.(result);
|
|
168
|
-
return result;
|
|
169
|
-
|
|
170
|
-
} catch (err: any) {
|
|
171
|
-
const error = `Error fetching ${url}: ${err.message}`;
|
|
172
|
-
this._onError?.(error);
|
|
173
|
-
return { df: null, sourceName: url, isMultiSheet: false, error };
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Load from IndexedDB storage by key
|
|
179
|
-
*/
|
|
180
|
-
async fromStorage(key: string): Promise<LoadResult> {
|
|
181
|
-
try {
|
|
182
|
-
const df = await this._driver.loadByName(key);
|
|
183
|
-
|
|
184
|
-
if (!df) {
|
|
185
|
-
const error = `No data found with key: ${key}`;
|
|
186
|
-
this._onError?.(error);
|
|
187
|
-
return { df: null, sourceName: key, isMultiSheet: false, error };
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
this._df = df;
|
|
191
|
-
this._sourceName = key;
|
|
192
|
-
|
|
193
|
-
const result: LoadResult = {
|
|
194
|
-
df,
|
|
195
|
-
sourceName: key,
|
|
196
|
-
isMultiSheet: false
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
this._onLoad?.(result);
|
|
200
|
-
return result;
|
|
201
|
-
|
|
202
|
-
} catch (err: any) {
|
|
203
|
-
const error = `Error loading from storage: ${err.message}`;
|
|
204
|
-
this._onError?.(error);
|
|
205
|
-
return { df: null, sourceName: key, isMultiSheet: false, error };
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Load from inline data (array of objects or columnar format)
|
|
211
|
-
*/
|
|
212
|
-
fromData(data: Record<string, any>[] | Record<string, any[]>, sourceName: string = 'inline data'): LoadResult {
|
|
213
|
-
try {
|
|
214
|
-
const df = new DataFrame(data);
|
|
215
|
-
this._df = df;
|
|
216
|
-
this._sourceName = sourceName;
|
|
217
|
-
|
|
218
|
-
const result: LoadResult = {
|
|
219
|
-
df,
|
|
220
|
-
sourceName,
|
|
221
|
-
isMultiSheet: false
|
|
222
|
-
};
|
|
223
|
-
|
|
224
|
-
this._onLoad?.(result);
|
|
225
|
-
return result;
|
|
226
|
-
|
|
227
|
-
} catch (err: any) {
|
|
228
|
-
const error = `Error creating DataFrame: ${err.message}`;
|
|
229
|
-
this._onError?.(error);
|
|
230
|
-
return { df: null, sourceName, isMultiSheet: false, error };
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Re-parse with different options (header row, delimiter)
|
|
236
|
-
*/
|
|
237
|
-
async reimport(options: { headerRow?: number; delimiter?: string }): Promise<LoadResult> {
|
|
238
|
-
if (!this._rawFileData) {
|
|
239
|
-
const error = 'No raw file data available for reimport';
|
|
240
|
-
this._onError?.(error);
|
|
241
|
-
return { df: null, sourceName: this._sourceName, isMultiSheet: false, error };
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
try {
|
|
245
|
-
if (this._rawFileData.isExcel) {
|
|
246
|
-
const sheets = await this._driver.streamFileMultiSheet(this._rawFileData.file, {
|
|
247
|
-
headerRow: options.headerRow ?? 0,
|
|
248
|
-
maxSheetSize: this._options.maxSheetSize,
|
|
249
|
-
sheetChunkSize: this._options.sheetChunkSize
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
return this._processSheets(sheets, this._rawFileData.file.name);
|
|
253
|
-
} else {
|
|
254
|
-
const df = this._driver.parseCSV(this._rawFileData.text!, {
|
|
255
|
-
delimiter: options.delimiter,
|
|
256
|
-
headerRow: options.headerRow ?? 0,
|
|
257
|
-
hasHeader: true
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
this._df = df;
|
|
261
|
-
|
|
262
|
-
if (this._options.persistToIndexedDB) {
|
|
263
|
-
await this._driver.store(this._rawFileData.file.name, df);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
const result: LoadResult = {
|
|
267
|
-
df,
|
|
268
|
-
sourceName: this._rawFileData.file.name,
|
|
269
|
-
isMultiSheet: false
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
this._onLoad?.(result);
|
|
273
|
-
return result;
|
|
274
|
-
}
|
|
275
|
-
} catch (err: any) {
|
|
276
|
-
const error = `Error reimporting: ${err.message}`;
|
|
277
|
-
this._onError?.(error);
|
|
278
|
-
return { df: null, sourceName: this._sourceName, isMultiSheet: false, error };
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/* ═══════════════════════════════════════════════════
|
|
283
|
-
* ACCESSORS
|
|
284
|
-
* ═══════════════════════════════════════════════════ */
|
|
285
|
-
|
|
286
|
-
get df(): DataFrame | null {
|
|
287
|
-
return this._df;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
get sheets(): Map<string, DataFrame> {
|
|
291
|
-
return this._sheets;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
get sourceName(): string {
|
|
295
|
-
return this._sourceName;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
get rawFileData(): RawFileData | null {
|
|
299
|
-
return this._rawFileData;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
get driver(): TabularDriver {
|
|
303
|
-
return this._driver;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
get shape(): [number, number] {
|
|
307
|
-
return this._df?.shape ?? [0, 0];
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
get columns(): string[] {
|
|
311
|
-
return this._df?.columns ?? [];
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
get height(): number {
|
|
315
|
-
return this._df?.height ?? 0;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
get width(): number {
|
|
319
|
-
return this._df?.width ?? 0;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
/* ═══════════════════════════════════════════════════
|
|
323
|
-
* DATA QUALITY
|
|
324
|
-
* ═══════════════════════════════════════════════════ */
|
|
325
|
-
|
|
326
|
-
/**
|
|
327
|
-
* Detect if the data appears malformed (bad headers, metadata rows, etc.)
|
|
328
|
-
*/
|
|
329
|
-
detectMalformed(): boolean {
|
|
330
|
-
if (!this._df) return false;
|
|
331
|
-
|
|
332
|
-
const columns = this._df.columns;
|
|
333
|
-
const rows = this._df.toRows();
|
|
334
|
-
|
|
335
|
-
// Check for generic/empty column names
|
|
336
|
-
const hasGenericColumns = columns.some(col =>
|
|
337
|
-
col.startsWith('__EMPTY') ||
|
|
338
|
-
/^_\d+$/.test(col) ||
|
|
339
|
-
/^col_\d+$/.test(col)
|
|
340
|
-
);
|
|
341
|
-
if (hasGenericColumns) return true;
|
|
342
|
-
|
|
343
|
-
// Check if first row looks like metadata
|
|
344
|
-
if (rows.length > 0) {
|
|
345
|
-
const firstRow = rows[0];
|
|
346
|
-
const values = Object.values(firstRow);
|
|
347
|
-
const nonEmpty = values.filter(v =>
|
|
348
|
-
v !== null && v !== undefined && String(v).trim() !== ''
|
|
349
|
-
);
|
|
350
|
-
|
|
351
|
-
// Sparse first row suggests header issues
|
|
352
|
-
if (nonEmpty.length < columns.length * 0.5) return true;
|
|
353
|
-
|
|
354
|
-
// Common metadata patterns
|
|
355
|
-
const hasMetadata = values.some(v =>
|
|
356
|
-
String(v).includes('Exported') ||
|
|
357
|
-
String(v).includes('Generated') ||
|
|
358
|
-
String(v).includes('Report')
|
|
359
|
-
);
|
|
360
|
-
if (hasMetadata) return true;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
return false;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
/**
|
|
367
|
-
* Get raw preview rows for header selection UI
|
|
368
|
-
*/
|
|
369
|
-
async getPreviewRows(maxRows: number = 15): Promise<{ sheetRow: number; values: any[] }[]> {
|
|
370
|
-
if (!this._rawFileData?.file) return [];
|
|
371
|
-
|
|
372
|
-
if (this._rawFileData.isExcel) {
|
|
373
|
-
return this._driver.readRawExcelRows(this._rawFileData.file, maxRows);
|
|
374
|
-
} else if (this._rawFileData.text) {
|
|
375
|
-
return this._parseCSVPreview(this._rawFileData.text, maxRows);
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
return [];
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
/* ═══════════════════════════════════════════════════
|
|
382
|
-
* PERSISTENCE
|
|
383
|
-
* ═══════════════════════════════════════════════════ */
|
|
384
|
-
|
|
385
|
-
async save(key?: string): Promise<string | null> {
|
|
386
|
-
if (!this._df) return null;
|
|
387
|
-
const name = key ?? this._sourceName;
|
|
388
|
-
return this._driver.store(name, this._df);
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
async clearStorage(): Promise<void> {
|
|
392
|
-
if (this._rawFileData?.file) {
|
|
393
|
-
const tables = await this._driver.list();
|
|
394
|
-
const matching = tables.filter(t => t.name === this._rawFileData!.file.name);
|
|
395
|
-
for (const table of matching) {
|
|
396
|
-
await this._driver.delete(table.id);
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
clear(): void {
|
|
402
|
-
this._df = null;
|
|
403
|
-
this._sheets.clear();
|
|
404
|
-
this._rawFileData = null;
|
|
405
|
-
this._sourceName = '';
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
/* ═══════════════════════════════════════════════════
|
|
409
|
-
* PRIVATE HELPERS
|
|
410
|
-
* ═══════════════════════════════════════════════════ */
|
|
411
|
-
|
|
412
|
-
private async _loadExcel(file: File): Promise<LoadResult> {
|
|
413
|
-
this._rawFileData = { file, isExcel: true };
|
|
414
|
-
|
|
415
|
-
const sheets = await this._driver.streamFileMultiSheet(file, {
|
|
416
|
-
maxSheetSize: this._options.maxSheetSize,
|
|
417
|
-
sheetChunkSize: this._options.sheetChunkSize,
|
|
418
|
-
onProgress: (loaded, total) => {
|
|
419
|
-
this._onProgress?.(loaded, total ?? 100);
|
|
420
|
-
}
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
return this._processSheets(sheets, file.name);
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
private async _loadCSV(file: File): Promise<LoadResult> {
|
|
427
|
-
const text = await file.text();
|
|
428
|
-
this._rawFileData = { file, text, isExcel: false };
|
|
429
|
-
|
|
430
|
-
const df = this._driver.parseCSV(text, {
|
|
431
|
-
autoDetectDelimiter: true,
|
|
432
|
-
hasHeader: true
|
|
433
|
-
});
|
|
434
|
-
|
|
435
|
-
// Strip fully empty __EMPTY columns
|
|
436
|
-
const cleanDf = this._stripEmptyColumns(df);
|
|
437
|
-
this._df = cleanDf;
|
|
438
|
-
this._sourceName = file.name;
|
|
439
|
-
|
|
440
|
-
if (this._options.persistToIndexedDB) {
|
|
441
|
-
await this._driver.store(file.name, cleanDf, { source: file.name });
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
const result: LoadResult = {
|
|
445
|
-
df: cleanDf,
|
|
446
|
-
sourceName: file.name,
|
|
447
|
-
isMultiSheet: false
|
|
448
|
-
};
|
|
449
|
-
|
|
450
|
-
this._onLoad?.(result);
|
|
451
|
-
return result;
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
private async _processSheets(sheets: Record<string, DataFrame>, sourceName: string): Promise<LoadResult> {
|
|
455
|
-
const sheetNames = Object.keys(sheets);
|
|
456
|
-
|
|
457
|
-
if (sheetNames.length === 0) {
|
|
458
|
-
const error = 'No data found in file';
|
|
459
|
-
this._onError?.(error);
|
|
460
|
-
return { df: null, sourceName, isMultiSheet: false, error };
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
this._sheets.clear();
|
|
464
|
-
sheetNames.forEach(name => {
|
|
465
|
-
this._sheets.set(name, this._stripEmptyColumns(sheets[name]));
|
|
466
|
-
});
|
|
467
|
-
|
|
468
|
-
const firstSheet = this._sheets.get(sheetNames[0])!;
|
|
469
|
-
this._df = firstSheet;
|
|
470
|
-
this._sourceName = sourceName;
|
|
471
|
-
|
|
472
|
-
if (this._options.persistToIndexedDB) {
|
|
473
|
-
await this._driver.store(sourceName, firstSheet, { source: sourceName });
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
const result: LoadResult = {
|
|
477
|
-
df: firstSheet,
|
|
478
|
-
sheets: Object.fromEntries(this._sheets),
|
|
479
|
-
sourceName,
|
|
480
|
-
isMultiSheet: sheetNames.length > 1
|
|
481
|
-
};
|
|
482
|
-
|
|
483
|
-
this._onLoad?.(result);
|
|
484
|
-
return result;
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
private _stripEmptyColumns(df: DataFrame): DataFrame {
|
|
488
|
-
const cols = df.columns;
|
|
489
|
-
const rows = df.toRows();
|
|
490
|
-
|
|
491
|
-
const emptyColumns = cols.filter(c => {
|
|
492
|
-
if (!c.startsWith('__EMPTY')) return false;
|
|
493
|
-
return rows.every(row => {
|
|
494
|
-
const val = row[c];
|
|
495
|
-
return val === null || val === undefined || String(val).trim() === '';
|
|
496
|
-
});
|
|
497
|
-
});
|
|
498
|
-
|
|
499
|
-
if (emptyColumns.length > 0) {
|
|
500
|
-
const keepCols = cols.filter(c => !emptyColumns.includes(c));
|
|
501
|
-
if (keepCols.length > 0) {
|
|
502
|
-
return df.select(...keepCols);
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
return df;
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
private _parseCSVPreview(text: string, maxRows: number): { sheetRow: number; values: any[] }[] {
|
|
510
|
-
const lines = text.replace(/\r\n/g, '\n').replace(/\r/g, '\n').split('\n');
|
|
511
|
-
const delimiter = (this._driver as any)._detectDelimiter(text);
|
|
512
|
-
const rows: { sheetRow: number; values: any[] }[] = [];
|
|
513
|
-
|
|
514
|
-
for (let i = 0; i < Math.min(lines.length, maxRows); i++) {
|
|
515
|
-
if (!lines[i]) {
|
|
516
|
-
rows.push({ sheetRow: i, values: [''] });
|
|
517
|
-
continue;
|
|
518
|
-
}
|
|
519
|
-
const values = (this._driver as any)._parseLine(lines[i], delimiter);
|
|
520
|
-
rows.push({ sheetRow: i, values });
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
return rows;
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
/**
|
|
528
|
-
* Factory function
|
|
529
|
-
*/
|
|
530
|
-
export function dataFrameSource(options: DataFrameSourceOptions = {}): DataFrameSource {
|
|
531
|
-
return new DataFrameSource(options);
|
|
532
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { TabularDriver } from '../../storage/TabularDriver.js';
|
|
2
|
-
import { DataFrame } from '../../storage/DataFrame.js';
|
|
3
|
-
export interface ImportSettingsCallbacks {
|
|
4
|
-
onReimport: (df: DataFrame | Record<string, DataFrame>, sourceName: string) => void;
|
|
5
|
-
onError: (message: string) => void;
|
|
6
|
-
onStatusUpdate: (text: string, type: 'loading' | 'success' | 'error') => void;
|
|
7
|
-
}
|
|
8
|
-
export interface SettingsModalCallbacks {
|
|
9
|
-
onClear: () => Promise<void>;
|
|
10
|
-
onAdjustImport: () => void;
|
|
11
|
-
}
|
|
12
|
-
export interface SettingsModalData {
|
|
13
|
-
fileName: string;
|
|
14
|
-
fileSize?: number;
|
|
15
|
-
rowCount: number;
|
|
16
|
-
colCount: number;
|
|
17
|
-
isMalformed: boolean;
|
|
18
|
-
hasRawFileData: boolean;
|
|
19
|
-
}
|
|
20
|
-
export interface RawFileData {
|
|
21
|
-
file: File;
|
|
22
|
-
text?: string;
|
|
23
|
-
isExcel?: boolean;
|
|
24
|
-
}
|
|
25
|
-
export declare class ImportSettingsModal {
|
|
26
|
-
private _id;
|
|
27
|
-
private _driver;
|
|
28
|
-
private _reshapeModal;
|
|
29
|
-
private _reshapeModalRendered;
|
|
30
|
-
private _settingsModal;
|
|
31
|
-
private _modal;
|
|
32
|
-
private _modalRendered;
|
|
33
|
-
private _maxSheetSize;
|
|
34
|
-
private _sheetChunkSize;
|
|
35
|
-
constructor(id: string, driver: TabularDriver, options?: {
|
|
36
|
-
maxSheetSize?: number;
|
|
37
|
-
sheetChunkSize?: number;
|
|
38
|
-
});
|
|
39
|
-
/**
|
|
40
|
-
* Show the data settings modal with file info and options
|
|
41
|
-
*/
|
|
42
|
-
showSettings(data: SettingsModalData, callbacks: SettingsModalCallbacks): void;
|
|
43
|
-
/**
|
|
44
|
-
* Close the settings modal if open
|
|
45
|
-
*/
|
|
46
|
-
closeSettings(): void;
|
|
47
|
-
/**
|
|
48
|
-
* Show the appropriate reshape modal based on file type
|
|
49
|
-
*/
|
|
50
|
-
showImportSettings(rawFileData: RawFileData, callbacks: ImportSettingsCallbacks): Promise<void>;
|
|
51
|
-
/**
|
|
52
|
-
* Cleanup any existing modals
|
|
53
|
-
*/
|
|
54
|
-
cleanup(): void;
|
|
55
|
-
private _escapeHtml;
|
|
56
|
-
private _buildClickablePreviewHTML;
|
|
57
|
-
private _showExcelModal;
|
|
58
|
-
private _showCSVModal;
|
|
59
|
-
}
|
|
60
|
-
//# sourceMappingURL=ImportSettingsModal.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ImportSettingsModal.d.ts","sourceRoot":"","sources":["ImportSettingsModal.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAEvD,MAAM,WAAW,uBAAuB;IACpC,UAAU,EAAE,CAAC,EAAE,EAAE,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACpF,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,KAAK,IAAI,CAAC;CACjF;AAED,MAAM,WAAW,sBAAsB;IACnC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,cAAc,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,qBAAa,mBAAmB;IAC5B,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,qBAAqB,CAAkB;IAC/C,OAAO,CAAC,cAAc,CAAsB;IAC5C,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,eAAe,CAAS;gBAG5B,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,aAAa,EACrB,OAAO,GAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAO;IAYpE;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,iBAAiB,EAAE,SAAS,EAAE,sBAAsB,GAAG,IAAI;IA6E9E;;OAEG;IACH,aAAa,IAAI,IAAI;IAUrB;;OAEG;IACG,kBAAkB,CAAC,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAUrG;;OAEG;IACH,OAAO,IAAI,IAAI;IAUf,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,0BAA0B;YAwDpB,eAAe;IAiI7B,OAAO,CAAC,aAAa;CAoKxB"}
|