juxscript 1.1.197 → 1.1.199

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.
@@ -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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"}
@@ -486,7 +486,21 @@ export class DataFrameComponent extends BaseComponent {
486
486
  if (!this._rawFileData?.file)
487
487
  return;
488
488
  this._cleanupReshapeModal();
489
- const suggestedRow = this._df ? this._detectLikelyHeaderRow(this._df) : 0;
489
+ // Always detect from a fresh raw parse, not from current _df
490
+ let suggestedRow = 0;
491
+ try {
492
+ const rawSheets = await this._driver.streamFileMultiSheet(this._rawFileData.file, {
493
+ headerRow: 0,
494
+ maxSheetSize: 20
495
+ });
496
+ const rawSheet = Object.values(rawSheets)[0];
497
+ if (rawSheet) {
498
+ suggestedRow = this._detectLikelyHeaderRow(rawSheet);
499
+ }
500
+ }
501
+ catch {
502
+ suggestedRow = 0;
503
+ }
490
504
  this._reshapeModal = new Modal(`${this._id}-reshape-modal`, {
491
505
  title: 'Excel Import Settings',
492
506
  size: 'large',
@@ -514,7 +528,7 @@ export class DataFrameComponent extends BaseComponent {
514
528
  <div style="font-weight: 600; margin-bottom: 0.5rem; color: hsl(var(--foreground));">
515
529
  Preview
516
530
  </div>
517
- <div id="${this._id}-preview" style="font-family: monospace; font-size: 12px; background: hsl(var(--muted) / 0.3); border: 1px solid hsl(var(--border)); border-radius: var(--radius); padding: 0; overflow: hidden; max-height: 400px; overflow-y: auto;"></div>
531
+ <div id="${this._id}-preview" style="font-family: ui-monospace, monospace; font-size: 12px; background: hsl(var(--muted) / 0.3); border: 1px solid hsl(var(--border)); border-radius: var(--radius); padding: 0; overflow: hidden; max-height: 400px; overflow-y: auto;"></div>
518
532
  </div>
519
533
  `;
520
534
  this._reshapeModal
@@ -576,10 +590,10 @@ export class DataFrameComponent extends BaseComponent {
576
590
  const headerRow = parseInt(headerRowInput?.value) || 0;
577
591
  updateHint(headerRow);
578
592
  try {
579
- // Get raw data to show all rows
593
+ // ALWAYS parse with headerRow=0 to get raw file structure
580
594
  const rawSheets = await this._driver.streamFileMultiSheet(this._rawFileData.file, {
581
595
  headerRow: 0,
582
- maxSheetSize: headerRow + 12
596
+ maxSheetSize: Math.max(headerRow + 12, 15)
583
597
  });
584
598
  const rawSheet = Object.values(rawSheets)[0];
585
599
  if (!rawSheet) {
@@ -587,63 +601,65 @@ export class DataFrameComponent extends BaseComponent {
587
601
  previewDiv.textContent = 'No data found';
588
602
  return;
589
603
  }
604
+ // rawSheet.columns = row 0 values (when parsed with headerRow=0)
605
+ // rawSheet.toRows() = rows 1+ (data rows when parsed with headerRow=0)
590
606
  const rawCols = rawSheet.columns;
591
607
  const rawRows = rawSheet.toRows();
592
- // Build a simple HTML table for clarity
593
- let html = '<table style="width: 100%; border-collapse: collapse; font-size: 11px;">';
594
- // Render each row
595
- const totalRows = Math.min(headerRow + 8, rawRows.length + 1);
596
- for (let i = 0; i < totalRows; i++) {
597
- const isHeader = (i === headerRow);
598
- const isSkipped = (i < headerRow);
608
+ // Build HTML table showing raw file structure
609
+ let html = '<table style="width: 100%; border-collapse: collapse; font-size: 12px;">';
610
+ // We need to show rows 0 through headerRow+7 (or so)
611
+ // Row 0 = rawCols, Row 1+ = rawRows[i-1]
612
+ const totalRowsToShow = Math.min(headerRow + 8, rawRows.length + 1);
613
+ for (let fileRow = 0; fileRow < totalRowsToShow; fileRow++) {
614
+ const isHeader = (fileRow === headerRow);
615
+ const isSkipped = (fileRow < headerRow);
599
616
  let rowStyle = 'border-bottom: 1px solid hsl(var(--border));';
600
- let cellStyle = 'padding: 6px 8px; text-align: left;';
601
617
  if (isHeader) {
602
- rowStyle += 'background: hsl(var(--primary) / 0.15); font-weight: bold;';
618
+ rowStyle += 'background: hsl(142 71% 45% / 0.15); font-weight: 600;';
603
619
  }
604
620
  else if (isSkipped) {
605
- rowStyle += 'background: hsl(var(--muted) / 0.3); color: hsl(var(--muted-foreground)); font-style: italic;';
621
+ rowStyle += 'background: hsl(var(--muted) / 0.4); color: hsl(var(--muted-foreground)); font-style: italic; opacity: 0.7;';
606
622
  }
607
623
  html += `<tr style="${rowStyle}">`;
608
624
  // Row index cell
609
- html += `<td style="${cellStyle} width: 50px; color: hsl(var(--muted-foreground)); font-weight: 500;">`;
625
+ html += `<td style="padding: 8px 12px; width: 60px; font-weight: 600; color: hsl(var(--muted-foreground)); border-right: 1px solid hsl(var(--border)); text-align: center;">`;
610
626
  if (isHeader) {
611
- html += `<strong>→ ${i}</strong>`;
627
+ html += `<span style="color: hsl(142 71% 45%);">▶ ${fileRow}</span>`;
612
628
  }
613
629
  else {
614
- html += `${i}`;
630
+ html += `${fileRow}`;
615
631
  }
616
632
  html += '</td>';
617
- // Data cells
633
+ // Get values for this file row
618
634
  let values;
619
- if (i === 0) {
635
+ if (fileRow === 0) {
620
636
  values = rawCols;
621
637
  }
622
- else if (i - 1 < rawRows.length) {
623
- values = Object.values(rawRows[i - 1]);
624
- }
625
638
  else {
626
- values = [];
639
+ values = rawRows[fileRow - 1] ? Object.values(rawRows[fileRow - 1]) : [];
627
640
  }
628
641
  // Show first 6 columns
629
642
  const displayCols = values.slice(0, 6);
630
643
  displayCols.forEach(val => {
631
- const displayVal = val != null ? String(val).substring(0, 25) : '';
644
+ const displayVal = val != null ? String(val).substring(0, 20) : '';
645
+ const cellStyle = isHeader
646
+ ? 'padding: 8px 12px; font-weight: 600; color: hsl(var(--foreground));'
647
+ : 'padding: 8px 12px;';
632
648
  html += `<td style="${cellStyle}">${this._escapeHtml(displayVal)}</td>`;
633
649
  });
634
650
  if (values.length > 6) {
635
- html += `<td style="${cellStyle} color: hsl(var(--muted-foreground));">...</td>`;
651
+ html += `<td style="padding: 8px 12px; color: hsl(var(--muted-foreground));">…</td>`;
636
652
  }
637
- // Status cell
638
- html += `<td style="${cellStyle} text-align: right; font-size: 10px;">`;
653
+ // Status badge cell
654
+ html += `<td style="padding: 8px 12px; text-align: right; white-space: nowrap;">`;
639
655
  if (isHeader) {
640
- html += '<span style="background: hsl(var(--primary)); color: white; padding: 2px 6px; border-radius: 4px;">HEADER</span>';
656
+ html += '<span style="background: hsl(142 71% 45%); color: white; padding: 3px 8px; border-radius: 4px; font-size: 10px; font-weight: 600;">HEADER</span>';
641
657
  }
642
658
  else if (isSkipped) {
643
- html += '<span style="color: hsl(var(--muted-foreground));">skipped</span>';
659
+ html += '<span style="color: hsl(var(--muted-foreground)); font-size: 10px;">skipped</span>';
644
660
  }
645
661
  else {
646
- html += '<span style="color: hsl(var(--success));">data</span>';
662
+ html += '<span style="color: hsl(var(--muted-foreground)); font-size: 10px;">data</span>';
647
663
  }
648
664
  html += '</td>';
649
665
  html += '</tr>';
@@ -604,7 +604,20 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
604
604
 
605
605
  this._cleanupReshapeModal();
606
606
 
607
- const suggestedRow = this._df ? this._detectLikelyHeaderRow(this._df) : 0;
607
+ // Always detect from a fresh raw parse, not from current _df
608
+ let suggestedRow = 0;
609
+ try {
610
+ const rawSheets = await this._driver.streamFileMultiSheet(this._rawFileData.file, {
611
+ headerRow: 0,
612
+ maxSheetSize: 20
613
+ });
614
+ const rawSheet = Object.values(rawSheets)[0];
615
+ if (rawSheet) {
616
+ suggestedRow = this._detectLikelyHeaderRow(rawSheet);
617
+ }
618
+ } catch {
619
+ suggestedRow = 0;
620
+ }
608
621
 
609
622
  this._reshapeModal = new Modal(`${this._id}-reshape-modal`, {
610
623
  title: 'Excel Import Settings',
@@ -634,7 +647,7 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
634
647
  <div style="font-weight: 600; margin-bottom: 0.5rem; color: hsl(var(--foreground));">
635
648
  Preview
636
649
  </div>
637
- <div id="${this._id}-preview" style="font-family: monospace; font-size: 12px; background: hsl(var(--muted) / 0.3); border: 1px solid hsl(var(--border)); border-radius: var(--radius); padding: 0; overflow: hidden; max-height: 400px; overflow-y: auto;"></div>
650
+ <div id="${this._id}-preview" style="font-family: ui-monospace, monospace; font-size: 12px; background: hsl(var(--muted) / 0.3); border: 1px solid hsl(var(--border)); border-radius: var(--radius); padding: 0; overflow: hidden; max-height: 400px; overflow-y: auto;"></div>
638
651
  </div>
639
652
  `;
640
653
 
@@ -704,10 +717,10 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
704
717
  updateHint(headerRow);
705
718
 
706
719
  try {
707
- // Get raw data to show all rows
720
+ // ALWAYS parse with headerRow=0 to get raw file structure
708
721
  const rawSheets = await this._driver.streamFileMultiSheet(this._rawFileData!.file, {
709
722
  headerRow: 0,
710
- maxSheetSize: headerRow + 12
723
+ maxSheetSize: Math.max(headerRow + 12, 15)
711
724
  });
712
725
  const rawSheet = Object.values(rawSheets)[0];
713
726
 
@@ -716,68 +729,71 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
716
729
  return;
717
730
  }
718
731
 
732
+ // rawSheet.columns = row 0 values (when parsed with headerRow=0)
733
+ // rawSheet.toRows() = rows 1+ (data rows when parsed with headerRow=0)
719
734
  const rawCols = rawSheet.columns;
720
735
  const rawRows = rawSheet.toRows();
721
736
 
722
- // Build a simple HTML table for clarity
723
- let html = '<table style="width: 100%; border-collapse: collapse; font-size: 11px;">';
737
+ // Build HTML table showing raw file structure
738
+ let html = '<table style="width: 100%; border-collapse: collapse; font-size: 12px;">';
724
739
 
725
- // Render each row
726
- const totalRows = Math.min(headerRow + 8, rawRows.length + 1);
740
+ // We need to show rows 0 through headerRow+7 (or so)
741
+ // Row 0 = rawCols, Row 1+ = rawRows[i-1]
742
+ const totalRowsToShow = Math.min(headerRow + 8, rawRows.length + 1);
727
743
 
728
- for (let i = 0; i < totalRows; i++) {
729
- const isHeader = (i === headerRow);
730
- const isSkipped = (i < headerRow);
744
+ for (let fileRow = 0; fileRow < totalRowsToShow; fileRow++) {
745
+ const isHeader = (fileRow === headerRow);
746
+ const isSkipped = (fileRow < headerRow);
731
747
 
732
748
  let rowStyle = 'border-bottom: 1px solid hsl(var(--border));';
733
- let cellStyle = 'padding: 6px 8px; text-align: left;';
734
749
 
735
750
  if (isHeader) {
736
- rowStyle += 'background: hsl(var(--primary) / 0.15); font-weight: bold;';
751
+ rowStyle += 'background: hsl(142 71% 45% / 0.15); font-weight: 600;';
737
752
  } else if (isSkipped) {
738
- rowStyle += 'background: hsl(var(--muted) / 0.3); color: hsl(var(--muted-foreground)); font-style: italic;';
753
+ rowStyle += 'background: hsl(var(--muted) / 0.4); color: hsl(var(--muted-foreground)); font-style: italic; opacity: 0.7;';
739
754
  }
740
755
 
741
756
  html += `<tr style="${rowStyle}">`;
742
757
 
743
758
  // Row index cell
744
- html += `<td style="${cellStyle} width: 50px; color: hsl(var(--muted-foreground)); font-weight: 500;">`;
759
+ html += `<td style="padding: 8px 12px; width: 60px; font-weight: 600; color: hsl(var(--muted-foreground)); border-right: 1px solid hsl(var(--border)); text-align: center;">`;
745
760
  if (isHeader) {
746
- html += `<strong>→ ${i}</strong>`;
761
+ html += `<span style="color: hsl(142 71% 45%);">▶ ${fileRow}</span>`;
747
762
  } else {
748
- html += `${i}`;
763
+ html += `${fileRow}`;
749
764
  }
750
765
  html += '</td>';
751
766
 
752
- // Data cells
767
+ // Get values for this file row
753
768
  let values: any[];
754
- if (i === 0) {
769
+ if (fileRow === 0) {
755
770
  values = rawCols;
756
- } else if (i - 1 < rawRows.length) {
757
- values = Object.values(rawRows[i - 1]);
758
771
  } else {
759
- values = [];
772
+ values = rawRows[fileRow - 1] ? Object.values(rawRows[fileRow - 1]) : [];
760
773
  }
761
774
 
762
775
  // Show first 6 columns
763
776
  const displayCols = values.slice(0, 6);
764
777
  displayCols.forEach(val => {
765
- const displayVal = val != null ? String(val).substring(0, 25) : '';
778
+ const displayVal = val != null ? String(val).substring(0, 20) : '';
779
+ const cellStyle = isHeader
780
+ ? 'padding: 8px 12px; font-weight: 600; color: hsl(var(--foreground));'
781
+ : 'padding: 8px 12px;';
766
782
  html += `<td style="${cellStyle}">${this._escapeHtml(displayVal)}</td>`;
767
783
  });
768
784
 
769
785
  if (values.length > 6) {
770
- html += `<td style="${cellStyle} color: hsl(var(--muted-foreground));">...</td>`;
786
+ html += `<td style="padding: 8px 12px; color: hsl(var(--muted-foreground));">…</td>`;
771
787
  }
772
788
 
773
- // Status cell
774
- html += `<td style="${cellStyle} text-align: right; font-size: 10px;">`;
789
+ // Status badge cell
790
+ html += `<td style="padding: 8px 12px; text-align: right; white-space: nowrap;">`;
775
791
  if (isHeader) {
776
- html += '<span style="background: hsl(var(--primary)); color: white; padding: 2px 6px; border-radius: 4px;">HEADER</span>';
792
+ html += '<span style="background: hsl(142 71% 45%); color: white; padding: 3px 8px; border-radius: 4px; font-size: 10px; font-weight: 600;">HEADER</span>';
777
793
  } else if (isSkipped) {
778
- html += '<span style="color: hsl(var(--muted-foreground));">skipped</span>';
794
+ html += '<span style="color: hsl(var(--muted-foreground)); font-size: 10px;">skipped</span>';
779
795
  } else {
780
- html += '<span style="color: hsl(var(--success));">data</span>';
796
+ html += '<span style="color: hsl(var(--muted-foreground)); font-size: 10px;">data</span>';
781
797
  }
782
798
  html += '</td>';
783
799
 
@@ -1 +1 @@
1
- {"version":3,"file":"TabularDriver.d.ts","sourceRoot":"","sources":["TabularDriver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TabularDriver.d.ts","sourceRoot":"","sources":["TabularDriver.ts"],"names":[],"mappings":"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"}
@@ -490,7 +490,7 @@ export class TabularDriver {
490
490
  * ✅ UPDATED: Stream Excel file with optional headerRow override
491
491
  */
492
492
  async streamFileMultiSheet(file, options = {}) {
493
- const { maxSheetSize = 100000, sheetChunkSize = 10000, onProgress, headerRow } = options;
493
+ const { maxSheetSize = 100000, sheetChunkSize = 10000, onProgress, headerRow = 0 } = options;
494
494
  let XLSX;
495
495
  try {
496
496
  XLSX = await import('xlsx');
@@ -524,17 +524,54 @@ export class TabularDriver {
524
524
  processedSheets++;
525
525
  continue;
526
526
  }
527
- // When headerRow is specified and > 0, we need to:
528
- // 1. Tell sheet_to_json to start reading from that row
529
- // 2. SheetJS treats the first row of the range as headers
530
- const jsonData = XLSX.utils.sheet_to_json(worksheet, {
531
- range: (headerRow !== undefined && headerRow > 0) ? headerRow : undefined,
532
- defval: null,
533
- raw: false,
534
- blankrows: false
535
- });
536
- if (jsonData.length > 0) {
537
- sheets[sheetName] = new DataFrame(jsonData);
527
+ // FIX: Use sheet_to_json with header option to get raw arrays first
528
+ // Then manually construct the DataFrame with the correct header row
529
+ if (headerRow > 0) {
530
+ // Get all data as raw arrays (no header interpretation)
531
+ const rawData = XLSX.utils.sheet_to_json(worksheet, {
532
+ header: 1, // Return array of arrays
533
+ defval: null,
534
+ raw: false,
535
+ blankrows: false
536
+ });
537
+ if (rawData.length <= headerRow) {
538
+ processedSheets++;
539
+ continue;
540
+ }
541
+ // Extract headers from the specified row
542
+ const headers = rawData[headerRow].map((h, i) => {
543
+ if (h === null || h === undefined || String(h).trim() === '') {
544
+ return `__EMPTY${i > 0 ? '_' + i : ''}`;
545
+ }
546
+ return String(h);
547
+ });
548
+ // Build rows from data after header row
549
+ const rows = [];
550
+ for (let i = headerRow + 1; i < rawData.length; i++) {
551
+ const rowData = rawData[i];
552
+ if (!rowData || rowData.every((cell) => cell === null || cell === undefined)) {
553
+ continue; // Skip empty rows
554
+ }
555
+ const row = {};
556
+ headers.forEach((header, j) => {
557
+ row[header] = rowData[j] !== undefined ? rowData[j] : null;
558
+ });
559
+ rows.push(row);
560
+ }
561
+ if (rows.length > 0) {
562
+ sheets[sheetName] = new DataFrame(rows);
563
+ }
564
+ }
565
+ else {
566
+ // Default behavior: first row is header
567
+ const jsonData = XLSX.utils.sheet_to_json(worksheet, {
568
+ defval: null,
569
+ raw: false,
570
+ blankrows: false
571
+ });
572
+ if (jsonData.length > 0) {
573
+ sheets[sheetName] = new DataFrame(jsonData);
574
+ }
538
575
  }
539
576
  processedSheets++;
540
577
  if (onProgress) {
@@ -610,7 +610,7 @@ export class TabularDriver {
610
610
  * ✅ UPDATED: Stream Excel file with optional headerRow override
611
611
  */
612
612
  async streamFileMultiSheet(file: File, options: ParseOptions = {}): Promise<Record<string, DataFrame>> {
613
- const { maxSheetSize = 100000, sheetChunkSize = 10000, onProgress, headerRow } = options;
613
+ const { maxSheetSize = 100000, sheetChunkSize = 10000, onProgress, headerRow = 0 } = options;
614
614
 
615
615
  let XLSX: any;
616
616
  try {
@@ -652,18 +652,59 @@ export class TabularDriver {
652
652
  continue;
653
653
  }
654
654
 
655
- // When headerRow is specified and > 0, we need to:
656
- // 1. Tell sheet_to_json to start reading from that row
657
- // 2. SheetJS treats the first row of the range as headers
658
- const jsonData: Record<string, any>[] = XLSX.utils.sheet_to_json(worksheet, {
659
- range: (headerRow !== undefined && headerRow > 0) ? headerRow : undefined,
660
- defval: null,
661
- raw: false,
662
- blankrows: false
663
- });
655
+ // FIX: Use sheet_to_json with header option to get raw arrays first
656
+ // Then manually construct the DataFrame with the correct header row
657
+ if (headerRow > 0) {
658
+ // Get all data as raw arrays (no header interpretation)
659
+ const rawData: any[][] = XLSX.utils.sheet_to_json(worksheet, {
660
+ header: 1, // Return array of arrays
661
+ defval: null,
662
+ raw: false,
663
+ blankrows: false
664
+ });
665
+
666
+ if (rawData.length <= headerRow) {
667
+ processedSheets++;
668
+ continue;
669
+ }
664
670
 
665
- if (jsonData.length > 0) {
666
- sheets[sheetName] = new DataFrame(jsonData);
671
+ // Extract headers from the specified row
672
+ const headers = rawData[headerRow].map((h: any, i: number) => {
673
+ if (h === null || h === undefined || String(h).trim() === '') {
674
+ return `__EMPTY${i > 0 ? '_' + i : ''}`;
675
+ }
676
+ return String(h);
677
+ });
678
+
679
+ // Build rows from data after header row
680
+ const rows: Record<string, any>[] = [];
681
+ for (let i = headerRow + 1; i < rawData.length; i++) {
682
+ const rowData = rawData[i];
683
+ if (!rowData || rowData.every((cell: any) => cell === null || cell === undefined)) {
684
+ continue; // Skip empty rows
685
+ }
686
+
687
+ const row: Record<string, any> = {};
688
+ headers.forEach((header: string, j: number) => {
689
+ row[header] = rowData[j] !== undefined ? rowData[j] : null;
690
+ });
691
+ rows.push(row);
692
+ }
693
+
694
+ if (rows.length > 0) {
695
+ sheets[sheetName] = new DataFrame(rows);
696
+ }
697
+ } else {
698
+ // Default behavior: first row is header
699
+ const jsonData: Record<string, any>[] = XLSX.utils.sheet_to_json(worksheet, {
700
+ defval: null,
701
+ raw: false,
702
+ blankrows: false
703
+ });
704
+
705
+ if (jsonData.length > 0) {
706
+ sheets[sheetName] = new DataFrame(jsonData);
707
+ }
667
708
  }
668
709
 
669
710
  processedSheets++;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "juxscript",
3
- "version": "1.1.197",
3
+ "version": "1.1.199",
4
4
  "type": "module",
5
5
  "description": "A JavaScript UX authorship platform",
6
6
  "main": "index.js",