infotable 1.4.0 → 1.5.0
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.
- checksums.yaml +4 -4
- data/README.md +35 -1
- data/app/assets/javascripts/infotable/controllers/drawer_controller.js +59 -364
- data/app/assets/javascripts/infotable/controllers/table_controller.js +85 -103
- data/app/assets/javascripts/infotable/vendor/sortable.esm.js +3363 -0
- data/app/controllers/infotable/tables_controller.rb +15 -4
- data/app/helpers/infotable/tables_helper.rb +11 -23
- data/app/views/infotable/tables/_column_visibility.html.erb +4 -4
- data/app/views/infotable/tables/_end_indicator.html.erb +8 -0
- data/app/views/infotable/tables/_next_page_frame.html.erb +1 -9
- data/app/views/infotable/tables/_table_rows.html.erb +10 -3
- data/app/views/infotable/tables/show.html.erb +3 -3
- data/config/importmap.rb +2 -2
- data/lib/generators/infotable/install/templates/initializer.rb +5 -3
- data/lib/infotable/base.rb +61 -4
- data/lib/infotable/configuration.rb +1 -1
- data/lib/infotable/engine.rb +1 -8
- data/lib/infotable/filter_processor.rb +10 -1
- data/lib/infotable/formatters/boolean_formatter.rb +4 -4
- data/lib/infotable/table_resolver.rb +9 -0
- data/lib/infotable/version.rb +1 -1
- metadata +3 -1
|
@@ -48,6 +48,8 @@ export default class extends Controller {
|
|
|
48
48
|
|
|
49
49
|
// Listen for column visibility changes to update export link
|
|
50
50
|
this.boundUpdateExportLink = this.updateExportLink.bind(this)
|
|
51
|
+
this.boundApplyColumns = this.applyColumnsFromDrawer.bind(this)
|
|
52
|
+
document.addEventListener("infotable:apply-columns", this.boundApplyColumns)
|
|
51
53
|
document.addEventListener("infotable:columns-changed", this.boundUpdateExportLink)
|
|
52
54
|
document.addEventListener("infotable:filters-changed", this.boundUpdateExportLink)
|
|
53
55
|
}
|
|
@@ -55,6 +57,7 @@ export default class extends Controller {
|
|
|
55
57
|
disconnect() {
|
|
56
58
|
this.element.removeEventListener("turbo:frame-load", this.boundApplyOrderAndVisibility)
|
|
57
59
|
document.removeEventListener("infotable:columns-changed", this.boundUpdateExportLink)
|
|
60
|
+
document.removeEventListener("infotable:apply-columns", this.boundApplyColumns)
|
|
58
61
|
document.removeEventListener("infotable:filters-changed", this.boundUpdateExportLink)
|
|
59
62
|
window.removeEventListener("resize", this.boundFitHeight)
|
|
60
63
|
cancelAnimationFrame(this.fitFrame)
|
|
@@ -88,22 +91,16 @@ export default class extends Controller {
|
|
|
88
91
|
this.applyColumnPinning()
|
|
89
92
|
}
|
|
90
93
|
|
|
91
|
-
// Handle loading states
|
|
92
|
-
beforeFetchRequest(event) {
|
|
93
|
-
this.showLoading()
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
afterFetchResponse(event) {
|
|
97
|
-
this.hideLoading()
|
|
98
|
-
}
|
|
99
|
-
|
|
100
94
|
// Handle turbo frame load
|
|
101
95
|
handleFrameLoad(event) {
|
|
102
96
|
this.fitHeight()
|
|
103
97
|
this.updateFilterCount(event.target)
|
|
104
98
|
// rows matching the current filters, when the server knows it (not with countless pagination)
|
|
105
|
-
|
|
106
|
-
|
|
99
|
+
// (a nested frame, e.g. the infinite-scroll "next page" one, carries no count: keep the last one)
|
|
100
|
+
if (event.target.id === `${this.nameValue}_content`) {
|
|
101
|
+
const total = parseInt(event.target.querySelector("[data-total-count]")?.dataset.totalCount, 10)
|
|
102
|
+
this.totalCount = Number.isFinite(total) ? total : null
|
|
103
|
+
}
|
|
107
104
|
this.syncSelectionScope(event.target)
|
|
108
105
|
if (this.urlStateValue && event.target.id === `${this.nameValue}_content`) this.syncUrl(event.target)
|
|
109
106
|
}
|
|
@@ -179,7 +176,7 @@ export default class extends Controller {
|
|
|
179
176
|
}
|
|
180
177
|
|
|
181
178
|
// The first change on a fresh page replaces the entry, later ones add entries for Back
|
|
182
|
-
const state = { turbo: { restorationIdentifier: crypto.randomUUID() } }
|
|
179
|
+
const state = { turbo: { restorationIdentifier: (crypto.randomUUID?.() ?? `infotable-${Date.now()}-${Math.random().toString(36).slice(2)}`) } }
|
|
183
180
|
if (this.urlStateStarted) {
|
|
184
181
|
window.history.pushState(state, "", next)
|
|
185
182
|
} else {
|
|
@@ -240,7 +237,17 @@ export default class extends Controller {
|
|
|
240
237
|
// Fires for rows added later (next page, infinite scroll) so they pick up the selection
|
|
241
238
|
rowCheckboxTargetConnected(checkbox) {
|
|
242
239
|
checkbox.checked = this.selected.has(checkbox.value)
|
|
243
|
-
this.
|
|
240
|
+
this.scheduleRenderSelection()
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// A page connects up to 500 checkboxes at once: render the selection once for all of them
|
|
244
|
+
scheduleRenderSelection() {
|
|
245
|
+
if (this.renderScheduled) return
|
|
246
|
+
this.renderScheduled = true
|
|
247
|
+
queueMicrotask(() => {
|
|
248
|
+
this.renderScheduled = false
|
|
249
|
+
this.renderSelection()
|
|
250
|
+
})
|
|
244
251
|
}
|
|
245
252
|
|
|
246
253
|
toggleRow(event) {
|
|
@@ -379,15 +386,6 @@ export default class extends Controller {
|
|
|
379
386
|
form.remove()
|
|
380
387
|
}
|
|
381
388
|
|
|
382
|
-
showLoading() {
|
|
383
|
-
// Add loading indicator (to be enhanced in later phases)
|
|
384
|
-
this.element.style.opacity = "0.6"
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
hideLoading() {
|
|
388
|
-
this.element.style.opacity = "1"
|
|
389
|
-
}
|
|
390
|
-
|
|
391
389
|
// Shift+click on a sortable header adds/toggles the column in the multi-sort list
|
|
392
390
|
// (sort=name:asc,age:desc). A plain click keeps the link's single-column behaviour.
|
|
393
391
|
sortClick(event) {
|
|
@@ -491,8 +489,18 @@ export default class extends Controller {
|
|
|
491
489
|
}
|
|
492
490
|
}
|
|
493
491
|
|
|
494
|
-
//
|
|
495
|
-
|
|
492
|
+
// The columns drawer changed order, visibility or pinning (it stored them in localStorage)
|
|
493
|
+
applyColumnsFromDrawer(event) {
|
|
494
|
+
const { tableName, order } = event.detail
|
|
495
|
+
if (tableName !== this.nameValue) return
|
|
496
|
+
|
|
497
|
+
this.applyColumnOrder(order)
|
|
498
|
+
this.applyColumnVisibility()
|
|
499
|
+
this.applyColumnPinning()
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// Apply column order: the given one, else the one in localStorage
|
|
503
|
+
applyColumnOrder(explicitOrder = null) {
|
|
496
504
|
const tableName = this.nameValue
|
|
497
505
|
const orderKey = `infotable_column_order_${tableName}`
|
|
498
506
|
|
|
@@ -520,11 +528,11 @@ export default class extends Controller {
|
|
|
520
528
|
const defaultSchema = headers.map(h => h.dataset.columnName)
|
|
521
529
|
|
|
522
530
|
// Load stored order from localStorage
|
|
523
|
-
const storedOrder = this.loadColumnOrder(tableName)
|
|
531
|
+
const storedOrder = explicitOrder || this.loadColumnOrder(tableName)
|
|
524
532
|
if (!storedOrder) return
|
|
525
533
|
|
|
526
534
|
// Validate stored order against default schema
|
|
527
|
-
if (!this.isSchemaValid(storedOrder, defaultSchema)) {
|
|
535
|
+
if (!explicitOrder && !this.isSchemaValid(storedOrder, defaultSchema)) {
|
|
528
536
|
console.warn(`Schema mismatch for table ${tableName}, clearing stored order`)
|
|
529
537
|
this.clearColumnOrder(tableName)
|
|
530
538
|
return
|
|
@@ -628,7 +636,6 @@ export default class extends Controller {
|
|
|
628
636
|
}
|
|
629
637
|
|
|
630
638
|
const headers = table.querySelectorAll("thead th[data-column-name]")
|
|
631
|
-
const rows = table.querySelectorAll("tbody tr")
|
|
632
639
|
|
|
633
640
|
if (headers.length === 0) {
|
|
634
641
|
console.warn(`No column headers found for table: ${tableName}`)
|
|
@@ -642,31 +649,18 @@ export default class extends Controller {
|
|
|
642
649
|
visibility = JSON.parse(stored)
|
|
643
650
|
}
|
|
644
651
|
|
|
652
|
+
const shown = new Map()
|
|
645
653
|
headers.forEach((header) => {
|
|
646
654
|
const columnName = header.dataset.columnName
|
|
647
|
-
const
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
let shouldShow
|
|
651
|
-
if (visibility && visibility.hasOwnProperty(columnName)) {
|
|
652
|
-
// Use saved preference
|
|
653
|
-
shouldShow = visibility[columnName]
|
|
654
|
-
} else {
|
|
655
|
-
// Use default visibility
|
|
656
|
-
shouldShow = defaultVisible
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
// Apply visibility
|
|
655
|
+
const saved = visibility && Object.prototype.hasOwnProperty.call(visibility, columnName)
|
|
656
|
+
const shouldShow = saved ? visibility[columnName] : header.dataset.defaultVisible === "true"
|
|
657
|
+
shown.set(columnName, shouldShow)
|
|
660
658
|
header.style.display = shouldShow ? "" : "none"
|
|
659
|
+
})
|
|
661
660
|
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
const cell = Array.from(cells).find(c => c.dataset.columnName === columnName)
|
|
666
|
-
if (cell) {
|
|
667
|
-
cell.style.display = shouldShow ? "" : "none"
|
|
668
|
-
}
|
|
669
|
-
})
|
|
661
|
+
// One pass over the cells: hide/show each by its column
|
|
662
|
+
table.querySelectorAll("tbody td[data-column-name]").forEach(cell => {
|
|
663
|
+
if (shown.has(cell.dataset.columnName)) cell.style.display = shown.get(cell.dataset.columnName) ? "" : "none"
|
|
670
664
|
})
|
|
671
665
|
} catch (e) {
|
|
672
666
|
console.warn("Failed to apply column visibility", e)
|
|
@@ -781,34 +775,31 @@ export default class extends Controller {
|
|
|
781
775
|
// The data-turbo="false" ensures Turbo doesn't intercept this
|
|
782
776
|
}
|
|
783
777
|
|
|
784
|
-
//
|
|
778
|
+
// Row click (`row_link` and/or `row_click`). Fires a cancelable `infotable:row-click` on the row;
|
|
779
|
+
// when nothing calls preventDefault() the click falls back to following the row's link.
|
|
785
780
|
handleRowClick(event) {
|
|
786
781
|
const row = event.currentTarget
|
|
787
|
-
const url = row.dataset.rowLink
|
|
788
|
-
|
|
789
|
-
if (!url) return
|
|
790
782
|
|
|
791
|
-
//
|
|
792
|
-
|
|
793
|
-
const tagName = target.tagName.toLowerCase()
|
|
783
|
+
// Clicks on controls inside the row belong to those controls
|
|
784
|
+
if (event.target.closest("a, button, summary, details, label, input, select, textarea")) return
|
|
794
785
|
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
}
|
|
786
|
+
const url = row.dataset.rowLink || null
|
|
787
|
+
const data = { ...row.dataset }
|
|
788
|
+
delete data.rowLink
|
|
789
|
+
delete data.action
|
|
800
790
|
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
791
|
+
const click = new CustomEvent("infotable:row-click", {
|
|
792
|
+
bubbles: true,
|
|
793
|
+
cancelable: true,
|
|
794
|
+
detail: { id: row.id || null, url, data, originalEvent: event }
|
|
795
|
+
})
|
|
796
|
+
if (!row.dispatchEvent(click) || !url) return
|
|
805
797
|
|
|
806
|
-
//
|
|
807
|
-
// Check if meta key (Cmd on Mac, Ctrl on Windows) is pressed for new tab
|
|
798
|
+
// Cmd on Mac, Ctrl elsewhere: new tab
|
|
808
799
|
if (event.metaKey || event.ctrlKey) {
|
|
809
800
|
window.open(url, "_blank")
|
|
810
801
|
} else {
|
|
811
|
-
window.location.href = url
|
|
802
|
+
window.Turbo ? window.Turbo.visit(url) : (window.location.href = url)
|
|
812
803
|
}
|
|
813
804
|
}
|
|
814
805
|
|
|
@@ -848,11 +839,20 @@ export default class extends Controller {
|
|
|
848
839
|
const cells = table.querySelectorAll(`th[data-column-name="${escaped}"], td[data-column-name="${escaped}"]`)
|
|
849
840
|
|
|
850
841
|
cells.forEach(cell => {
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
842
|
+
// Remember how the server rendered the cell (action columns have width/min-width but no max-width)
|
|
843
|
+
if (cell.dataset.defaultWidth === undefined) {
|
|
844
|
+
cell.dataset.defaultWidth = cell.style.width
|
|
845
|
+
cell.dataset.defaultMaxWidth = cell.style.maxWidth
|
|
846
|
+
cell.dataset.defaultMinWidth = cell.style.minWidth
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
if (width === null) {
|
|
850
|
+
cell.style.width = cell.dataset.defaultWidth
|
|
851
|
+
cell.style.maxWidth = cell.dataset.defaultMaxWidth
|
|
852
|
+
cell.style.minWidth = cell.dataset.defaultMinWidth
|
|
853
|
+
} else {
|
|
854
|
+
cell.style.width = cell.style.maxWidth = cell.style.minWidth = `${width}px`
|
|
855
|
+
}
|
|
856
856
|
})
|
|
857
857
|
}
|
|
858
858
|
|
|
@@ -957,6 +957,12 @@ export default class extends Controller {
|
|
|
957
957
|
}
|
|
958
958
|
|
|
959
959
|
// Apply column pinning (sticky positioning) from localStorage
|
|
960
|
+
// Small pushpin before a pinned column's label, tilted toward the side it is pinned to
|
|
961
|
+
addPinIcon(header, side) {
|
|
962
|
+
const tilt = side === "left" ? "-rotate-45" : "rotate-45"
|
|
963
|
+
header.insertAdjacentHTML("afterbegin", `<svg data-pin-icon aria-hidden="true" class="inline-block w-3 h-3 mr-1 -mt-0.5 text-indigo-500 dark:text-indigo-400 ${tilt}" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 24 24"><path d="M12 17v5"/><path d="M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z"/></svg>`)
|
|
964
|
+
}
|
|
965
|
+
|
|
960
966
|
applyColumnPinning() {
|
|
961
967
|
const tableName = this.nameValue
|
|
962
968
|
const pinnedKey = `infotable_column_pinned_${tableName}`
|
|
@@ -1002,6 +1008,7 @@ export default class extends Controller {
|
|
|
1002
1008
|
// First pass: reset all columns
|
|
1003
1009
|
headers.forEach(header => {
|
|
1004
1010
|
header.style.position = ''
|
|
1011
|
+
header.style.top = ''
|
|
1005
1012
|
header.style.left = ''
|
|
1006
1013
|
header.style.right = ''
|
|
1007
1014
|
header.style.zIndex = ''
|
|
@@ -1015,6 +1022,7 @@ export default class extends Controller {
|
|
|
1015
1022
|
header.style.removeProperty('opacity')
|
|
1016
1023
|
header.style.backgroundClip = ''
|
|
1017
1024
|
header.style.boxShadow = ''
|
|
1025
|
+
header.querySelectorAll('[data-pin-icon]').forEach(icon => icon.remove())
|
|
1018
1026
|
header.classList.remove('infotable-pinned-left', 'infotable-pinned-right', '!bg-gray-50', 'dark:!bg-gray-800', "after:content-['']", "after:absolute", "after:top-0", "after:right-0", "after:bottom-0", "after:w-5", "after:pointer-events-none", "after:bg-gradient-to-r", "after:from-transparent", "after:to-black/[0.04]", "after:z-[1]", "before:content-['']", "before:absolute", "before:top-0", "before:left-0", "before:bottom-0", "before:w-5", "before:pointer-events-none", "before:bg-gradient-to-l", "before:from-transparent", "before:to-black/[0.04]", "before:z-[1]")
|
|
1019
1027
|
})
|
|
1020
1028
|
|
|
@@ -1035,7 +1043,7 @@ export default class extends Controller {
|
|
|
1035
1043
|
cell.style.removeProperty('opacity')
|
|
1036
1044
|
cell.style.backgroundClip = ''
|
|
1037
1045
|
cell.style.boxShadow = ''
|
|
1038
|
-
cell.classList.remove('infotable-pinned-left', 'infotable-pinned-right', '!bg-white', 'dark:!bg-gray-900', "after:content-['']", "after:absolute", "after:top-0", "after:right-0", "after:bottom-0", "after:w-5", "after:pointer-events-none", "after:bg-gradient-to-r", "after:from-transparent", "after:to-black/[0.04]", "after:z-[1]", "before:content-['']", "before:absolute", "before:top-0", "before:left-0", "before:bottom-0", "before:w-5", "before:pointer-events-none", "before:bg-gradient-to-l", "before:from-transparent", "before:to-black/[0.04]", "before:z-[1]")
|
|
1046
|
+
cell.classList.remove('infotable-pinned-left', 'infotable-pinned-right', '!bg-white', 'dark:!bg-gray-900', 'group-hover:!bg-gray-50', 'dark:group-hover:!bg-gray-800', "after:content-['']", "after:absolute", "after:top-0", "after:right-0", "after:bottom-0", "after:w-5", "after:pointer-events-none", "after:bg-gradient-to-r", "after:from-transparent", "after:to-black/[0.04]", "after:z-[1]", "before:content-['']", "before:absolute", "before:top-0", "before:left-0", "before:bottom-0", "before:w-5", "before:pointer-events-none", "before:bg-gradient-to-l", "before:from-transparent", "before:to-black/[0.04]", "before:z-[1]")
|
|
1039
1047
|
})
|
|
1040
1048
|
})
|
|
1041
1049
|
|
|
@@ -1069,13 +1077,6 @@ export default class extends Controller {
|
|
|
1069
1077
|
top: 0px !important;
|
|
1070
1078
|
left: ${leftOffset}px !important;
|
|
1071
1079
|
z-index: 30 !important;
|
|
1072
|
-
background: #f9fafb !important;
|
|
1073
|
-
background-color: #f9fafb !important;
|
|
1074
|
-
background-image: none !important;
|
|
1075
|
-
background-position: initial !important;
|
|
1076
|
-
background-size: initial !important;
|
|
1077
|
-
background-repeat: initial !important;
|
|
1078
|
-
background-attachment: initial !important;
|
|
1079
1080
|
opacity: 1 !important;
|
|
1080
1081
|
background-clip: padding-box !important;
|
|
1081
1082
|
box-shadow: 2px 0 4px -2px rgba(0, 0, 0, 0.1) !important;
|
|
@@ -1085,6 +1086,7 @@ export default class extends Controller {
|
|
|
1085
1086
|
// Set all styles at once via setAttribute (most aggressive method)
|
|
1086
1087
|
header.setAttribute('style', newStyles)
|
|
1087
1088
|
header.classList.add('infotable-pinned-left', '!bg-gray-50', 'dark:!bg-gray-800')
|
|
1089
|
+
this.addPinIcon(header, 'left')
|
|
1088
1090
|
|
|
1089
1091
|
// Mark last left-pinned column
|
|
1090
1092
|
if (columnName === lastLeftPinned) {
|
|
@@ -1103,13 +1105,6 @@ export default class extends Controller {
|
|
|
1103
1105
|
position: sticky !important;
|
|
1104
1106
|
left: ${leftOffset}px !important;
|
|
1105
1107
|
z-index: 15 !important;
|
|
1106
|
-
background: #ffffff !important;
|
|
1107
|
-
background-color: #ffffff !important;
|
|
1108
|
-
background-image: none !important;
|
|
1109
|
-
background-position: initial !important;
|
|
1110
|
-
background-size: initial !important;
|
|
1111
|
-
background-repeat: initial !important;
|
|
1112
|
-
background-attachment: initial !important;
|
|
1113
1108
|
opacity: 1 !important;
|
|
1114
1109
|
background-clip: padding-box !important;
|
|
1115
1110
|
box-shadow: 2px 0 4px -2px rgba(0, 0, 0, 0.1) !important;
|
|
@@ -1117,7 +1112,7 @@ export default class extends Controller {
|
|
|
1117
1112
|
`.replace(/\s+/g, ' ').trim()
|
|
1118
1113
|
|
|
1119
1114
|
cell.setAttribute('style', newStyles)
|
|
1120
|
-
cell.classList.add('infotable-pinned-left', '!bg-white', 'dark:!bg-gray-900')
|
|
1115
|
+
cell.classList.add('infotable-pinned-left', '!bg-white', 'dark:!bg-gray-900', 'group-hover:!bg-gray-50', 'dark:group-hover:!bg-gray-800')
|
|
1121
1116
|
|
|
1122
1117
|
if (columnName === lastLeftPinned) {
|
|
1123
1118
|
cell.classList.add("after:content-['']", "after:absolute", "after:top-0", "after:right-0", "after:bottom-0", "after:w-5", "after:pointer-events-none", "after:bg-gradient-to-r", "after:from-transparent", "after:to-black/[0.04]", "after:z-[1]")
|
|
@@ -1136,13 +1131,6 @@ export default class extends Controller {
|
|
|
1136
1131
|
top: 0px !important;
|
|
1137
1132
|
right: ${rightOffset}px !important;
|
|
1138
1133
|
z-index: 30 !important;
|
|
1139
|
-
background: #f9fafb !important;
|
|
1140
|
-
background-color: #f9fafb !important;
|
|
1141
|
-
background-image: none !important;
|
|
1142
|
-
background-position: initial !important;
|
|
1143
|
-
background-size: initial !important;
|
|
1144
|
-
background-repeat: initial !important;
|
|
1145
|
-
background-attachment: initial !important;
|
|
1146
1134
|
opacity: 1 !important;
|
|
1147
1135
|
background-clip: padding-box !important;
|
|
1148
1136
|
box-shadow: -2px 0 4px -2px rgba(0, 0, 0, 0.1) !important;
|
|
@@ -1151,6 +1139,7 @@ export default class extends Controller {
|
|
|
1151
1139
|
|
|
1152
1140
|
header.setAttribute('style', newStyles)
|
|
1153
1141
|
header.classList.add('infotable-pinned-right', '!bg-gray-50', 'dark:!bg-gray-800')
|
|
1142
|
+
this.addPinIcon(header, 'right')
|
|
1154
1143
|
|
|
1155
1144
|
// Mark first right-pinned column
|
|
1156
1145
|
if (columnName === firstRightPinned) {
|
|
@@ -1169,13 +1158,6 @@ export default class extends Controller {
|
|
|
1169
1158
|
position: sticky !important;
|
|
1170
1159
|
right: ${rightOffset}px !important;
|
|
1171
1160
|
z-index: 15 !important;
|
|
1172
|
-
background: #ffffff !important;
|
|
1173
|
-
background-color: #ffffff !important;
|
|
1174
|
-
background-image: none !important;
|
|
1175
|
-
background-position: initial !important;
|
|
1176
|
-
background-size: initial !important;
|
|
1177
|
-
background-repeat: initial !important;
|
|
1178
|
-
background-attachment: initial !important;
|
|
1179
1161
|
opacity: 1 !important;
|
|
1180
1162
|
background-clip: padding-box !important;
|
|
1181
1163
|
box-shadow: -2px 0 4px -2px rgba(0, 0, 0, 0.1) !important;
|
|
@@ -1183,7 +1165,7 @@ export default class extends Controller {
|
|
|
1183
1165
|
`.replace(/\s+/g, ' ').trim()
|
|
1184
1166
|
|
|
1185
1167
|
cell.setAttribute('style', newStyles)
|
|
1186
|
-
cell.classList.add('infotable-pinned-right', '!bg-white', 'dark:!bg-gray-900')
|
|
1168
|
+
cell.classList.add('infotable-pinned-right', '!bg-white', 'dark:!bg-gray-900', 'group-hover:!bg-gray-50', 'dark:group-hover:!bg-gray-800')
|
|
1187
1169
|
|
|
1188
1170
|
if (columnName === firstRightPinned) {
|
|
1189
1171
|
cell.classList.add("before:content-['']", "before:absolute", "before:top-0", "before:left-0", "before:bottom-0", "before:w-5", "before:pointer-events-none", "before:bg-gradient-to-l", "before:from-transparent", "before:to-black/[0.04]", "before:z-[1]")
|