juxscript 1.1.217 → 1.1.218
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.
|
@@ -22,6 +22,9 @@ export interface DataFrameOptions {
|
|
|
22
22
|
class?: string;
|
|
23
23
|
persistToIndexedDB?: boolean;
|
|
24
24
|
clearStorageOnFileRemove?: boolean;
|
|
25
|
+
collapsible?: boolean;
|
|
26
|
+
collapsed?: boolean;
|
|
27
|
+
summaryTemplate?: (df: DataFrame) => string;
|
|
25
28
|
}
|
|
26
29
|
type DataFrameState = BaseState & {
|
|
27
30
|
loaded: boolean;
|
|
@@ -57,6 +60,10 @@ export declare class DataFrameComponent extends BaseComponent<DataFrameState> {
|
|
|
57
60
|
private _uploadAccept;
|
|
58
61
|
private _uploadDescription;
|
|
59
62
|
private _showUploadIcon;
|
|
63
|
+
private _collapsible;
|
|
64
|
+
private _collapsed;
|
|
65
|
+
private _summaryTemplate;
|
|
66
|
+
private _detailsElement;
|
|
60
67
|
constructor(id: string, options?: DataFrameOptions);
|
|
61
68
|
protected getTriggerEvents(): readonly string[];
|
|
62
69
|
protected getCallbackEvents(): readonly string[];
|
|
@@ -132,6 +139,10 @@ export declare class DataFrameComponent extends BaseComponent<DataFrameState> {
|
|
|
132
139
|
private _renderMultiSheet;
|
|
133
140
|
private _updateStatus;
|
|
134
141
|
private _setDataFrame;
|
|
142
|
+
/**
|
|
143
|
+
* Update the collapsible summary text
|
|
144
|
+
*/
|
|
145
|
+
private _updateSummary;
|
|
135
146
|
private _detectMalformedData;
|
|
136
147
|
private _showReshapeModal;
|
|
137
148
|
private _cleanupReshapeModal;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataframe.d.ts","sourceRoot":"","sources":["dataframe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AASnC,MAAM,WAAW,gBAAgB;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"dataframe.d.ts","sourceRoot":"","sources":["dataframe.ts"],"names":[],"mappings":"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"}
|
|
@@ -49,6 +49,11 @@ export class DataFrameComponent extends BaseComponent {
|
|
|
49
49
|
this._uploadAccept = '.csv,.tsv,.txt,.xlsx,.xls';
|
|
50
50
|
this._uploadDescription = '';
|
|
51
51
|
this._showUploadIcon = true;
|
|
52
|
+
// ✅ NEW: Collapsible state
|
|
53
|
+
this._collapsible = false;
|
|
54
|
+
this._collapsed = false;
|
|
55
|
+
this._summaryTemplate = null;
|
|
56
|
+
this._detailsElement = null;
|
|
52
57
|
this._driver = new TabularDriver(options.dbName ?? 'jux-dataframes', options.storeName ?? 'frames');
|
|
53
58
|
this._showStatus = options.showStatus ?? true;
|
|
54
59
|
this._icon = options.icon ?? '';
|
|
@@ -67,6 +72,10 @@ export class DataFrameComponent extends BaseComponent {
|
|
|
67
72
|
// ✅ NEW: Storage options
|
|
68
73
|
this._persistToIndexedDB = options.persistToIndexedDB ?? false;
|
|
69
74
|
this._clearStorageOnFileRemove = options.clearStorageOnFileRemove ?? true;
|
|
75
|
+
// ✅ NEW: Collapsible options
|
|
76
|
+
this._collapsible = options.collapsible ?? false;
|
|
77
|
+
this._collapsed = options.collapsed ?? false;
|
|
78
|
+
this._summaryTemplate = options.summaryTemplate ?? null;
|
|
70
79
|
}
|
|
71
80
|
getTriggerEvents() { return TRIGGER_EVENTS; }
|
|
72
81
|
getCallbackEvents() { return CALLBACK_EVENTS; }
|
|
@@ -502,6 +511,8 @@ export class DataFrameComponent extends BaseComponent {
|
|
|
502
511
|
const columnDefs = this._df.columns.map(col => ({ key: col, label: col }));
|
|
503
512
|
this._table.columns(columnDefs).rows(this._df.toRows());
|
|
504
513
|
}
|
|
514
|
+
// ✅ Update summary if collapsible
|
|
515
|
+
this._updateSummary();
|
|
505
516
|
const isMalformed = this._detectMalformedData(this._df);
|
|
506
517
|
if (isMalformed && this._rawFileData) {
|
|
507
518
|
this._updateStatus(`${sourceName} — ${this._df.height} rows × ${this._df.width} cols (Data may need reformatting)`, 'warning');
|
|
@@ -535,6 +546,26 @@ export class DataFrameComponent extends BaseComponent {
|
|
|
535
546
|
}
|
|
536
547
|
this._triggerCallback('load', this._df, null, this);
|
|
537
548
|
}
|
|
549
|
+
/**
|
|
550
|
+
* Update the collapsible summary text
|
|
551
|
+
*/
|
|
552
|
+
_updateSummary() {
|
|
553
|
+
if (!this._collapsible || !this._detailsElement)
|
|
554
|
+
return;
|
|
555
|
+
const summary = this._detailsElement.querySelector('.jux-dataframe-summary-text');
|
|
556
|
+
if (!summary)
|
|
557
|
+
return;
|
|
558
|
+
if (!this._df) {
|
|
559
|
+
summary.textContent = 'No data loaded';
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
if (this._summaryTemplate) {
|
|
563
|
+
summary.textContent = this._summaryTemplate(this._df);
|
|
564
|
+
}
|
|
565
|
+
else {
|
|
566
|
+
summary.textContent = `${this.state.sourceName} — ${this._df.height} rows × ${this._df.width} cols`;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
538
569
|
/* ═══════════════════════════════════════════════════
|
|
539
570
|
* MALFORMED DATA DETECTION
|
|
540
571
|
* ═══════════════════════════════════════════════════ */
|
|
@@ -985,15 +1016,46 @@ export class DataFrameComponent extends BaseComponent {
|
|
|
985
1016
|
statusBar.textContent = 'No data loaded.';
|
|
986
1017
|
wrapper.appendChild(statusBar);
|
|
987
1018
|
}
|
|
1019
|
+
// ✅ NEW: Wrap table in collapsible details if enabled
|
|
1020
|
+
let tableContainer;
|
|
1021
|
+
if (this._collapsible) {
|
|
1022
|
+
const details = document.createElement('details');
|
|
1023
|
+
details.className = 'jux-dataframe-details';
|
|
1024
|
+
details.open = !this._collapsed;
|
|
1025
|
+
this._detailsElement = details;
|
|
1026
|
+
const summary = document.createElement('summary');
|
|
1027
|
+
summary.className = 'jux-dataframe-summary';
|
|
1028
|
+
const chevron = document.createElement('span');
|
|
1029
|
+
chevron.className = 'jux-dataframe-summary-chevron';
|
|
1030
|
+
chevron.innerHTML = '▶';
|
|
1031
|
+
summary.appendChild(chevron);
|
|
1032
|
+
const textSpan = document.createElement('span');
|
|
1033
|
+
textSpan.className = 'jux-dataframe-summary-text';
|
|
1034
|
+
textSpan.textContent = 'No data loaded';
|
|
1035
|
+
summary.appendChild(textSpan);
|
|
1036
|
+
details.appendChild(summary);
|
|
1037
|
+
const content = document.createElement('div');
|
|
1038
|
+
content.className = 'jux-dataframe-details-content';
|
|
1039
|
+
details.appendChild(content);
|
|
1040
|
+
wrapper.appendChild(details);
|
|
1041
|
+
tableContainer = content;
|
|
1042
|
+
// Track toggle state
|
|
1043
|
+
details.addEventListener('toggle', () => {
|
|
1044
|
+
this._collapsed = !details.open;
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
1047
|
+
else {
|
|
1048
|
+
tableContainer = wrapper;
|
|
1049
|
+
}
|
|
988
1050
|
const tbl = new Table(`${this._id}-table`, {
|
|
989
1051
|
striped: this._tableOptions.striped,
|
|
990
1052
|
hoverable: this._tableOptions.hoverable,
|
|
991
1053
|
sortable: this._tableOptions.sortable,
|
|
992
|
-
filterable: this._tableOptions.filterable,
|
|
1054
|
+
filterable: this._tableOptions.filterable,
|
|
993
1055
|
paginated: this._tableOptions.paginated,
|
|
994
1056
|
rowsPerPage: this._tableOptions.rowsPerPage
|
|
995
1057
|
});
|
|
996
|
-
tbl.render(
|
|
1058
|
+
tbl.render(tableContainer);
|
|
997
1059
|
this._table = tbl;
|
|
998
1060
|
if (this._pendingSource) {
|
|
999
1061
|
const fn = this._pendingSource;
|
|
@@ -28,9 +28,12 @@ export interface DataFrameOptions {
|
|
|
28
28
|
showReshapeWarning?: boolean;
|
|
29
29
|
style?: string;
|
|
30
30
|
class?: string;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
persistToIndexedDB?: boolean;
|
|
32
|
+
clearStorageOnFileRemove?: boolean;
|
|
33
|
+
// ✅ NEW: Collapsible options
|
|
34
|
+
collapsible?: boolean; // Enable collapse toggle
|
|
35
|
+
collapsed?: boolean; // Initial collapsed state (default: false = expanded)
|
|
36
|
+
summaryTemplate?: (df: DataFrame) => string; // Custom summary text
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
type DataFrameState = BaseState & {
|
|
@@ -77,6 +80,11 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
|
|
|
77
80
|
private _uploadAccept: string = '.csv,.tsv,.txt,.xlsx,.xls';
|
|
78
81
|
private _uploadDescription: string = '';
|
|
79
82
|
private _showUploadIcon: boolean = true;
|
|
83
|
+
// ✅ NEW: Collapsible state
|
|
84
|
+
private _collapsible: boolean = false;
|
|
85
|
+
private _collapsed: boolean = false;
|
|
86
|
+
private _summaryTemplate: ((df: DataFrame) => string) | null = null;
|
|
87
|
+
private _detailsElement: HTMLDetailsElement | null = null;
|
|
80
88
|
|
|
81
89
|
constructor(id: string, options: DataFrameOptions = {}) {
|
|
82
90
|
super(id, {
|
|
@@ -114,6 +122,10 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
|
|
|
114
122
|
// ✅ NEW: Storage options
|
|
115
123
|
this._persistToIndexedDB = options.persistToIndexedDB ?? false;
|
|
116
124
|
this._clearStorageOnFileRemove = options.clearStorageOnFileRemove ?? true;
|
|
125
|
+
// ✅ NEW: Collapsible options
|
|
126
|
+
this._collapsible = options.collapsible ?? false;
|
|
127
|
+
this._collapsed = options.collapsed ?? false;
|
|
128
|
+
this._summaryTemplate = options.summaryTemplate ?? null;
|
|
117
129
|
}
|
|
118
130
|
|
|
119
131
|
protected getTriggerEvents(): readonly string[] { return TRIGGER_EVENTS; }
|
|
@@ -611,6 +623,9 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
|
|
|
611
623
|
this._table.columns(columnDefs).rows(this._df.toRows());
|
|
612
624
|
}
|
|
613
625
|
|
|
626
|
+
// ✅ Update summary if collapsible
|
|
627
|
+
this._updateSummary();
|
|
628
|
+
|
|
614
629
|
const isMalformed = this._detectMalformedData(this._df!);
|
|
615
630
|
|
|
616
631
|
if (isMalformed && this._rawFileData) {
|
|
@@ -652,6 +667,27 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
|
|
|
652
667
|
this._triggerCallback('load', this._df, null, this);
|
|
653
668
|
}
|
|
654
669
|
|
|
670
|
+
/**
|
|
671
|
+
* Update the collapsible summary text
|
|
672
|
+
*/
|
|
673
|
+
private _updateSummary(): void {
|
|
674
|
+
if (!this._collapsible || !this._detailsElement) return;
|
|
675
|
+
|
|
676
|
+
const summary = this._detailsElement.querySelector('.jux-dataframe-summary-text');
|
|
677
|
+
if (!summary) return;
|
|
678
|
+
|
|
679
|
+
if (!this._df) {
|
|
680
|
+
summary.textContent = 'No data loaded';
|
|
681
|
+
return;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
if (this._summaryTemplate) {
|
|
685
|
+
summary.textContent = this._summaryTemplate(this._df);
|
|
686
|
+
} else {
|
|
687
|
+
summary.textContent = `${this.state.sourceName} — ${this._df.height} rows × ${this._df.width} cols`;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
|
|
655
691
|
/* ═══════════════════════════════════════════════════
|
|
656
692
|
* MALFORMED DATA DETECTION
|
|
657
693
|
* ═══════════════════════════════════════════════════ */
|
|
@@ -1161,15 +1197,54 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
|
|
|
1161
1197
|
wrapper.appendChild(statusBar);
|
|
1162
1198
|
}
|
|
1163
1199
|
|
|
1200
|
+
// ✅ NEW: Wrap table in collapsible details if enabled
|
|
1201
|
+
let tableContainer: HTMLElement;
|
|
1202
|
+
|
|
1203
|
+
if (this._collapsible) {
|
|
1204
|
+
const details = document.createElement('details');
|
|
1205
|
+
details.className = 'jux-dataframe-details';
|
|
1206
|
+
details.open = !this._collapsed;
|
|
1207
|
+
this._detailsElement = details;
|
|
1208
|
+
|
|
1209
|
+
const summary = document.createElement('summary');
|
|
1210
|
+
summary.className = 'jux-dataframe-summary';
|
|
1211
|
+
|
|
1212
|
+
const chevron = document.createElement('span');
|
|
1213
|
+
chevron.className = 'jux-dataframe-summary-chevron';
|
|
1214
|
+
chevron.innerHTML = '▶';
|
|
1215
|
+
summary.appendChild(chevron);
|
|
1216
|
+
|
|
1217
|
+
const textSpan = document.createElement('span');
|
|
1218
|
+
textSpan.className = 'jux-dataframe-summary-text';
|
|
1219
|
+
textSpan.textContent = 'No data loaded';
|
|
1220
|
+
summary.appendChild(textSpan);
|
|
1221
|
+
|
|
1222
|
+
details.appendChild(summary);
|
|
1223
|
+
|
|
1224
|
+
const content = document.createElement('div');
|
|
1225
|
+
content.className = 'jux-dataframe-details-content';
|
|
1226
|
+
details.appendChild(content);
|
|
1227
|
+
|
|
1228
|
+
wrapper.appendChild(details);
|
|
1229
|
+
tableContainer = content;
|
|
1230
|
+
|
|
1231
|
+
// Track toggle state
|
|
1232
|
+
details.addEventListener('toggle', () => {
|
|
1233
|
+
this._collapsed = !details.open;
|
|
1234
|
+
});
|
|
1235
|
+
} else {
|
|
1236
|
+
tableContainer = wrapper;
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1164
1239
|
const tbl = new Table(`${this._id}-table`, {
|
|
1165
1240
|
striped: this._tableOptions.striped,
|
|
1166
1241
|
hoverable: this._tableOptions.hoverable,
|
|
1167
1242
|
sortable: this._tableOptions.sortable,
|
|
1168
|
-
filterable: this._tableOptions.filterable,
|
|
1243
|
+
filterable: this._tableOptions.filterable,
|
|
1169
1244
|
paginated: this._tableOptions.paginated,
|
|
1170
1245
|
rowsPerPage: this._tableOptions.rowsPerPage
|
|
1171
1246
|
});
|
|
1172
|
-
tbl.render(
|
|
1247
|
+
tbl.render(tableContainer);
|
|
1173
1248
|
this._table = tbl;
|
|
1174
1249
|
|
|
1175
1250
|
if (this._pendingSource) {
|
package/lib/styles/shadcn.css
CHANGED
|
@@ -848,4 +848,74 @@ code {
|
|
|
848
848
|
|
|
849
849
|
.scroll-both {
|
|
850
850
|
overflow: auto;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
/* ═══════════════════════════════════════════════════════════════════
|
|
854
|
+
* DATAFRAME COLLAPSIBLE
|
|
855
|
+
* ═══════════════════════════════════════════════════════════════════ */
|
|
856
|
+
|
|
857
|
+
.jux-dataframe-details {
|
|
858
|
+
border: 1px solid hsl(var(--border));
|
|
859
|
+
border-radius: var(--radius);
|
|
860
|
+
background: hsl(var(--background));
|
|
861
|
+
overflow: hidden;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
.jux-dataframe-summary {
|
|
865
|
+
display: flex;
|
|
866
|
+
align-items: center;
|
|
867
|
+
gap: 0.5rem;
|
|
868
|
+
padding: 0.75rem 1rem;
|
|
869
|
+
cursor: pointer;
|
|
870
|
+
user-select: none;
|
|
871
|
+
font-weight: 500;
|
|
872
|
+
font-size: 0.875rem;
|
|
873
|
+
color: hsl(var(--foreground));
|
|
874
|
+
background: hsl(var(--muted) / 0.3);
|
|
875
|
+
border-bottom: 1px solid transparent;
|
|
876
|
+
transition: all 0.15s;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
.jux-dataframe-summary:hover {
|
|
880
|
+
background: hsl(var(--muted) / 0.5);
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
.jux-dataframe-details[open] .jux-dataframe-summary {
|
|
884
|
+
border-bottom-color: hsl(var(--border));
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
/* Hide default marker */
|
|
888
|
+
.jux-dataframe-summary::-webkit-details-marker,
|
|
889
|
+
.jux-dataframe-summary::marker {
|
|
890
|
+
display: none;
|
|
891
|
+
content: '';
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
.jux-dataframe-summary-chevron {
|
|
895
|
+
display: inline-flex;
|
|
896
|
+
align-items: center;
|
|
897
|
+
justify-content: center;
|
|
898
|
+
width: 1rem;
|
|
899
|
+
height: 1rem;
|
|
900
|
+
font-size: 0.625rem;
|
|
901
|
+
color: hsl(var(--muted-foreground));
|
|
902
|
+
transition: transform 0.2s ease;
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
.jux-dataframe-details[open] .jux-dataframe-summary-chevron {
|
|
906
|
+
transform: rotate(90deg);
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
.jux-dataframe-summary-text {
|
|
910
|
+
flex: 1;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
.jux-dataframe-details-content {
|
|
914
|
+
padding: 0;
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
/* Remove border from table inside collapsible */
|
|
918
|
+
.jux-dataframe-details-content .jux-table-wrapper {
|
|
919
|
+
border: none;
|
|
920
|
+
border-radius: 0;
|
|
851
921
|
}
|