juxscript 1.1.224 → 1.1.226

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.
@@ -64,6 +64,7 @@ export declare class DataFrameComponent extends BaseComponent<DataFrameState> {
64
64
  private _collapsed;
65
65
  private _summaryTemplate;
66
66
  private _detailsElement;
67
+ private _settingsModal;
67
68
  constructor(id: string, options?: DataFrameOptions);
68
69
  protected getTriggerEvents(): readonly string[];
69
70
  protected getCallbackEvents(): readonly string[];
@@ -172,13 +173,26 @@ export declare class DataFrameComponent extends BaseComponent<DataFrameState> {
172
173
  private _updateStatus;
173
174
  private _setDataFrame;
174
175
  /**
175
- * Append settings button to status bar
176
+ * Show the data view (table + settings gear), hide upload area
176
177
  */
177
- private _appendSettingsButton;
178
+ private _showDataView;
179
+ /**
180
+ * Hide data view, show upload area
181
+ */
182
+ private _hideDataView;
183
+ /**
184
+ * Update the settings gear tooltip/info
185
+ */
186
+ private _updateSettingsGear;
187
+ /**
188
+ * Show the unified settings modal
189
+ */
190
+ private _showSettingsModal;
178
191
  /**
179
192
  * Update the collapsible summary text
180
193
  */
181
194
  private _updateSummary;
195
+ private _appendSettingsButton;
182
196
  private _detectMalformedData;
183
197
  private _showReshapeModal;
184
198
  private _cleanupReshapeModal;
@@ -1 +1 @@
1
- {"version":3,"file":"dataframe.d.ts","sourceRoot":"","sources":["dataframe.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dataframe.d.ts","sourceRoot":"","sources":["dataframe.ts"],"names":[],"mappings":"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"}
@@ -52,6 +52,7 @@ export class DataFrameComponent extends BaseComponent {
52
52
  this._collapsed = false;
53
53
  this._summaryTemplate = null;
54
54
  this._detailsElement = null;
55
+ this._settingsModal = null;
55
56
  this._driver = new TabularDriver(options.dbName ?? 'jux-dataframes', options.storeName ?? 'frames');
56
57
  this._showStatus = options.showStatus ?? true;
57
58
  this._icon = options.icon ?? '';
@@ -253,17 +254,15 @@ export class DataFrameComponent extends BaseComponent {
253
254
  if (existingTabs)
254
255
  existingTabs.remove();
255
256
  }
256
- // ✅ Hide details element when cleared
257
+ // ✅ Hide data view, show upload
258
+ this._hideDataView();
259
+ // ✅ Hide collapsible details
257
260
  if (this._collapsible && this._detailsElement) {
258
261
  this._detailsElement.style.display = 'none';
259
262
  }
260
- // ✅ Hide status when cleared (for inline upload mode)
261
- const statusEl = document.getElementById(`${this._id}-status`);
262
- if (statusEl && this._inlineUpload) {
263
- statusEl.style.display = 'none';
264
- }
265
- else if (statusEl) {
266
- this._updateStatus('No data loaded.', 'empty');
263
+ // ✅ Clear file from upload component
264
+ if (this._uploadRef) {
265
+ this._uploadRef.clear();
267
266
  }
268
267
  return this;
269
268
  }
@@ -543,23 +542,28 @@ export class DataFrameComponent extends BaseComponent {
543
542
  const el = document.getElementById(`${this._id}-status`);
544
543
  if (!el)
545
544
  return;
546
- // Always show status (inline with upload button)
547
- el.style.display = '';
548
- el.className = 'jux-dataframe-status';
549
- if (type)
545
+ // Only show status during loading/error states
546
+ if (type === 'loading' || type === 'error') {
547
+ el.style.display = '';
548
+ el.className = 'jux-dataframe-status';
550
549
  el.classList.add(`jux-dataframe-status-${type}`);
551
- el.innerHTML = '';
552
- if (this._icon && (type === 'success' || type === 'warning')) {
553
- const iconEl = renderIcon(this._icon);
554
- iconEl.style.width = '16px';
555
- iconEl.style.height = '16px';
556
- iconEl.style.marginRight = '6px';
557
- iconEl.style.verticalAlign = 'middle';
558
- el.appendChild(iconEl);
550
+ el.innerHTML = '';
551
+ if (this._icon && type === 'error') {
552
+ const iconEl = renderIcon(this._icon);
553
+ iconEl.style.width = '16px';
554
+ iconEl.style.height = '16px';
555
+ iconEl.style.marginRight = '6px';
556
+ iconEl.style.verticalAlign = 'middle';
557
+ el.appendChild(iconEl);
558
+ }
559
+ const span = document.createElement('span');
560
+ span.textContent = text;
561
+ el.appendChild(span);
562
+ }
563
+ else {
564
+ // ✅ Hide status after successful load - table speaks for itself
565
+ el.style.display = 'none';
559
566
  }
560
- const span = document.createElement('span');
561
- span.textContent = text;
562
- el.appendChild(span);
563
567
  }
564
568
  _setDataFrame(df, sourceName) {
565
569
  this._df = df;
@@ -589,66 +593,226 @@ export class DataFrameComponent extends BaseComponent {
589
593
  const columnDefs = this._df.columns.map(col => ({ key: col, label: col }));
590
594
  this._table.columns(columnDefs).rows(this._df.toRows());
591
595
  }
592
- // ✅ Show the details element now that data is loaded
596
+ // ✅ Show the table container, hide upload area
597
+ this._showDataView();
598
+ // ✅ Update collapsible summary if enabled
593
599
  if (this._collapsible && this._detailsElement) {
594
600
  this._detailsElement.style.display = '';
595
601
  this._updateSummary();
596
602
  }
603
+ // ✅ Hide status - data is loaded
604
+ this._updateStatus('', 'success');
605
+ this._triggerCallback('load', this._df, null, this);
606
+ }
607
+ /**
608
+ * Show the data view (table + settings gear), hide upload area
609
+ */
610
+ _showDataView() {
611
+ const wrapper = document.getElementById(this._id);
612
+ if (!wrapper)
613
+ return;
614
+ // Hide upload area
615
+ const uploadArea = wrapper.querySelector('.jux-dataframe-upload-area');
616
+ if (uploadArea) {
617
+ uploadArea.style.display = 'none';
618
+ }
619
+ // Show data container (table + toolbar)
620
+ const dataContainer = wrapper.querySelector('.jux-dataframe-data');
621
+ if (dataContainer) {
622
+ dataContainer.style.display = '';
623
+ }
624
+ // Update settings gear with file info
625
+ this._updateSettingsGear();
626
+ }
627
+ /**
628
+ * Hide data view, show upload area
629
+ */
630
+ _hideDataView() {
631
+ const wrapper = document.getElementById(this._id);
632
+ if (!wrapper)
633
+ return;
634
+ // Show upload area
635
+ const uploadArea = wrapper.querySelector('.jux-dataframe-upload-area');
636
+ if (uploadArea) {
637
+ uploadArea.style.display = '';
638
+ }
639
+ // Hide data container
640
+ const dataContainer = wrapper.querySelector('.jux-dataframe-data');
641
+ if (dataContainer) {
642
+ dataContainer.style.display = 'none';
643
+ }
644
+ }
645
+ /**
646
+ * Update the settings gear tooltip/info
647
+ */
648
+ _updateSettingsGear() {
649
+ const gear = document.getElementById(`${this._id}-settings-gear`);
650
+ if (!gear || !this._df)
651
+ return;
597
652
  const isMalformed = this._detectMalformedData(this._df);
598
- // Update status with settings button
599
- if (isMalformed && this._rawFileData) {
600
- this._updateStatus(`${sourceName} ${this._df.height} rows × ${this._df.width} cols`, 'warning');
601
- this._appendSettingsButton('Fix Import Settings', 'warning');
653
+ if (isMalformed) {
654
+ gear.classList.add('jux-dataframe-gear-warning');
655
+ gear.title = `${this.state.sourceName} May need reformatting`;
602
656
  }
603
657
  else {
604
- this._updateStatus(`${sourceName} — ${this._df.height} rows × ${this._df.width} cols`, 'success');
605
- if (this._rawFileData) {
606
- this._appendSettingsButton('Import Settings', 'ghost');
607
- }
658
+ gear.classList.remove('jux-dataframe-gear-warning');
659
+ gear.title = `${this.state.sourceName} — ${this._df.height} rows × ${this._df.width} cols`;
608
660
  }
609
- this._triggerCallback('load', this._df, null, this);
610
661
  }
611
662
  /**
612
- * Append settings button to status bar
663
+ * Show the unified settings modal
613
664
  */
614
- _appendSettingsButton(label, variant) {
665
+ _showSettingsModal() {
666
+ this._cleanupReshapeModal();
667
+ const fileInfo = this._rawFileData?.file;
668
+ const isMalformed = this._df ? this._detectMalformedData(this._df) : false;
669
+ this._settingsModal = new Modal(`${this._id}-settings-modal`, {
670
+ title: 'Data Settings',
671
+ size: 'medium',
672
+ close: true,
673
+ backdropClose: true
674
+ });
675
+ const fileSizeKB = fileInfo ? (fileInfo.size / 1024).toFixed(1) : '0';
676
+ const fileName = fileInfo?.name || this.state.sourceName || 'Unknown';
677
+ let contentHTML = `
678
+ <div class="jux-dataframe-settings-content">
679
+ <!-- File Info Section -->
680
+ <div class="jux-dataframe-settings-section">
681
+ <div class="jux-dataframe-settings-label">Source</div>
682
+ <div class="jux-dataframe-settings-value">
683
+ <strong>${this._escapeHtml(fileName)}</strong>
684
+ ${fileInfo ? `<span class="jux-muted" style="margin-left: 8px;">${fileSizeKB} KB</span>` : ''}
685
+ </div>
686
+ </div>
687
+
688
+ <!-- Data Info Section -->
689
+ <div class="jux-dataframe-settings-section">
690
+ <div class="jux-dataframe-settings-label">Data</div>
691
+ <div class="jux-dataframe-settings-value">
692
+ ${this._df ? `${this._df.height} rows × ${this._df.width} columns` : 'No data loaded'}
693
+ ${isMalformed ? '<span style="color: hsl(var(--warning)); margin-left: 8px;">⚠️ May need reformatting</span>' : ''}
694
+ </div>
695
+ </div>
696
+ `;
697
+ // Import Settings button (only if we have raw file data)
698
+ if (this._rawFileData) {
699
+ contentHTML += `
700
+ <div class="jux-dataframe-settings-section">
701
+ <div class="jux-dataframe-settings-label">Import</div>
702
+ <div class="jux-dataframe-settings-value">
703
+ <button id="${this._id}-adjust-import" class="jux-button jux-button-outline jux-button-sm">
704
+ ⚙️ Adjust Header Row / Delimiter
705
+ </button>
706
+ </div>
707
+ </div>
708
+ `;
709
+ }
710
+ contentHTML += `
711
+ </div>
712
+ `;
713
+ this._settingsModal
714
+ .content(contentHTML)
715
+ .actions([
716
+ {
717
+ label: 'Remove Data',
718
+ variant: 'secondary',
719
+ click: async () => {
720
+ await this.clear();
721
+ this._settingsModal.closeModal();
722
+ }
723
+ },
724
+ {
725
+ label: 'Done',
726
+ variant: 'primary',
727
+ click: () => this._settingsModal.closeModal()
728
+ }
729
+ ]);
730
+ this._settingsModal.render(document.body);
731
+ this._settingsModal.open();
732
+ // Wire up import settings button
615
733
  requestAnimationFrame(() => {
616
- const statusEl = document.getElementById(`${this._id}-status`);
617
- if (statusEl) {
618
- const settingsBtn = document.createElement('button');
619
- settingsBtn.textContent = label;
620
- settingsBtn.className = `jux-button jux-button-sm jux-button-${variant}`;
621
- settingsBtn.style.marginLeft = '0.5rem';
622
- settingsBtn.addEventListener('click', () => this._showReshapeModal());
623
- statusEl.appendChild(settingsBtn);
734
+ const adjustBtn = document.getElementById(`${this._id}-adjust-import`);
735
+ if (adjustBtn) {
736
+ adjustBtn.addEventListener('click', () => {
737
+ this._settingsModal.closeModal();
738
+ this._showReshapeModal();
739
+ });
624
740
  }
625
741
  });
626
742
  }
627
743
  /**
628
744
  * Update the collapsible summary text
629
745
  */
630
- _updateSummary() {
746
+ _updateSummary(isMalformed) {
631
747
  if (!this._collapsible || !this._detailsElement)
632
748
  return;
633
- const summaryTextEl = this._detailsElement.querySelector('.jux-dataframe-summary-text');
634
- if (!summaryTextEl)
635
- return;
636
- if (!this._df) {
637
- // Don't show anything if no data
749
+ const summaryEl = this._detailsElement.querySelector('.jux-dataframe-summary');
750
+ if (!summaryEl)
638
751
  return;
752
+ const malformed = isMalformed ?? (this._df ? this._detectMalformedData(this._df) : false);
753
+ const summaryTextEl = summaryEl.querySelector('.jux-dataframe-summary-text');
754
+ if (summaryTextEl) {
755
+ if (!this._df) {
756
+ summaryTextEl.textContent = 'No data loaded';
757
+ }
758
+ else if (this._summaryTemplate) {
759
+ summaryTextEl.textContent = this._summaryTemplate(this._df);
760
+ }
761
+ else {
762
+ const suffix = malformed ? ' ⚠️' : '';
763
+ summaryTextEl.textContent = `${this.state.sourceName || 'Data'} — ${this._df.height} rows × ${this._df.width} cols${suffix}`;
764
+ }
639
765
  }
640
- if (this._summaryTemplate) {
641
- summaryTextEl.textContent = this._summaryTemplate(this._df);
766
+ // Add/update settings gear in summary
767
+ let gearBtn = summaryEl.querySelector('.jux-dataframe-summary-gear');
768
+ if (this._df) {
769
+ if (!gearBtn) {
770
+ gearBtn = document.createElement('button');
771
+ gearBtn.className = 'jux-dataframe-summary-gear';
772
+ gearBtn.type = 'button';
773
+ gearBtn.innerHTML = '⚙️';
774
+ gearBtn.addEventListener('click', (e) => {
775
+ e.stopPropagation();
776
+ this._showSettingsModal();
777
+ });
778
+ summaryEl.appendChild(gearBtn);
779
+ }
780
+ if (malformed) {
781
+ gearBtn.classList.add('jux-dataframe-gear-warning');
782
+ }
783
+ else {
784
+ gearBtn.classList.remove('jux-dataframe-gear-warning');
785
+ }
642
786
  }
643
- else {
644
- const isMalformed = this._detectMalformedData(this._df);
645
- const suffix = isMalformed ? ' ⚠️' : '';
646
- summaryTextEl.textContent = `${this.state.sourceName || 'Data'} — ${this._df.height} rows × ${this._df.width} cols${suffix}`;
787
+ else if (gearBtn) {
788
+ gearBtn.remove();
647
789
  }
648
790
  }
649
791
  /* ═══════════════════════════════════════════════════
650
792
  * MALFORMED DATA DETECTION
651
793
  * ═══════════════════════════════════════════════════ */
794
+ _appendSettingsButton(label, variant) {
795
+ const statusEl = document.getElementById(`${this._id}-status`);
796
+ if (!statusEl)
797
+ return;
798
+ // Remove existing settings button if any
799
+ const existing = statusEl.querySelector('.jux-dataframe-settings-btn');
800
+ if (existing)
801
+ existing.remove();
802
+ const btn = document.createElement('button');
803
+ btn.className = `jux-dataframe-settings-btn jux-dataframe-settings-btn-${variant}`;
804
+ btn.type = 'button';
805
+ btn.textContent = `⚙️ ${label}`;
806
+ btn.style.marginLeft = '8px';
807
+ btn.style.cursor = 'pointer';
808
+ btn.style.fontSize = '0.8rem';
809
+ btn.style.padding = '2px 8px';
810
+ btn.style.borderRadius = 'var(--radius, 4px)';
811
+ btn.style.border = '1px solid hsl(var(--border))';
812
+ btn.style.background = variant === 'warning' ? 'hsl(38 92% 50% / 0.15)' : 'transparent';
813
+ btn.addEventListener('click', () => this._showReshapeModal());
814
+ statusEl.appendChild(btn);
815
+ }
652
816
  _detectMalformedData(df) {
653
817
  const columns = df.columns;
654
818
  const rows = df.toRows();
@@ -771,8 +935,8 @@ export class DataFrameComponent extends BaseComponent {
771
935
  if (nonEmpty.length < values.length * 0.5)
772
936
  continue;
773
937
  const nonNumeric = nonEmpty.filter(v => {
774
- const str = String(v).trim();
775
- return isNaN(Number(str)) && str !== '';
938
+ const trimmed = v.trim();
939
+ return isNaN(Number(trimmed)) && trimmed !== '';
776
940
  }).length;
777
941
  if (nonNumeric >= nonEmpty.length * 0.7) {
778
942
  selectedSheetRow = sheetRow;
@@ -1045,8 +1209,10 @@ export class DataFrameComponent extends BaseComponent {
1045
1209
  wrapper.className += ` ${className}`;
1046
1210
  if (style)
1047
1211
  wrapper.setAttribute('style', style);
1212
+ // ═══════════════════════════════════════════════════
1213
+ // UPLOAD AREA (shown initially, hidden after data loads)
1214
+ // ═══════════════════════════════════════════════════
1048
1215
  if (this._inlineUpload) {
1049
- // ✅ NEW: Enhanced upload area with better styling
1050
1216
  const uploadArea = document.createElement('div');
1051
1217
  uploadArea.className = 'jux-dataframe-upload-area';
1052
1218
  uploadArea.id = `${this._id}-upload-area`;
@@ -1060,11 +1226,9 @@ export class DataFrameComponent extends BaseComponent {
1060
1226
  }
1061
1227
  const upload = new FileUpload(`${this._id}-upload`, uploadOpts);
1062
1228
  this._uploadRef = upload;
1063
- // ✅ Handle file change AND file clear
1064
1229
  this._pendingSource = async () => {
1065
1230
  upload.bind('change', async (files) => {
1066
1231
  if (!files || files.length === 0) {
1067
- // File was cleared - reset the table
1068
1232
  await this.clear();
1069
1233
  return;
1070
1234
  }
@@ -1075,12 +1239,12 @@ export class DataFrameComponent extends BaseComponent {
1075
1239
  uploadContainer.className = 'jux-dataframe-upload';
1076
1240
  uploadContainer.id = `${this._id}-upload-container`;
1077
1241
  uploadArea.appendChild(uploadContainer);
1078
- // Status bar INLINE with upload (inside upload area)
1242
+ // Status bar (for loading/error states only)
1079
1243
  if (this._showStatus) {
1080
1244
  const statusBar = document.createElement('div');
1081
- statusBar.className = 'jux-dataframe-status jux-dataframe-status-empty';
1245
+ statusBar.className = 'jux-dataframe-status';
1082
1246
  statusBar.id = `${this._id}-status`;
1083
- statusBar.style.display = 'none'; // Hidden until needed
1247
+ statusBar.style.display = 'none';
1084
1248
  uploadArea.appendChild(statusBar);
1085
1249
  }
1086
1250
  if (this._uploadDescription) {
@@ -1095,22 +1259,34 @@ export class DataFrameComponent extends BaseComponent {
1095
1259
  }
1096
1260
  else {
1097
1261
  container.appendChild(wrapper);
1098
- // ✅ Status bar for non-upload mode
1099
- if (this._showStatus) {
1100
- const statusBar = document.createElement('div');
1101
- statusBar.className = 'jux-dataframe-status jux-dataframe-status-empty';
1102
- statusBar.id = `${this._id}-status`;
1103
- statusBar.textContent = 'No data loaded.';
1104
- wrapper.appendChild(statusBar);
1105
- }
1106
1262
  }
1107
- // ✅ Collapsible details wrapper - HIDDEN until data loads
1263
+ // ═══════════════════════════════════════════════════
1264
+ // DATA CONTAINER (hidden initially, shown after data loads)
1265
+ // ═══════════════════════════════════════════════════
1266
+ const dataContainer = document.createElement('div');
1267
+ dataContainer.className = 'jux-dataframe-data';
1268
+ dataContainer.style.display = 'none'; // Hidden until data loads
1269
+ // ✅ Toolbar with settings gear
1270
+ const toolbar = document.createElement('div');
1271
+ toolbar.className = 'jux-dataframe-toolbar';
1272
+ const settingsGear = document.createElement('button');
1273
+ settingsGear.className = 'jux-dataframe-gear';
1274
+ settingsGear.id = `${this._id}-settings-gear`;
1275
+ settingsGear.type = 'button';
1276
+ settingsGear.innerHTML = '⚙️';
1277
+ settingsGear.title = 'Data Settings';
1278
+ settingsGear.addEventListener('click', () => this._showSettingsModal());
1279
+ toolbar.appendChild(settingsGear);
1280
+ dataContainer.appendChild(toolbar);
1281
+ // ═══════════════════════════════════════════════════
1282
+ // TABLE CONTAINER (inside data container or collapsible)
1283
+ // ═══════════════════════════════════════════════════
1108
1284
  let tableContainer;
1109
1285
  if (this._collapsible) {
1110
1286
  const details = document.createElement('details');
1111
1287
  details.className = 'jux-dataframe-details';
1112
1288
  details.open = !this._collapsed;
1113
- details.style.display = 'none'; // Hidden until data loads
1289
+ details.style.display = 'none'; // Hidden until data loads
1114
1290
  this._detailsElement = details;
1115
1291
  const summary = document.createElement('summary');
1116
1292
  summary.className = 'jux-dataframe-summary';
@@ -1120,21 +1296,24 @@ export class DataFrameComponent extends BaseComponent {
1120
1296
  summary.appendChild(chevron);
1121
1297
  const textSpan = document.createElement('span');
1122
1298
  textSpan.className = 'jux-dataframe-summary-text';
1123
- // Don't set text - will be set when data loads
1124
1299
  summary.appendChild(textSpan);
1125
1300
  details.appendChild(summary);
1126
1301
  const content = document.createElement('div');
1127
1302
  content.className = 'jux-dataframe-details-content';
1128
1303
  details.appendChild(content);
1129
- wrapper.appendChild(details);
1304
+ dataContainer.appendChild(details);
1130
1305
  tableContainer = content;
1131
1306
  details.addEventListener('toggle', () => {
1132
1307
  this._collapsed = !details.open;
1133
1308
  });
1134
1309
  }
1135
1310
  else {
1136
- tableContainer = wrapper;
1311
+ tableContainer = dataContainer;
1137
1312
  }
1313
+ wrapper.appendChild(dataContainer);
1314
+ // ═══════════════════════════════════════════════════
1315
+ // TABLE
1316
+ // ═══════════════════════════════════════════════════
1138
1317
  const tbl = new Table(`${this._id}-table`, {
1139
1318
  striped: this._tableOptions.striped,
1140
1319
  hoverable: this._tableOptions.hoverable,
@@ -83,6 +83,7 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
83
83
  private _collapsed: boolean = false;
84
84
  private _summaryTemplate: ((df: DataFrame) => string) | null = null;
85
85
  private _detailsElement: HTMLDetailsElement | null = null;
86
+ private _settingsModal: Modal | null = null;
86
87
 
87
88
  constructor(id: string, options: DataFrameOptions = {}) {
88
89
  super(id, {
@@ -310,17 +311,17 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
310
311
  if (existingTabs) existingTabs.remove();
311
312
  }
312
313
 
313
- // ✅ Hide details element when cleared
314
+ // ✅ Hide data view, show upload
315
+ this._hideDataView();
316
+
317
+ // ✅ Hide collapsible details
314
318
  if (this._collapsible && this._detailsElement) {
315
319
  this._detailsElement.style.display = 'none';
316
320
  }
317
321
 
318
- // ✅ Hide status when cleared (for inline upload mode)
319
- const statusEl = document.getElementById(`${this._id}-status`);
320
- if (statusEl && this._inlineUpload) {
321
- statusEl.style.display = 'none';
322
- } else if (statusEl) {
323
- this._updateStatus('No data loaded.', 'empty');
322
+ // ✅ Clear file from upload component
323
+ if (this._uploadRef) {
324
+ this._uploadRef.clear();
324
325
  }
325
326
 
326
327
  return this;
@@ -658,25 +659,29 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
658
659
  const el = document.getElementById(`${this._id}-status`);
659
660
  if (!el) return;
660
661
 
661
- // Always show status (inline with upload button)
662
- el.style.display = '';
663
- el.className = 'jux-dataframe-status';
664
- if (type) el.classList.add(`jux-dataframe-status-${type}`);
665
-
666
- el.innerHTML = '';
662
+ // Only show status during loading/error states
663
+ if (type === 'loading' || type === 'error') {
664
+ el.style.display = '';
665
+ el.className = 'jux-dataframe-status';
666
+ el.classList.add(`jux-dataframe-status-${type}`);
667
+ el.innerHTML = '';
668
+
669
+ if (this._icon && type === 'error') {
670
+ const iconEl = renderIcon(this._icon);
671
+ iconEl.style.width = '16px';
672
+ iconEl.style.height = '16px';
673
+ iconEl.style.marginRight = '6px';
674
+ iconEl.style.verticalAlign = 'middle';
675
+ el.appendChild(iconEl);
676
+ }
667
677
 
668
- if (this._icon && (type === 'success' || type === 'warning')) {
669
- const iconEl = renderIcon(this._icon);
670
- iconEl.style.width = '16px';
671
- iconEl.style.height = '16px';
672
- iconEl.style.marginRight = '6px';
673
- iconEl.style.verticalAlign = 'middle';
674
- el.appendChild(iconEl);
678
+ const span = document.createElement('span');
679
+ span.textContent = text;
680
+ el.appendChild(span);
681
+ } else {
682
+ // Hide status after successful load - table speaks for itself
683
+ el.style.display = 'none';
675
684
  }
676
-
677
- const span = document.createElement('span');
678
- span.textContent = text;
679
- el.appendChild(span);
680
685
  }
681
686
 
682
687
  private _setDataFrame(df: DataFrame, sourceName: string): void {
@@ -710,47 +715,169 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
710
715
  this._table.columns(columnDefs).rows(this._df.toRows());
711
716
  }
712
717
 
713
- // ✅ Show the details element now that data is loaded
718
+ // ✅ Show the table container, hide upload area
719
+ this._showDataView();
720
+
721
+ // ✅ Update collapsible summary if enabled
714
722
  if (this._collapsible && this._detailsElement) {
715
723
  this._detailsElement.style.display = '';
716
724
  this._updateSummary();
717
725
  }
718
726
 
719
- const isMalformed = this._detectMalformedData(this._df!);
727
+ // Hide status - data is loaded
728
+ this._updateStatus('', 'success');
720
729
 
721
- // Update status with settings button
722
- if (isMalformed && this._rawFileData) {
723
- this._updateStatus(
724
- `${sourceName} — ${this._df!.height} rows × ${this._df!.width} cols`,
725
- 'warning'
726
- );
727
- this._appendSettingsButton('Fix Import Settings', 'warning');
728
- } else {
729
- this._updateStatus(
730
- `${sourceName} — ${this._df!.height} rows × ${this._df!.width} cols`,
731
- 'success'
732
- );
733
- if (this._rawFileData) {
734
- this._appendSettingsButton('Import Settings', 'ghost');
735
- }
730
+ this._triggerCallback('load', this._df, null, this);
731
+ }
732
+
733
+ /**
734
+ * Show the data view (table + settings gear), hide upload area
735
+ */
736
+ private _showDataView(): void {
737
+ const wrapper = document.getElementById(this._id);
738
+ if (!wrapper) return;
739
+
740
+ // Hide upload area
741
+ const uploadArea = wrapper.querySelector('.jux-dataframe-upload-area') as HTMLElement;
742
+ if (uploadArea) {
743
+ uploadArea.style.display = 'none';
736
744
  }
737
745
 
738
- this._triggerCallback('load', this._df, null, this);
746
+ // Show data container (table + toolbar)
747
+ const dataContainer = wrapper.querySelector('.jux-dataframe-data') as HTMLElement;
748
+ if (dataContainer) {
749
+ dataContainer.style.display = '';
750
+ }
751
+
752
+ // Update settings gear with file info
753
+ this._updateSettingsGear();
739
754
  }
740
755
 
741
756
  /**
742
- * Append settings button to status bar
757
+ * Hide data view, show upload area
743
758
  */
744
- private _appendSettingsButton(label: string, variant: 'warning' | 'ghost'): void {
759
+ private _hideDataView(): void {
760
+ const wrapper = document.getElementById(this._id);
761
+ if (!wrapper) return;
762
+
763
+ // Show upload area
764
+ const uploadArea = wrapper.querySelector('.jux-dataframe-upload-area') as HTMLElement;
765
+ if (uploadArea) {
766
+ uploadArea.style.display = '';
767
+ }
768
+
769
+ // Hide data container
770
+ const dataContainer = wrapper.querySelector('.jux-dataframe-data') as HTMLElement;
771
+ if (dataContainer) {
772
+ dataContainer.style.display = 'none';
773
+ }
774
+ }
775
+
776
+ /**
777
+ * Update the settings gear tooltip/info
778
+ */
779
+ private _updateSettingsGear(): void {
780
+ const gear = document.getElementById(`${this._id}-settings-gear`);
781
+ if (!gear || !this._df) return;
782
+
783
+ const isMalformed = this._detectMalformedData(this._df);
784
+
785
+ if (isMalformed) {
786
+ gear.classList.add('jux-dataframe-gear-warning');
787
+ gear.title = `${this.state.sourceName} — May need reformatting`;
788
+ } else {
789
+ gear.classList.remove('jux-dataframe-gear-warning');
790
+ gear.title = `${this.state.sourceName} — ${this._df.height} rows × ${this._df.width} cols`;
791
+ }
792
+ }
793
+
794
+ /**
795
+ * Show the unified settings modal
796
+ */
797
+ private _showSettingsModal(): void {
798
+ this._cleanupReshapeModal();
799
+
800
+ const fileInfo = this._rawFileData?.file;
801
+ const isMalformed = this._df ? this._detectMalformedData(this._df) : false;
802
+
803
+ this._settingsModal = new Modal(`${this._id}-settings-modal`, {
804
+ title: 'Data Settings',
805
+ size: 'medium',
806
+ close: true,
807
+ backdropClose: true
808
+ });
809
+
810
+ const fileSizeKB = fileInfo ? (fileInfo.size / 1024).toFixed(1) : '0';
811
+ const fileName = fileInfo?.name || this.state.sourceName || 'Unknown';
812
+
813
+ let contentHTML = `
814
+ <div class="jux-dataframe-settings-content">
815
+ <!-- File Info Section -->
816
+ <div class="jux-dataframe-settings-section">
817
+ <div class="jux-dataframe-settings-label">Source</div>
818
+ <div class="jux-dataframe-settings-value">
819
+ <strong>${this._escapeHtml(fileName)}</strong>
820
+ ${fileInfo ? `<span class="jux-muted" style="margin-left: 8px;">${fileSizeKB} KB</span>` : ''}
821
+ </div>
822
+ </div>
823
+
824
+ <!-- Data Info Section -->
825
+ <div class="jux-dataframe-settings-section">
826
+ <div class="jux-dataframe-settings-label">Data</div>
827
+ <div class="jux-dataframe-settings-value">
828
+ ${this._df ? `${this._df.height} rows × ${this._df.width} columns` : 'No data loaded'}
829
+ ${isMalformed ? '<span style="color: hsl(var(--warning)); margin-left: 8px;">⚠️ May need reformatting</span>' : ''}
830
+ </div>
831
+ </div>
832
+ `;
833
+
834
+ // Import Settings button (only if we have raw file data)
835
+ if (this._rawFileData) {
836
+ contentHTML += `
837
+ <div class="jux-dataframe-settings-section">
838
+ <div class="jux-dataframe-settings-label">Import</div>
839
+ <div class="jux-dataframe-settings-value">
840
+ <button id="${this._id}-adjust-import" class="jux-button jux-button-outline jux-button-sm">
841
+ ⚙️ Adjust Header Row / Delimiter
842
+ </button>
843
+ </div>
844
+ </div>
845
+ `;
846
+ }
847
+
848
+ contentHTML += `
849
+ </div>
850
+ `;
851
+
852
+ this._settingsModal
853
+ .content(contentHTML)
854
+ .actions([
855
+ {
856
+ label: 'Remove Data',
857
+ variant: 'secondary',
858
+ click: async () => {
859
+ await this.clear();
860
+ this._settingsModal!.closeModal();
861
+ }
862
+ },
863
+ {
864
+ label: 'Done',
865
+ variant: 'primary',
866
+ click: () => this._settingsModal!.closeModal()
867
+ }
868
+ ]);
869
+
870
+ this._settingsModal.render(document.body);
871
+ this._settingsModal.open();
872
+
873
+ // Wire up import settings button
745
874
  requestAnimationFrame(() => {
746
- const statusEl = document.getElementById(`${this._id}-status`);
747
- if (statusEl) {
748
- const settingsBtn = document.createElement('button');
749
- settingsBtn.textContent = label;
750
- settingsBtn.className = `jux-button jux-button-sm jux-button-${variant}`;
751
- settingsBtn.style.marginLeft = '0.5rem';
752
- settingsBtn.addEventListener('click', () => this._showReshapeModal());
753
- statusEl.appendChild(settingsBtn);
875
+ const adjustBtn = document.getElementById(`${this._id}-adjust-import`);
876
+ if (adjustBtn) {
877
+ adjustBtn.addEventListener('click', () => {
878
+ this._settingsModal!.closeModal();
879
+ this._showReshapeModal();
880
+ });
754
881
  }
755
882
  });
756
883
  }
@@ -758,23 +885,49 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
758
885
  /**
759
886
  * Update the collapsible summary text
760
887
  */
761
- private _updateSummary(): void {
888
+ private _updateSummary(isMalformed?: boolean): void {
762
889
  if (!this._collapsible || !this._detailsElement) return;
763
890
 
764
- const summaryTextEl = this._detailsElement.querySelector('.jux-dataframe-summary-text');
765
- if (!summaryTextEl) return;
891
+ const summaryEl = this._detailsElement.querySelector('.jux-dataframe-summary');
892
+ if (!summaryEl) return;
766
893
 
767
- if (!this._df) {
768
- // Don't show anything if no data
769
- return;
894
+ const malformed = isMalformed ?? (this._df ? this._detectMalformedData(this._df) : false);
895
+
896
+ const summaryTextEl = summaryEl.querySelector('.jux-dataframe-summary-text');
897
+ if (summaryTextEl) {
898
+ if (!this._df) {
899
+ summaryTextEl.textContent = 'No data loaded';
900
+ } else if (this._summaryTemplate) {
901
+ summaryTextEl.textContent = this._summaryTemplate(this._df);
902
+ } else {
903
+ const suffix = malformed ? ' ⚠️' : '';
904
+ summaryTextEl.textContent = `${this.state.sourceName || 'Data'} — ${this._df.height} rows × ${this._df.width} cols${suffix}`;
905
+ }
770
906
  }
771
907
 
772
- if (this._summaryTemplate) {
773
- summaryTextEl.textContent = this._summaryTemplate(this._df);
774
- } else {
775
- const isMalformed = this._detectMalformedData(this._df);
776
- const suffix = isMalformed ? ' ⚠️' : '';
777
- summaryTextEl.textContent = `${this.state.sourceName || 'Data'} — ${this._df.height} rows × ${this._df.width} cols${suffix}`;
908
+ // Add/update settings gear in summary
909
+ let gearBtn = summaryEl.querySelector('.jux-dataframe-summary-gear') as HTMLButtonElement;
910
+
911
+ if (this._df) {
912
+ if (!gearBtn) {
913
+ gearBtn = document.createElement('button');
914
+ gearBtn.className = 'jux-dataframe-summary-gear';
915
+ gearBtn.type = 'button';
916
+ gearBtn.innerHTML = '⚙️';
917
+ gearBtn.addEventListener('click', (e) => {
918
+ e.stopPropagation();
919
+ this._showSettingsModal();
920
+ });
921
+ summaryEl.appendChild(gearBtn);
922
+ }
923
+
924
+ if (malformed) {
925
+ gearBtn.classList.add('jux-dataframe-gear-warning');
926
+ } else {
927
+ gearBtn.classList.remove('jux-dataframe-gear-warning');
928
+ }
929
+ } else if (gearBtn) {
930
+ gearBtn.remove();
778
931
  }
779
932
  }
780
933
 
@@ -782,6 +935,29 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
782
935
  * MALFORMED DATA DETECTION
783
936
  * ═══════════════════════════════════════════════════ */
784
937
 
938
+ private _appendSettingsButton(label: string, variant: string): void {
939
+ const statusEl = document.getElementById(`${this._id}-status`);
940
+ if (!statusEl) return;
941
+
942
+ // Remove existing settings button if any
943
+ const existing = statusEl.querySelector('.jux-dataframe-settings-btn');
944
+ if (existing) existing.remove();
945
+
946
+ const btn = document.createElement('button');
947
+ btn.className = `jux-dataframe-settings-btn jux-dataframe-settings-btn-${variant}`;
948
+ btn.type = 'button';
949
+ btn.textContent = `⚙️ ${label}`;
950
+ btn.style.marginLeft = '8px';
951
+ btn.style.cursor = 'pointer';
952
+ btn.style.fontSize = '0.8rem';
953
+ btn.style.padding = '2px 8px';
954
+ btn.style.borderRadius = 'var(--radius, 4px)';
955
+ btn.style.border = '1px solid hsl(var(--border))';
956
+ btn.style.background = variant === 'warning' ? 'hsl(38 92% 50% / 0.15)' : 'transparent';
957
+ btn.addEventListener('click', () => this._showReshapeModal());
958
+ statusEl.appendChild(btn);
959
+ }
960
+
785
961
  private _detectMalformedData(df: DataFrame): boolean {
786
962
  const columns = df.columns;
787
963
  const rows = df.toRows();
@@ -924,8 +1100,8 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
924
1100
  const nonEmpty = values.filter(v => v !== null && v !== undefined && String(v).trim() !== '');
925
1101
  if (nonEmpty.length < values.length * 0.5) continue;
926
1102
  const nonNumeric = nonEmpty.filter(v => {
927
- const str = String(v).trim();
928
- return isNaN(Number(str)) && str !== '';
1103
+ const trimmed = v.trim();
1104
+ return isNaN(Number(trimmed)) && trimmed !== '';
929
1105
  }).length;
930
1106
  if (nonNumeric >= nonEmpty.length * 0.7) {
931
1107
  selectedSheetRow = sheetRow;
@@ -1229,8 +1405,10 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
1229
1405
  if (className) wrapper.className += ` ${className}`;
1230
1406
  if (style) wrapper.setAttribute('style', style);
1231
1407
 
1408
+ // ═══════════════════════════════════════════════════
1409
+ // UPLOAD AREA (shown initially, hidden after data loads)
1410
+ // ═══════════════════════════════════════════════════
1232
1411
  if (this._inlineUpload) {
1233
- // ✅ NEW: Enhanced upload area with better styling
1234
1412
  const uploadArea = document.createElement('div');
1235
1413
  uploadArea.className = 'jux-dataframe-upload-area';
1236
1414
  uploadArea.id = `${this._id}-upload-area`;
@@ -1247,11 +1425,9 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
1247
1425
  const upload = new FileUpload(`${this._id}-upload`, uploadOpts);
1248
1426
  this._uploadRef = upload;
1249
1427
 
1250
- // ✅ Handle file change AND file clear
1251
1428
  this._pendingSource = async () => {
1252
1429
  upload.bind('change', async (files: File[]) => {
1253
1430
  if (!files || files.length === 0) {
1254
- // File was cleared - reset the table
1255
1431
  await this.clear();
1256
1432
  return;
1257
1433
  }
@@ -1264,12 +1440,12 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
1264
1440
  uploadContainer.id = `${this._id}-upload-container`;
1265
1441
  uploadArea.appendChild(uploadContainer);
1266
1442
 
1267
- // Status bar INLINE with upload (inside upload area)
1443
+ // Status bar (for loading/error states only)
1268
1444
  if (this._showStatus) {
1269
1445
  const statusBar = document.createElement('div');
1270
- statusBar.className = 'jux-dataframe-status jux-dataframe-status-empty';
1446
+ statusBar.className = 'jux-dataframe-status';
1271
1447
  statusBar.id = `${this._id}-status`;
1272
- statusBar.style.display = 'none'; // Hidden until needed
1448
+ statusBar.style.display = 'none';
1273
1449
  uploadArea.appendChild(statusBar);
1274
1450
  }
1275
1451
 
@@ -1285,25 +1461,40 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
1285
1461
  upload.render(uploadContainer);
1286
1462
  } else {
1287
1463
  container.appendChild(wrapper);
1288
-
1289
- // ✅ Status bar for non-upload mode
1290
- if (this._showStatus) {
1291
- const statusBar = document.createElement('div');
1292
- statusBar.className = 'jux-dataframe-status jux-dataframe-status-empty';
1293
- statusBar.id = `${this._id}-status`;
1294
- statusBar.textContent = 'No data loaded.';
1295
- wrapper.appendChild(statusBar);
1296
- }
1297
1464
  }
1298
1465
 
1299
- // ✅ Collapsible details wrapper - HIDDEN until data loads
1466
+ // ═══════════════════════════════════════════════════
1467
+ // DATA CONTAINER (hidden initially, shown after data loads)
1468
+ // ═══════════════════════════════════════════════════
1469
+ const dataContainer = document.createElement('div');
1470
+ dataContainer.className = 'jux-dataframe-data';
1471
+ dataContainer.style.display = 'none'; // Hidden until data loads
1472
+
1473
+ // ✅ Toolbar with settings gear
1474
+ const toolbar = document.createElement('div');
1475
+ toolbar.className = 'jux-dataframe-toolbar';
1476
+
1477
+ const settingsGear = document.createElement('button');
1478
+ settingsGear.className = 'jux-dataframe-gear';
1479
+ settingsGear.id = `${this._id}-settings-gear`;
1480
+ settingsGear.type = 'button';
1481
+ settingsGear.innerHTML = '⚙️';
1482
+ settingsGear.title = 'Data Settings';
1483
+ settingsGear.addEventListener('click', () => this._showSettingsModal());
1484
+ toolbar.appendChild(settingsGear);
1485
+
1486
+ dataContainer.appendChild(toolbar);
1487
+
1488
+ // ═══════════════════════════════════════════════════
1489
+ // TABLE CONTAINER (inside data container or collapsible)
1490
+ // ═══════════════════════════════════════════════════
1300
1491
  let tableContainer: HTMLElement;
1301
1492
 
1302
1493
  if (this._collapsible) {
1303
1494
  const details = document.createElement('details');
1304
1495
  details.className = 'jux-dataframe-details';
1305
1496
  details.open = !this._collapsed;
1306
- details.style.display = 'none'; // Hidden until data loads
1497
+ details.style.display = 'none'; // Hidden until data loads
1307
1498
  this._detailsElement = details;
1308
1499
 
1309
1500
  const summary = document.createElement('summary');
@@ -1316,7 +1507,6 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
1316
1507
 
1317
1508
  const textSpan = document.createElement('span');
1318
1509
  textSpan.className = 'jux-dataframe-summary-text';
1319
- // Don't set text - will be set when data loads
1320
1510
  summary.appendChild(textSpan);
1321
1511
 
1322
1512
  details.appendChild(summary);
@@ -1325,16 +1515,21 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
1325
1515
  content.className = 'jux-dataframe-details-content';
1326
1516
  details.appendChild(content);
1327
1517
 
1328
- wrapper.appendChild(details);
1518
+ dataContainer.appendChild(details);
1329
1519
  tableContainer = content;
1330
1520
 
1331
1521
  details.addEventListener('toggle', () => {
1332
1522
  this._collapsed = !details.open;
1333
1523
  });
1334
1524
  } else {
1335
- tableContainer = wrapper;
1525
+ tableContainer = dataContainer;
1336
1526
  }
1337
1527
 
1528
+ wrapper.appendChild(dataContainer);
1529
+
1530
+ // ═══════════════════════════════════════════════════
1531
+ // TABLE
1532
+ // ═══════════════════════════════════════════════════
1338
1533
  const tbl = new Table(`${this._id}-table`, {
1339
1534
  striped: this._tableOptions.striped,
1340
1535
  hoverable: this._tableOptions.hoverable,
@@ -916,6 +916,36 @@ code {
916
916
  flex: 1;
917
917
  }
918
918
 
919
+ /* ✅ Settings button in summary */
920
+ .jux-dataframe-summary-settings {
921
+ padding: 0.25rem 0.5rem;
922
+ font-size: 0.75rem;
923
+ font-weight: 500;
924
+ border: 1px solid hsl(var(--border));
925
+ border-radius: calc(var(--radius) - 2px);
926
+ background: hsl(var(--background));
927
+ color: hsl(var(--muted-foreground));
928
+ cursor: pointer;
929
+ transition: all 0.15s;
930
+ margin-left: auto;
931
+ }
932
+
933
+ .jux-dataframe-summary-settings:hover {
934
+ background: hsl(var(--accent));
935
+ color: hsl(var(--foreground));
936
+ border-color: hsl(var(--muted-foreground) / 0.3);
937
+ }
938
+
939
+ .jux-dataframe-summary-settings-warning {
940
+ background: hsl(var(--warning) / 0.1);
941
+ border-color: hsl(var(--warning) / 0.3);
942
+ color: hsl(var(--warning-foreground));
943
+ }
944
+
945
+ .jux-dataframe-summary-settings-warning:hover {
946
+ background: hsl(var(--warning) / 0.2);
947
+ }
948
+
919
949
  .jux-dataframe-details-content {
920
950
  padding: 0;
921
951
  }
@@ -924,4 +954,96 @@ code {
924
954
  .jux-dataframe-details-content .jux-table-wrapper {
925
955
  border: none;
926
956
  border-radius: 0;
957
+ }
958
+
959
+ /* ═══════════════════════════════════════════════════════════════════
960
+ * DATAFRAME DATA VIEW (Post-upload clean UI)
961
+ * ═══════════════════════════════════════════════════════════════════ */
962
+
963
+ .jux-dataframe-data {
964
+ display: flex;
965
+ flex-direction: column;
966
+ gap: 0.5rem;
967
+ }
968
+
969
+ .jux-dataframe-toolbar {
970
+ display: flex;
971
+ justify-content: flex-end;
972
+ align-items: center;
973
+ padding: 0.25rem 0;
974
+ }
975
+
976
+ .jux-dataframe-gear {
977
+ display: inline-flex;
978
+ align-items: center;
979
+ justify-content: center;
980
+ width: 2rem;
981
+ height: 2rem;
982
+ padding: 0;
983
+ border: none;
984
+ background: transparent;
985
+ border-radius: var(--radius);
986
+ cursor: pointer;
987
+ font-size: 1rem;
988
+ color: hsl(var(--muted-foreground));
989
+ transition: all 0.15s;
990
+ }
991
+
992
+ .jux-dataframe-gear:hover {
993
+ background: hsl(var(--muted) / 0.5);
994
+ color: hsl(var(--foreground));
995
+ }
996
+
997
+ .jux-dataframe-gear-warning {
998
+ color: hsl(var(--warning));
999
+ }
1000
+
1001
+ .jux-dataframe-gear-warning:hover {
1002
+ background: hsl(var(--warning) / 0.1);
1003
+ }
1004
+
1005
+ /* Settings modal content */
1006
+ .jux-dataframe-settings-content {
1007
+ display: flex;
1008
+ flex-direction: column;
1009
+ gap: 1rem;
1010
+ }
1011
+
1012
+ .jux-dataframe-settings-section {
1013
+ display: flex;
1014
+ flex-direction: column;
1015
+ gap: 0.25rem;
1016
+ }
1017
+
1018
+ .jux-dataframe-settings-label {
1019
+ font-size: 0.75rem;
1020
+ font-weight: 600;
1021
+ text-transform: uppercase;
1022
+ letter-spacing: 0.05em;
1023
+ color: hsl(var(--muted-foreground));
1024
+ }
1025
+
1026
+ .jux-dataframe-settings-value {
1027
+ font-size: 0.875rem;
1028
+ color: hsl(var(--foreground));
1029
+ }
1030
+
1031
+ /* Summary gear in collapsible mode */
1032
+ .jux-dataframe-summary-gear {
1033
+ padding: 0.25rem 0.5rem;
1034
+ font-size: 0.875rem;
1035
+ border: none;
1036
+ background: transparent;
1037
+ cursor: pointer;
1038
+ color: hsl(var(--muted-foreground));
1039
+ transition: all 0.15s;
1040
+ margin-left: auto;
1041
+ }
1042
+
1043
+ .jux-dataframe-summary-gear:hover {
1044
+ color: hsl(var(--foreground));
1045
+ }
1046
+
1047
+ .jux-dataframe-summary-gear.jux-dataframe-gear-warning {
1048
+ color: hsl(var(--warning));
927
1049
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "juxscript",
3
- "version": "1.1.224",
3
+ "version": "1.1.226",
4
4
  "type": "module",
5
5
  "description": "A JavaScript UX authorship platform",
6
6
  "main": "index.js",