@bagelink/vue 1.0.16 → 1.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/style.css CHANGED
@@ -4404,20 +4404,20 @@ body:has(.bg-dark.is-active) {
4404
4404
  background: transparent;
4405
4405
  }
4406
4406
 
4407
- .fixed-columns[data-v-f204ab99] {
4407
+ .fixed-columns[data-v-147c95d0] {
4408
4408
  border-right: 2px solid var(--border-color);
4409
4409
  }
4410
- .spreadsheet table[data-v-f204ab99] {
4410
+ table[data-v-147c95d0] {
4411
4411
  border-collapse: collapse;
4412
4412
  }
4413
- .spreadsheet th[data-v-f204ab99], .spreadsheet td[data-v-f204ab99] {
4413
+ th[data-v-147c95d0], td[data-v-147c95d0] {
4414
4414
  border: 1px solid var(--border-color);
4415
4415
  padding: 0.1rem 0.5rem;
4416
4416
  min-width: 80px;
4417
4417
  background: var(--bgl-white);
4418
4418
  user-select: none;
4419
4419
  }
4420
- .spreadsheet th[data-v-f204ab99] {
4420
+ th[data-v-147c95d0] {
4421
4421
  background: var(--input-bg);
4422
4422
  white-space: nowrap;
4423
4423
  position: relative;
@@ -4425,27 +4425,27 @@ body:has(.bg-dark.is-active) {
4425
4425
  font-weight: 500;
4426
4426
  text-align: start;
4427
4427
  }
4428
- .spreadsheet th .bgl_icon-font[data-v-f204ab99]{
4428
+ th .bgl_icon-font[data-v-147c95d0]{
4429
4429
  vertical-align: middle;
4430
4430
  }
4431
- .spreadsheet td.selected[data-v-f204ab99] {
4431
+ td.selected[data-v-147c95d0] {
4432
4432
  background: var(--bgl-primary-light);
4433
4433
  }
4434
- .spreadsheet td.locked[data-v-f204ab99] {
4434
+ td.locked[data-v-147c95d0] {
4435
4435
  background: var(--bgl-gray-light);
4436
4436
  cursor: default;
4437
4437
  }
4438
- .spreadsheet td.locked.selected[data-v-f204ab99] {
4438
+ td.locked.selected[data-v-147c95d0] {
4439
4439
  background: var(--bgl-primary-light);
4440
4440
  }
4441
- .spreadsheet td[data-v-f204ab99] {
4441
+ td[data-v-147c95d0] {
4442
4442
  height: 40px;
4443
4443
  vertical-align: middle;
4444
4444
  }
4445
- .spreadsheet td[data-v-f204ab99]:has(img){
4445
+ td[data-v-147c95d0]:has(img){
4446
4446
  padding: 0;
4447
4447
  }
4448
- .spreadsheet td span[data-v-f204ab99]{
4448
+ td span[data-v-147c95d0]{
4449
4449
  display: block;
4450
4450
  display: -webkit-box;
4451
4451
  max-width: 100%;
@@ -4455,7 +4455,7 @@ body:has(.bg-dark.is-active) {
4455
4455
  -webkit-line-clamp: 1;
4456
4456
  word-break: break-all;
4457
4457
  }
4458
- .spreadsheet input[data-v-f204ab99] {
4458
+ input[data-v-147c95d0] {
4459
4459
  width: 100%;
4460
4460
  border: none;
4461
4461
  background: transparent;
@@ -4464,37 +4464,63 @@ body:has(.bg-dark.is-active) {
4464
4464
  min-height: 0;
4465
4465
  min-width: 0;
4466
4466
  }
4467
- .spreadsheet input[data-v-f204ab99]:focus {
4467
+ input[data-v-147c95d0]:focus {
4468
4468
  outline: 2px solid var(--bgl-primary);
4469
4469
  outline-offset: 6px;
4470
4470
  }
4471
- .spreadsheet th.sortable[data-v-f204ab99] {
4471
+ th.sortable[data-v-147c95d0] {
4472
4472
  cursor: pointer;
4473
4473
  }
4474
- .row-number-header[data-v-f204ab99], .row-number[data-v-f204ab99] {
4474
+ .row-number-header[data-v-147c95d0], .row-number[data-v-147c95d0] {
4475
4475
  width: fit-content;
4476
4476
  min-width: fit-content !important;
4477
4477
  padding: 0.1rem 0.7rem !important;
4478
4478
  }
4479
- .spreadsheet td .bgl-checkbox[data-v-f204ab99]{
4479
+ td .bgl-checkbox[data-v-147c95d0]{
4480
4480
  margin: 0;
4481
4481
  text-align: center;
4482
4482
  justify-content: center;
4483
4483
  }
4484
- .spreadsheet td[data-v-f204ab99]:has(.bgl-checkbox){
4484
+ td[data-v-147c95d0]:has(.bgl-checkbox){
4485
4485
  text-align: center;
4486
4486
  background: var(--input-bg);
4487
4487
  }
4488
- .spreadsheet td[data-v-f204ab99]:has(:checked){
4488
+ td[data-v-147c95d0]:has(:checked){
4489
4489
  background: var(--bgl-primary-light);
4490
4490
  }
4491
- .spreadsheetCellPlaceHolder[data-v-f204ab99]{
4491
+ .spreadsheetCellPlaceHolder[data-v-147c95d0]{
4492
4492
  height: 0px;
4493
4493
  overflow: hidden;
4494
4494
  opacity: 0;
4495
4495
  pointer-events: none;
4496
4496
  user-select: none;
4497
4497
  }
4498
+ .th-content[data-v-147c95d0] {
4499
+ position: relative;
4500
+ display: flex;
4501
+ align-items: center;
4502
+ width: 100%;
4503
+ height: 100%;
4504
+ }
4505
+ .resize-handle[data-v-147c95d0] {
4506
+ position: absolute;
4507
+ right: -8px;
4508
+ top: 0;
4509
+ bottom: 0;
4510
+ width: 4px;
4511
+ z-index: 100;
4512
+ cursor: col-resize;
4513
+ background: transparent;
4514
+ transition: background 0.2s;
4515
+ }
4516
+ .resize-handle[data-v-147c95d0]:hover {
4517
+ background: var(--bgl-primary);
4518
+ }
4519
+
4520
+ /* Spreadsheet container styles */
4521
+ .spreadsheet[data-v-e4d0dbbe] {
4522
+ user-select: none;
4523
+ }
4498
4524
 
4499
4525
  .zoomer-debug[data-v-379819e1] {
4500
4526
  position: fixed;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/vue",
3
3
  "type": "module",
4
- "version": "1.0.16",
4
+ "version": "1.0.18",
5
5
  "description": "Bagel core sdk packages",
6
6
  "author": {
7
7
  "name": "Neveh Allon",
@@ -1,6 +1,9 @@
1
1
  <script lang="ts" setup>
2
- import { Btn, Icon, CheckInput, TextInput } from '@bagelink/vue'
3
- import { computed, ref, watch, nextTick } from 'vue'
2
+ import type { VNode } from 'vue'
3
+ import { Btn, Icon, CheckInput, TextInput, localRef } from '@bagelink/vue'
4
+ import { computed, ref, watch, nextTick, onUnmounted } from 'vue'
5
+ import Dropdown from '../Dropdown.vue'
6
+ import SpreadsheetTable from './SpreadsheetTable.vue'
4
7
 
5
8
  // Define column configuration types
6
9
  type ColumnFormat = 'text' | 'number' | 'currency' | 'date' | 'percentage' | 'image' | 'boolean'
@@ -91,6 +94,9 @@ function emitUpdate() {
91
94
  emit('update:modelValue', localRows.value.map(row => unflattenObject({ ...row })))
92
95
  }
93
96
 
97
+ // After other ref declarations but before the columns computed property
98
+ const visibleColumns = ref<string[]>([])
99
+
94
100
  // Sort state
95
101
  const sortColumn = ref<string | null>(null)
96
102
  const sortDirection = ref<'asc' | 'desc'>('asc')
@@ -178,7 +184,7 @@ function isCellEditable(columnKey: string): boolean {
178
184
  return !(column?.locked ?? false)
179
185
  }
180
186
 
181
- // Sort rows by column
187
+ // Update the sortByColumn function to preserve column visibility
182
188
  function sortByColumn(columnKey: string) {
183
189
  const column = columns.value.find(col => col.key === columnKey)
184
190
  if (!column?.sortable) return
@@ -202,8 +208,16 @@ function sortByColumn(columnKey: string) {
202
208
  return aVal < bVal ? -modifier : modifier
203
209
  })
204
210
 
211
+ // Save the current visibleColumns state
212
+ const currentVisibleColumns = [...visibleColumns.value]
213
+
205
214
  localRows.value = sorted
206
215
  emitUpdate()
216
+
217
+ // Restore the visibleColumns state after the update
218
+ nextTick(() => {
219
+ visibleColumns.value = currentVisibleColumns
220
+ })
207
221
  }
208
222
 
209
223
  // Variables to handle cell selection
@@ -356,13 +370,25 @@ function updateCell(rowIndex: number, key: string, newValue: string | boolean) {
356
370
  emitUpdate()
357
371
  }
358
372
 
359
- // Update the fixed and scrollable columns computed properties to filter out hidden columns
373
+ // After other ref declarations but before computed properties
374
+ // const visibleColumns = ref<string[]>([])
375
+
376
+ // After the columns computed property
377
+ // Initialize visibleColumns with all columns when columns change
378
+ watch(() => columns.value, (newColumns) => {
379
+ if (newColumns.length > 0 && visibleColumns.value.length === 0) {
380
+ visibleColumns.value = newColumns.filter(col => !col.hidden).map(col => col.key)
381
+ }
382
+ })
383
+
384
+ // Update the fixedColumns computed property
360
385
  const fixedColumns = computed(() => {
361
- return columns.value.filter(col => col.fixed && !col.hidden)
386
+ return columns.value.filter(col => col.fixed && !col.hidden && visibleColumns.value.includes(col.key))
362
387
  })
363
388
 
389
+ // Update the scrollableColumns computed property
364
390
  const scrollableColumns = computed(() => {
365
- return columns.value.filter(col => !col.fixed && !col.hidden)
391
+ return columns.value.filter(col => !col.fixed && !col.hidden && visibleColumns.value.includes(col.key))
366
392
  })
367
393
 
368
394
  // Update createEmptyRow to use defaultValue from column config
@@ -418,7 +444,16 @@ async function copySelection() {
418
444
  }
419
445
  }
420
446
 
421
- // Paste function using Navigator Clipboard API
447
+ // Add a ref for the search input
448
+ const searchInputRef = ref<any>(null)
449
+
450
+ // Add a method to check if the search input is focused
451
+ function isSearchFocused(): boolean {
452
+ const inputElement = searchInputRef.value?.$el?.querySelector('input')
453
+ return document.activeElement === inputElement
454
+ }
455
+
456
+ // Update the pasteSelection function to handle search focus
422
457
  async function pasteSelection() {
423
458
  if (!selectionStart.value) return
424
459
 
@@ -461,6 +496,17 @@ async function pasteSelection() {
461
496
  }
462
497
  }
463
498
 
499
+ // Create a handler for paste events at the container level
500
+ function handleContainerPaste(event: ClipboardEvent) {
501
+ if (isSearchFocused()) {
502
+ // If search is focused and spreadsheet has a selection, override default behavior
503
+ if (selectionStart.value) {
504
+ event.preventDefault()
505
+ pasteSelection()
506
+ }
507
+ }
508
+ }
509
+
464
510
  // Add a variable to track the original value before editing
465
511
  const editingOriginalValue = ref<string | null>(null)
466
512
 
@@ -543,8 +589,8 @@ function handleCellKeyDown(event: KeyboardEvent, row: number, col: number) {
543
589
  // Update keyboard shortcuts to include undo/redo
544
590
  function handleSpreadsheetKeyDown(event: KeyboardEvent) {
545
591
  // Don't intercept keyboard shortcuts when editing a cell
546
- if (editingCell.value) return
547
-
592
+ if (editingCell.value || isSearchFocused()) return
593
+ console.log('handleSpreadsheetKeyDown', event)
548
594
  const isCtrlOrCmd = event.ctrlKey || event.metaKey
549
595
 
550
596
  if (isCtrlOrCmd) {
@@ -593,6 +639,64 @@ const filteredRows = computed(() => {
593
639
  })
594
640
  })
595
641
  })
642
+
643
+ // Add after other ref declarations
644
+ const columnWidths = ref<Map<string, number>>(new Map())
645
+ const isResizing = ref(false)
646
+ const resizingColumn = ref<string | null>(null)
647
+ const startX = ref<number>(0)
648
+ const startWidth = ref<number>(0)
649
+
650
+ // Add after other function declarations
651
+ function handleResizeStart(e: MouseEvent, columnKey: string) {
652
+ isResizing.value = true
653
+ resizingColumn.value = columnKey
654
+ startX.value = e.pageX
655
+
656
+ // Find the column header element
657
+ const columnHeader = (e.target as HTMLElement).closest('th')
658
+ if (!columnHeader) return
659
+
660
+ // Get the actual computed width of the column
661
+ const computedWidth = columnHeader.getBoundingClientRect().width
662
+ const currentWidth = columnWidths.value.get(columnKey) || computedWidth
663
+ startWidth.value = currentWidth
664
+
665
+ // Add event listeners for mousemove and mouseup
666
+ document.addEventListener('mousemove', handleResizeMove)
667
+ document.addEventListener('mouseup', handleResizeEnd)
668
+ }
669
+
670
+ function handleResizeMove(e: MouseEvent) {
671
+ if (!isResizing.value || !resizingColumn.value) return
672
+
673
+ e.preventDefault()
674
+
675
+ const diff = e.pageX - startX.value
676
+ const newWidth = Math.max(80, startWidth.value + diff) // Keep minimum width of 80px
677
+
678
+ columnWidths.value.set(resizingColumn.value, newWidth)
679
+ }
680
+
681
+ function handleResizeEnd() {
682
+ isResizing.value = false
683
+ resizingColumn.value = null
684
+
685
+ // Remove event listeners
686
+ document.removeEventListener('mousemove', handleResizeMove)
687
+ document.removeEventListener('mouseup', handleResizeEnd)
688
+ }
689
+
690
+ // Clean up event listeners when component is unmounted
691
+ onUnmounted(() => {
692
+ document.removeEventListener('mousemove', handleResizeMove)
693
+ document.removeEventListener('mouseup', handleResizeEnd)
694
+ })
695
+
696
+ // Add a computed property for visible column options
697
+ const columnOptions = computed(() => {
698
+ return columns.value.filter(col => !col.hidden)
699
+ })
596
700
  </script>
597
701
 
598
702
  <template>
@@ -600,7 +704,22 @@ const filteredRows = computed(() => {
600
704
  <div class="flex gap-05 py-05 justify-content-end m_flex-wrap">
601
705
  <label v-if="label" class="label me-auto">{{ label }}</label>
602
706
  <div class="flex gap-075">
603
- <TextInput v-model="search" icon="search" placeholder="Search" class="m-0 max-w200px" />
707
+ <Dropdown flat thin icon="view_column">
708
+ <div class="p-05">
709
+ <div class="flex space-between">
710
+ <Btn flat thin small value="Select All" @click="visibleColumns = columnOptions.map(col => col.key)" />
711
+ <Btn flat thin small value="Clear All" @click="visibleColumns = []" />
712
+ </div>
713
+ <CheckInput
714
+ v-for="col in columnOptions"
715
+ :key="col.key"
716
+ v-model="visibleColumns"
717
+ :value="col.key"
718
+ :label="col.label || col.key"
719
+ />
720
+ </div>
721
+ </Dropdown>
722
+ <TextInput ref="searchInputRef" v-model="search" icon="search" placeholder="Search" class="m-0 max-w200px" />
604
723
  <Btn v-tooltip="'Paste'" flat thin round icon="paste" @click="pasteSelection" />
605
724
  <Btn v-tooltip="'copy'" flat thin round icon="copy" @click="copySelection" />
606
725
  <Btn v-tooltip="'Undo'" flat thin round icon="undo" :disabled="!canUndo" @click="undo" />
@@ -610,156 +729,57 @@ const filteredRows = computed(() => {
610
729
  <div class="spreadsheet" @mouseup="handleMouseUp">
611
730
  <div class="flex w-100p relative">
612
731
  <!-- Fixed Columns -->
613
- <table v-if="fixedColumns.length" class="fixed-columns sticky z-2 start-0 bg-white">
614
- <thead>
615
- <tr>
616
- <th class="row-number-header bg-white" />
617
- <th
618
- v-for="col in fixedColumns"
619
- :key="col.key"
620
- >
621
- <span @click="col.sortable && sortByColumn(col.key)">
622
- {{ col.label || col.key }}
623
- </span>
624
- <Icon
625
- v-if="sortColumn === col.key"
626
- class="line-height-0 transition-400"
627
- name="keyboard_arrow_down" :class="{ 'rotate-180': sortDirection === 'desc' }"
628
- />
629
- </th>
630
- </tr>
631
- </thead>
632
- <tbody>
633
- <tr v-for="(row, rowIndex) in filteredRows" :key="rowIndex">
634
- <td class="row-number txt-center hover user-select-none pointer txt12 regular" @click="selectEntireRow(rowIndex)">
635
- {{ rowIndex + 1 }}
636
- </td>
637
- <td
638
- v-for="col in fixedColumns"
639
- :key="col.key"
640
- :class="{
641
- selected: isCellSelected(rowIndex, fixedColumns.indexOf(col)),
642
- locked: !isCellEditable(col.key),
643
- }"
644
- :style="{ width: col.width }"
645
- :tabindex="col.hidden ? undefined : 0"
646
- @mousedown="handleMouseDown(rowIndex, fixedColumns.indexOf(col))"
647
- @mouseover="handleMouseOver(rowIndex, fixedColumns.indexOf(col))"
648
- @focusin="handleMouseOver(rowIndex, fixedColumns.indexOf(col))"
649
- @dblclick="startEditing(rowIndex, fixedColumns.indexOf(col))"
650
- @keydown="handleCellKeyDown($event, rowIndex, fixedColumns.indexOf(col))"
651
- >
652
- <template v-if="editingCell && editingCell.row === rowIndex && editingCell.col === fixedColumns.indexOf(col)">
653
- <input
654
- :ref="el => setInputRef(el, `cell-${rowIndex}-${fixedColumns.indexOf(col)}`)"
655
- :value="row[col.key]"
656
- type="text"
657
- class="spreadsheet-input"
658
- @input="(e: Event) => updateCell(rowIndex, col.key, (e.target as HTMLInputElement).value)"
659
- @blur="handleStopEditingAndBlur(false)"
660
- @keydown.enter.prevent="handleStopEditingAndBlur(false)"
661
- @keydown.esc.prevent="handleStopEditingAndBlur(true)"
662
- @mousedown.stop
663
- >
664
- <span class="spreadsheet-cell spreadsheetCellPlaceHolder">{{ formatCellValue(row[col.key], col.format) }}</span>
665
- </template>
666
- <template v-else>
667
- <template v-if="col.format === 'image'">
668
- <div class="h40px w-100p flex align-items-center justify-content-center overflow-hidden">
669
- <img class=" w-100p h-100p contain radius-05" :src="row[col.key]" :alt="col.label || col.key">
670
- </div>
671
- </template>
672
- <template v-else-if="col.format === 'boolean'">
673
- <CheckInput
674
- :modelValue="!!row[col.key]"
675
- :disabled="!isCellEditable(col.key)"
676
- @update:modelValue="(value: boolean | any[] | undefined) => updateCell(rowIndex, col.key, !!value)"
677
- @mousedown.stop
678
- />
679
- </template>
680
- <template v-else>
681
- <span class="spreadsheet-cell">{{ formatCellValue(row[col.key], col.format) }}</span>
682
- </template>
683
- </template>
684
- </td>
685
- </tr>
686
- </tbody>
687
- </table>
732
+ <SpreadsheetTable
733
+ v-if="fixedColumns.length"
734
+ :columns="fixedColumns"
735
+ :rows="filteredRows"
736
+ :is-fixed="true"
737
+ :show-row-numbers="true"
738
+ :column-widths="columnWidths"
739
+ :sort-column="sortColumn"
740
+ :sort-direction="sortDirection"
741
+ :selection-start="selectionStart"
742
+ :selection-end="selectionEnd"
743
+ :editing-cell="editingCell"
744
+ :base-column-index="0"
745
+ class="sticky z-2 start-0 bg-white"
746
+ @sortColumn="sortByColumn"
747
+ @resizeStart="handleResizeStart"
748
+ @selectRow="selectEntireRow"
749
+ @cellMouseDown="handleMouseDown"
750
+ @cellMouseOver="handleMouseOver"
751
+ @cellEditStart="startEditing"
752
+ @cellKeyDown="handleCellKeyDown"
753
+ @updateCell="updateCell"
754
+ @stopEditing="handleStopEditingAndBlur"
755
+ @setInputRef="setInputRef"
756
+ />
688
757
 
689
758
  <!-- Scrollable Columns -->
690
759
  <div class="flex-shrink flex-grow overflow-x">
691
- <table class="w-100p">
692
- <thead>
693
- <tr>
694
- <th v-if="!fixedColumns.length" class="row-number-header bg-white" />
695
- <th
696
- v-for="col in scrollableColumns"
697
- :key="col.key"
698
- >
699
- <span @click="col.sortable && sortByColumn(col.key)">
700
- {{ col.label || col.key }}
701
- </span>
702
-
703
- <Icon v-if="sortColumn === col.key" name="keyboard_arrow_down" class="line-height-0 inline-block" :class="{ 'rotate-180': sortColumn === col.key && sortDirection === 'desc' }" />
704
- </th>
705
- </tr>
706
- </thead>
707
- <tbody>
708
- <tr v-for="(row, rowIndex) in filteredRows" :key="rowIndex">
709
- <td v-if="!fixedColumns.length" class="row-number txt-center hover user-select-none pointer txt12 regular" @click="selectEntireRow(rowIndex)">
710
- {{ rowIndex + 1 }}
711
- </td>
712
- <td
713
- v-for="(col, colIndex) in scrollableColumns"
714
- :key="col.key"
715
- :class="{
716
- selected: isCellSelected(rowIndex, fixedColumns.length + colIndex),
717
- locked: !isCellEditable(col.key),
718
- }"
719
- :style="{ width: col.width }"
720
- :tabindex="col.hidden ? undefined : 0"
721
- @mousedown="handleMouseDown(rowIndex, fixedColumns.length + colIndex)"
722
- @mouseover="handleMouseOver(rowIndex, fixedColumns.length + colIndex)"
723
- @focusin="handleMouseOver(rowIndex, fixedColumns.length + colIndex)"
724
- @dblclick="startEditing(rowIndex, fixedColumns.length + colIndex)"
725
- @keydown="handleCellKeyDown($event, rowIndex, fixedColumns.length + colIndex)"
726
- >
727
- <template v-if="editingCell && editingCell.row === rowIndex && editingCell.col === (fixedColumns.length + colIndex)">
728
- <input
729
- :ref="el => setInputRef(el, `cell-${rowIndex}-${fixedColumns.length + colIndex}`)"
730
- :value="row[col.key]"
731
- type="text"
732
- class="spreadsheet-input"
733
- @input="(e: Event) => updateCell(rowIndex, col.key, (e.target as HTMLInputElement).value)"
734
- @blur="handleStopEditingAndBlur(false)"
735
- @keydown.enter.prevent="handleStopEditingAndBlur(false)"
736
- @keydown.esc.prevent="handleStopEditingAndBlur(true)"
737
- @mousedown.stop
738
- >
739
- <span class="spreadsheet-cell spreadsheetCellPlaceHolder">{{ formatCellValue(row[col.key], col.format) }}</span>
740
- </template>
741
- <template v-else>
742
- <template v-if="col.format === 'image'">
743
- <div v-if="row[col.key]" class="h40px w-100p flex align-items-center justify-content-center overflow-hidden">
744
- <img class=" w-100p h-100p contain radius-05" :src="row[col.key]" :alt="col.label || col.key">
745
- </div>
746
- </template>
747
- <template v-else-if="col.format === 'boolean'">
748
- <CheckInput
749
- :modelValue="!!row[col.key]"
750
- :disabled="!isCellEditable(col.key)"
751
- @update:modelValue="(value: boolean | any[] | undefined) => updateCell(rowIndex, col.key, !!value)"
752
- @mousedown.stop
753
- />
754
- </template>
755
- <template v-else>
756
- <span class="spreadsheet-cell">{{ formatCellValue(row[col.key], col.format) }}</span>
757
- </template>
758
- </template>
759
- </td>
760
- </tr>
761
- </tbody>
762
- </table>
760
+ <SpreadsheetTable
761
+ :columns="scrollableColumns"
762
+ :rows="filteredRows"
763
+ :is-fixed="false"
764
+ :show-row-numbers="!fixedColumns.length"
765
+ :column-widths="columnWidths"
766
+ :sort-column="sortColumn"
767
+ :sort-direction="sortDirection"
768
+ :selection-start="selectionStart"
769
+ :selection-end="selectionEnd"
770
+ :editing-cell="editingCell"
771
+ :base-column-index="fixedColumns.length"
772
+ @sortColumn="sortByColumn"
773
+ @resizeStart="handleResizeStart"
774
+ @selectRow="selectEntireRow"
775
+ @cellMouseDown="handleMouseDown"
776
+ @cellMouseOver="handleMouseOver"
777
+ @cellEditStart="startEditing"
778
+ @cellKeyDown="handleCellKeyDown"
779
+ @updateCell="updateCell"
780
+ @stopEditing="handleStopEditingAndBlur"
781
+ @setInputRef="setInputRef"
782
+ />
763
783
  </div>
764
784
  </div>
765
785
  <Btn v-if="allowAddRow" outline thin round icon="add" value="Add Row" class="mt-05" @click="addRow" />
@@ -768,97 +788,8 @@ const filteredRows = computed(() => {
768
788
  </template>
769
789
 
770
790
  <style scoped>
771
- .fixed-columns {
772
- border-right: 2px solid var(--border-color);
773
- }
774
- .spreadsheet table {
775
- border-collapse: collapse;
776
- }
777
- .spreadsheet th, .spreadsheet td {
778
- border: 1px solid var(--border-color);
779
- padding: 0.1rem 0.5rem;
780
- min-width: 80px;
781
- background: var(--bgl-white);
782
- user-select: none;
783
- }
784
- .spreadsheet th {
785
- background: var(--input-bg);
786
- white-space: nowrap;
787
- position: relative;
788
- padding: 0.25rem 0.5rem;
789
- font-weight: 500;
790
- text-align: start;
791
- }
792
- .spreadsheet th .bgl_icon-font{
793
- vertical-align: middle;
794
- }
795
- .spreadsheet td.selected {
796
- background: var(--bgl-primary-light);
797
- }
798
- .spreadsheet td.locked {
799
- background: var(--bgl-gray-light);
800
- cursor: default;
801
- }
802
- .spreadsheet td.locked.selected {
803
- background: var(--bgl-primary-light);
804
- }
805
- .spreadsheet td {
806
- height: 40px;
807
- vertical-align: middle;
808
- }
809
- .spreadsheet td:has(img){
810
- padding: 0;
811
- }
812
- .spreadsheet td span{
813
- display: block;
814
- display: -webkit-box;
815
- max-width: 100%;
816
- -webkit-box-orient: vertical;
817
- overflow: hidden;
818
- text-overflow: ellipsis;
819
- -webkit-line-clamp: 1;
820
- word-break: break-all;
821
- }
822
- .spreadsheet input {
823
- width: 100%;
824
- border: none;
825
- background: transparent;
826
- padding: 0;
827
- margin: 0;
828
- min-height: 0;
829
- min-width: 0;
830
- }
831
- .spreadsheet input:focus {
832
- outline: 2px solid var(--bgl-primary);
833
- outline-offset: 6px;
834
- }
835
- .spreadsheet th.sortable {
836
- cursor: pointer;
837
- }
838
- .row-number-header, .row-number {
839
- width: fit-content;
840
- min-width: fit-content !important;
841
- padding: 0.1rem 0.7rem !important;
842
- }
843
- .spreadsheet td .bgl-checkbox{
844
- margin: 0;
845
- text-align: center;
846
- justify-content: center;
847
-
848
- }
849
- .spreadsheet td:has(.bgl-checkbox){
850
- text-align: center;
851
- background: var(--input-bg);
852
- }
853
- .spreadsheet td:has(:checked){
854
- background: var(--bgl-primary-light);
855
- }
856
-
857
- .spreadsheetCellPlaceHolder{
858
- height: 0px;
859
- overflow: hidden;
860
- opacity: 0;
861
- pointer-events: none;
791
+ /* Spreadsheet container styles */
792
+ .spreadsheet {
862
793
  user-select: none;
863
794
  }
864
795
  </style>