juxscript 1.1.191 → 1.1.192

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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"}
@@ -430,13 +430,13 @@ export class DataFrameComponent extends BaseComponent {
430
430
  return isNaN(Number(str)) && str !== '';
431
431
  }).length;
432
432
  if (nonNumericCount >= nonEmpty.length * 0.7 && i > 0) {
433
- // Return 1-based row number for the UI
434
- // i is index in toRows() but row 0 of the file was consumed as header,
435
- // so the actual file row is i + 1, and 1-based display is i + 2
436
- return i + 2;
433
+ // i is the index in toRows(). Row 0 of the file was already consumed
434
+ // as the header during the initial parse, so the actual 0-based file
435
+ // row index is i + 1.
436
+ return i + 1;
437
437
  }
438
438
  }
439
- return 1; // Default to row 1 (1-based)
439
+ return 0;
440
440
  }
441
441
  /* ═══════════════════════════════════════════════════
442
442
  * RESHAPE MODAL
@@ -464,7 +464,7 @@ export class DataFrameComponent extends BaseComponent {
464
464
  if (!this._rawFileData?.file)
465
465
  return;
466
466
  this._cleanupReshapeModal();
467
- const suggestedRow = this._df ? this._detectLikelyHeaderRow(this._df) : 1;
467
+ const suggestedRow = this._df ? this._detectLikelyHeaderRow(this._df) : 0;
468
468
  this._reshapeModal = new Modal(`${this._id}-reshape-modal`, {
469
469
  title: 'Excel Import Settings',
470
470
  size: 'large',
@@ -481,14 +481,14 @@ export class DataFrameComponent extends BaseComponent {
481
481
  id="${this._id}-header-row"
482
482
  class="jux-input-element"
483
483
  value="${suggestedRow}"
484
- min="1"
484
+ min="0"
485
485
  max="50"
486
486
  style="width: 100%;"
487
487
  />
488
488
  <div class="jux-reshape-hint">
489
489
  <strong>Detected issue:</strong> The current header row appears to contain metadata or empty values.
490
490
  Row ${suggestedRow} looks like it contains the actual column headers.
491
- Adjust the value above and check the preview below.
491
+ Adjust the value above and check the preview below. The Row column shows the index for each row.
492
492
  </div>
493
493
  </div>
494
494
  <div class="jux-reshape-preview-container">
@@ -511,8 +511,7 @@ export class DataFrameComponent extends BaseComponent {
511
511
  variant: 'primary',
512
512
  click: async () => {
513
513
  const input = document.getElementById(`${this._id}-header-row`);
514
- const headerRowOneBased = parseInt(input.value) || 1;
515
- const headerRow = headerRowOneBased - 1; // Convert to 0-based for driver
514
+ const headerRow = parseInt(input.value) || 0;
516
515
  this.state.loading = true;
517
516
  this._updateStatus('Re-parsing with new settings...', 'loading');
518
517
  try {
@@ -544,8 +543,7 @@ export class DataFrameComponent extends BaseComponent {
544
543
  const headerRowInput = document.getElementById(`${this._id}-header-row`);
545
544
  const previewDiv = document.getElementById(`${this._id}-preview`);
546
545
  const updatePreview = async () => {
547
- const headerRowOneBased = parseInt(headerRowInput?.value) || 1;
548
- const headerRow = headerRowOneBased - 1; // Convert to 0-based for driver
546
+ const headerRow = parseInt(headerRowInput?.value) || 0;
549
547
  try {
550
548
  const sheets = await this._driver.streamFileMultiSheet(this._rawFileData.file, {
551
549
  headerRow,
@@ -557,12 +555,16 @@ export class DataFrameComponent extends BaseComponent {
557
555
  previewDiv.textContent = 'No data found';
558
556
  return;
559
557
  }
560
- const preview = firstSheet.toRows().slice(0, 10).map((row, i) => {
558
+ const dataRows = firstSheet.toRows().slice(0, 10);
559
+ const colHeader = 'Row'.padEnd(6) + firstSheet.columns.map(c => String(c).padEnd(20)).join(' | ');
560
+ const separator = '─'.repeat(Math.min(colHeader.length, 120));
561
+ const preview = dataRows.map((row, i) => {
562
+ const rowIdx = String(headerRow + 1 + i).padEnd(6);
561
563
  const cols = Object.values(row).map(v => String(v ?? '').padEnd(20)).join(' | ');
562
- return `${i === 0 ? '>> ' : ' '}${cols}`;
564
+ return `${rowIdx}${cols}`;
563
565
  }).join('\n');
564
566
  if (previewDiv) {
565
- previewDiv.textContent = `Columns: ${firstSheet.columns.join(' | ')}\n${'─'.repeat(80)}\n${preview}`;
567
+ previewDiv.textContent = `${'Row'.padEnd(6)}Columns: ${firstSheet.columns.join(' | ')}\n${separator}\n${preview}`;
566
568
  }
567
569
  }
568
570
  catch (err) {
@@ -597,7 +599,7 @@ export class DataFrameComponent extends BaseComponent {
597
599
  </div>
598
600
  <div style="margin-bottom: 1rem;">
599
601
  <label style="display: block; font-weight: 600; margin-bottom: 0.5rem;">Header Row</label>
600
- <input type="number" id="${this._id}-header-row" class="jux-input-element" value="1" min="1" max="50" style="width: 100%;" />
602
+ <input type="number" id="${this._id}-header-row" class="jux-input-element" value="0" min="0" max="50" style="width: 100%;" />
601
603
  </div>
602
604
  <div style="margin-bottom: 1rem;">
603
605
  <label style="display: block; font-weight: 600; margin-bottom: 0.5rem;">Skip Rows Before Header</label>
@@ -626,8 +628,7 @@ export class DataFrameComponent extends BaseComponent {
626
628
  const headerRowInput = document.getElementById(`${this._id}-header-row`);
627
629
  const skipRowsInput = document.getElementById(`${this._id}-skip-rows`);
628
630
  const delim = delimiterSelect.value;
629
- const headerRowOneBased = parseInt(headerRowInput.value) || 1;
630
- const headerRow = headerRowOneBased - 1; // Convert to 0-based
631
+ const headerRow = parseInt(headerRowInput.value) || 0;
631
632
  const skipRows = parseInt(skipRowsInput.value) || 0;
632
633
  this.state.loading = true;
633
634
  this._updateStatus('Re-parsing with new settings...', 'loading');
@@ -636,8 +637,7 @@ export class DataFrameComponent extends BaseComponent {
636
637
  delimiter: delim,
637
638
  headerRow,
638
639
  skipRows,
639
- hasHeader: true,
640
- maxRows: 10
640
+ hasHeader: true
641
641
  });
642
642
  await this._driver.store(this._rawFileData.file.name, df, { source: this._rawFileData.file.name });
643
643
  this._showReshapeWarning = false;
@@ -663,14 +663,13 @@ export class DataFrameComponent extends BaseComponent {
663
663
  delimiterSelect.value = detected;
664
664
  const detectedHeaderRow = this._driver._detectHeaderRow(this._rawFileData.text, detected);
665
665
  if (headerRowInput)
666
- headerRowInput.value = String(detectedHeaderRow + 1); // Convert 0-based to 1-based for display
666
+ headerRowInput.value = String(detectedHeaderRow);
667
667
  }
668
668
  const updatePreview = () => {
669
669
  if (!this._rawFileData?.text)
670
670
  return;
671
671
  const delim = delimiterSelect?.value || ',';
672
- const headerRowOneBased = parseInt(headerRowInput?.value) || 1;
673
- const headerRow = headerRowOneBased - 1; // Convert to 0-based
672
+ const headerRow = parseInt(headerRowInput?.value) || 0;
674
673
  const skipRows = parseInt(skipRowsInput?.value) || 0;
675
674
  try {
676
675
  const df = this._driver.parseCSV(this._rawFileData.text, {
@@ -680,12 +679,16 @@ export class DataFrameComponent extends BaseComponent {
680
679
  hasHeader: true,
681
680
  maxRows: 10
682
681
  });
683
- const preview = df.toRows().map((row, i) => {
682
+ const dataRows = df.toRows();
683
+ const colHeader = 'Row'.padEnd(6) + df.columns.map(c => String(c).padEnd(20)).join(' | ');
684
+ const separator = '─'.repeat(Math.min(colHeader.length, 120));
685
+ const preview = dataRows.map((row, i) => {
686
+ const rowIdx = String(headerRow + skipRows + 1 + i).padEnd(6);
684
687
  const cols = Object.values(row).map(v => String(v ?? '').padEnd(20)).join(' | ');
685
- return `${i === 0 ? '>> ' : ' '}${cols}`;
688
+ return `${rowIdx}${cols}`;
686
689
  }).join('\n');
687
690
  if (previewDiv) {
688
- previewDiv.textContent = `Columns: ${df.columns.join(' | ')}\n${'─'.repeat(80)}\n${preview}`;
691
+ previewDiv.textContent = `${'Row'.padEnd(6)}Columns: ${df.columns.join(' | ')}\n${separator}\n${preview}`;
689
692
  }
690
693
  }
691
694
  catch (err) {
@@ -542,14 +542,14 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
542
542
  }).length;
543
543
 
544
544
  if (nonNumericCount >= nonEmpty.length * 0.7 && i > 0) {
545
- // Return 1-based row number for the UI
546
- // i is index in toRows() but row 0 of the file was consumed as header,
547
- // so the actual file row is i + 1, and 1-based display is i + 2
548
- return i + 2;
545
+ // i is the index in toRows(). Row 0 of the file was already consumed
546
+ // as the header during the initial parse, so the actual 0-based file
547
+ // row index is i + 1.
548
+ return i + 1;
549
549
  }
550
550
  }
551
551
 
552
- return 1; // Default to row 1 (1-based)
552
+ return 0;
553
553
  }
554
554
 
555
555
  /* ═══════════════════════════════════════════════════
@@ -580,7 +580,7 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
580
580
 
581
581
  this._cleanupReshapeModal();
582
582
 
583
- const suggestedRow = this._df ? this._detectLikelyHeaderRow(this._df) : 1;
583
+ const suggestedRow = this._df ? this._detectLikelyHeaderRow(this._df) : 0;
584
584
 
585
585
  this._reshapeModal = new Modal(`${this._id}-reshape-modal`, {
586
586
  title: 'Excel Import Settings',
@@ -599,14 +599,14 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
599
599
  id="${this._id}-header-row"
600
600
  class="jux-input-element"
601
601
  value="${suggestedRow}"
602
- min="1"
602
+ min="0"
603
603
  max="50"
604
604
  style="width: 100%;"
605
605
  />
606
606
  <div class="jux-reshape-hint">
607
607
  <strong>Detected issue:</strong> The current header row appears to contain metadata or empty values.
608
608
  Row ${suggestedRow} looks like it contains the actual column headers.
609
- Adjust the value above and check the preview below.
609
+ Adjust the value above and check the preview below. The Row column shows the index for each row.
610
610
  </div>
611
611
  </div>
612
612
  <div class="jux-reshape-preview-container">
@@ -630,8 +630,7 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
630
630
  variant: 'primary',
631
631
  click: async () => {
632
632
  const input = document.getElementById(`${this._id}-header-row`) as HTMLInputElement;
633
- const headerRowOneBased = parseInt(input.value) || 1;
634
- const headerRow = headerRowOneBased - 1; // Convert to 0-based for driver
633
+ const headerRow = parseInt(input.value) || 0;
635
634
 
636
635
  this.state.loading = true;
637
636
  this._updateStatus('Re-parsing with new settings...', 'loading');
@@ -670,8 +669,7 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
670
669
  const previewDiv = document.getElementById(`${this._id}-preview`)!;
671
670
 
672
671
  const updatePreview = async () => {
673
- const headerRowOneBased = parseInt(headerRowInput?.value) || 1;
674
- const headerRow = headerRowOneBased - 1; // Convert to 0-based for driver
672
+ const headerRow = parseInt(headerRowInput?.value) || 0;
675
673
  try {
676
674
  const sheets = await this._driver.streamFileMultiSheet(this._rawFileData!.file, {
677
675
  headerRow,
@@ -684,13 +682,17 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
684
682
  return;
685
683
  }
686
684
 
687
- const preview = firstSheet.toRows().slice(0, 10).map((row, i) => {
685
+ const dataRows = firstSheet.toRows().slice(0, 10);
686
+ const colHeader = 'Row'.padEnd(6) + firstSheet.columns.map(c => String(c).padEnd(20)).join(' | ');
687
+ const separator = '─'.repeat(Math.min(colHeader.length, 120));
688
+ const preview = dataRows.map((row, i) => {
689
+ const rowIdx = String(headerRow + 1 + i).padEnd(6);
688
690
  const cols = Object.values(row).map(v => String(v ?? '').padEnd(20)).join(' | ');
689
- return `${i === 0 ? '>> ' : ' '}${cols}`;
691
+ return `${rowIdx}${cols}`;
690
692
  }).join('\n');
691
693
 
692
694
  if (previewDiv) {
693
- previewDiv.textContent = `Columns: ${firstSheet.columns.join(' | ')}\n${'─'.repeat(80)}\n${preview}`;
695
+ previewDiv.textContent = `${'Row'.padEnd(6)}Columns: ${firstSheet.columns.join(' | ')}\n${separator}\n${preview}`;
694
696
  }
695
697
  } catch (err: any) {
696
698
  if (previewDiv) previewDiv.textContent = `Error: ${err.message}`;
@@ -727,7 +729,7 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
727
729
  </div>
728
730
  <div style="margin-bottom: 1rem;">
729
731
  <label style="display: block; font-weight: 600; margin-bottom: 0.5rem;">Header Row</label>
730
- <input type="number" id="${this._id}-header-row" class="jux-input-element" value="1" min="1" max="50" style="width: 100%;" />
732
+ <input type="number" id="${this._id}-header-row" class="jux-input-element" value="0" min="0" max="50" style="width: 100%;" />
731
733
  </div>
732
734
  <div style="margin-bottom: 1rem;">
733
735
  <label style="display: block; font-weight: 600; margin-bottom: 0.5rem;">Skip Rows Before Header</label>
@@ -758,8 +760,7 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
758
760
  const skipRowsInput = document.getElementById(`${this._id}-skip-rows`) as HTMLInputElement;
759
761
 
760
762
  const delim = delimiterSelect.value;
761
- const headerRowOneBased = parseInt(headerRowInput.value) || 1;
762
- const headerRow = headerRowOneBased - 1; // Convert to 0-based
763
+ const headerRow = parseInt(headerRowInput.value) || 0;
763
764
  const skipRows = parseInt(skipRowsInput.value) || 0;
764
765
 
765
766
  this.state.loading = true;
@@ -770,8 +771,7 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
770
771
  delimiter: delim,
771
772
  headerRow,
772
773
  skipRows,
773
- hasHeader: true,
774
- maxRows: 10
774
+ hasHeader: true
775
775
  });
776
776
 
777
777
  await this._driver.store(this._rawFileData.file.name, df, { source: this._rawFileData.file.name });
@@ -800,15 +800,14 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
800
800
  if (delimiterSelect) delimiterSelect.value = detected;
801
801
 
802
802
  const detectedHeaderRow = (this._driver as any)._detectHeaderRow(this._rawFileData.text, detected);
803
- if (headerRowInput) headerRowInput.value = String(detectedHeaderRow + 1); // Convert 0-based to 1-based for display
803
+ if (headerRowInput) headerRowInput.value = String(detectedHeaderRow);
804
804
  }
805
805
 
806
806
  const updatePreview = () => {
807
807
  if (!this._rawFileData?.text) return;
808
808
 
809
809
  const delim = delimiterSelect?.value || ',';
810
- const headerRowOneBased = parseInt(headerRowInput?.value) || 1;
811
- const headerRow = headerRowOneBased - 1; // Convert to 0-based
810
+ const headerRow = parseInt(headerRowInput?.value) || 0;
812
811
  const skipRows = parseInt(skipRowsInput?.value) || 0;
813
812
 
814
813
  try {
@@ -820,13 +819,17 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
820
819
  maxRows: 10
821
820
  });
822
821
 
823
- const preview = df.toRows().map((row, i) => {
822
+ const dataRows = df.toRows();
823
+ const colHeader = 'Row'.padEnd(6) + df.columns.map(c => String(c).padEnd(20)).join(' | ');
824
+ const separator = '─'.repeat(Math.min(colHeader.length, 120));
825
+ const preview = dataRows.map((row, i) => {
826
+ const rowIdx = String(headerRow + skipRows + 1 + i).padEnd(6);
824
827
  const cols = Object.values(row).map(v => String(v ?? '').padEnd(20)).join(' | ');
825
- return `${i === 0 ? '>> ' : ' '}${cols}`;
828
+ return `${rowIdx}${cols}`;
826
829
  }).join('\n');
827
830
 
828
831
  if (previewDiv) {
829
- previewDiv.textContent = `Columns: ${df.columns.join(' | ')}\n${'─'.repeat(80)}\n${preview}`;
832
+ previewDiv.textContent = `${'Row'.padEnd(6)}Columns: ${df.columns.join(' | ')}\n${separator}\n${preview}`;
830
833
  }
831
834
  } catch (err: any) {
832
835
  if (previewDiv) previewDiv.textContent = `Error: ${err.message}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "juxscript",
3
- "version": "1.1.191",
3
+ "version": "1.1.192",
4
4
  "type": "module",
5
5
  "description": "A JavaScript UX authorship platform",
6
6
  "main": "index.js",