-
diff --git a/src/Components/style.css b/src/Components/style.css
index a72e677..0cbdcb3 100644
--- a/src/Components/style.css
+++ b/src/Components/style.css
@@ -8,16 +8,23 @@
touch-action: none;
}
+/* prevent native mobile long-press text selection on draggable elements */
+[data-flexitable-root] [data-id] {
+ -webkit-user-select: none;
+ user-select: none;
+ -webkit-touch-callout: none;
+}
+
/* structural reset: targets only the library's own elements,
never bleeds into consumer cell content */
[data-flexitable-root],
-[data-flexitable-root] .table,
-[data-flexitable-root] .header,
-[data-flexitable-root] .thead,
-[data-flexitable-root] .body,
-[data-flexitable-root] .ibody,
-[data-flexitable-root] .draggable,
-[data-flexitable-root] .tr {
+[data-flexitable-root] [data-rtdnd='table'],
+[data-flexitable-root] [data-rtdnd='header'],
+[data-flexitable-root] [data-rtdnd='thead'],
+[data-flexitable-root] [data-rtdnd='body'],
+[data-flexitable-root] [data-rtdnd='ibody'],
+[data-flexitable-root] [data-rtdnd='draggable'],
+[data-flexitable-root] [data-rtdnd='tr'] {
box-sizing: border-box;
margin: 0;
padding: 0;
@@ -29,8 +36,8 @@
/* user-facing cells: box-sizing only — padding/margin intentionally left
unset so consumers can style freely via className and style props */
-[data-flexitable-root] .th,
-[data-flexitable-root] .td {
+[data-flexitable-root] [data-rtdnd='th'],
+[data-flexitable-root] [data-rtdnd='td'] {
box-sizing: border-box;
}
@@ -45,17 +52,17 @@
}
/* hide webkit scrollbar on header scroll container (scrollLeft synced via JS) */
-[data-flexitable-root] .thead::-webkit-scrollbar {
+[data-flexitable-root] [data-rtdnd='thead']::-webkit-scrollbar {
display: none;
}
/* hide webkit scrollbar on virtual column drag body strip */
-[data-flexitable-root] .clone-body-strip::-webkit-scrollbar {
+[data-flexitable-root] [data-rtdnd='clone-body-strip']::-webkit-scrollbar {
display: none;
}
/* drag handle: only the handle shows grab cursor when not actively dragging */
-[data-flexitable-root]:not(.is-dragging) .draggable:has([data-drag-handle]) > div {
+[data-flexitable-root]:not(.is-dragging) [data-rtdnd='draggable']:has([data-drag-handle]) > div {
cursor: default !important;
}
diff --git a/src/hooks/useDragContextEvents.tsx b/src/hooks/useDragContextEvents.tsx
index 1014316..33651b3 100644
--- a/src/hooks/useDragContextEvents.tsx
+++ b/src/hooks/useDragContextEvents.tsx
@@ -160,7 +160,7 @@ const useDragContextEvents = (
const idx = String(sourceIndex)
// Header: clone just the .th element — mirrors React.cloneElement(children) from Draggable
- const thEl = draggableEl.querySelector('.th')
+ const thEl = draggableEl.querySelector('[data-rtdnd="th"]')
if (thEl) {
const headerWrapper = document.createElement('div')
headerWrapper.style.flexShrink = '0'
@@ -174,7 +174,7 @@ const useDragContextEvents = (
bodyWrapper.style.flex = '1'
const inner = document.createElement('div')
- inner.className = 'rbody'
+ inner.dataset.rtdnd = 'rbody'
inner.style.height = `${body.scrollHeight}px`
inner.style.position = 'relative'
@@ -183,7 +183,7 @@ const useDragContextEvents = (
if (isVirtualRef.current) {
// Virtual rows have spacer divs alongside cells. Strip .tr down to just
// the target cell so the column strip shows correctly at offset 0.
- const trEl = rowClone.querySelector('.tr')
+ const trEl = rowClone.querySelector('[data-rtdnd="tr"]')
if (trEl) {
const targetCell = trEl.querySelector(`[data-col-index="${idx}"]`)
while (trEl.firstChild) trEl.removeChild(trEl.firstChild)
@@ -204,7 +204,7 @@ const useDragContextEvents = (
// The 'clone-body-strip' class hides scrollbar in WebKit via style.css
bodyWrapper.style.overflow = 'auto'
bodyWrapper.style.scrollbarWidth = 'none'
- bodyWrapper.className = 'clone-body-strip'
+ bodyWrapper.dataset.rtdnd = 'clone-body-strip'
} else {
bodyWrapper.style.overflow = 'hidden'
}
diff --git a/src/hooks/useDropTarget.ts b/src/hooks/useDropTarget.ts
index 283cccf..3825f68 100644
--- a/src/hooks/useDropTarget.ts
+++ b/src/hooks/useDropTarget.ts
@@ -30,7 +30,7 @@ const useDropTarget = (refs: HookRefs, options: Options): DropTargetResult => {
const scrollTop = body.scrollTop
const topOffset = body.getBoundingClientRect().top
- const elements = body.querySelectorAll('.draggable[data-type="row"]')
+ const elements = body.querySelectorAll('[data-rtdnd="draggable"][data-type="row"]')
let items: RowItem[] = []
for (let i = 0; i < elements.length; i++) {
const el = elements[i] as HTMLElement
diff --git a/src/hooks/useIndexMaps.ts b/src/hooks/useIndexMaps.ts
index 2d9420d..5d6679c 100644
--- a/src/hooks/useIndexMaps.ts
+++ b/src/hooks/useIndexMaps.ts
@@ -29,7 +29,7 @@ const useIndexMaps = (refs: HookRefs): IndexMapsResult => {
const buildRowMap = useCallback((body: HTMLElement) => {
rowIndexMapRef.current.clear()
- const rows = body.querySelectorAll('.draggable[data-type="row"]')
+ const rows = body.querySelectorAll('[data-rtdnd="draggable"][data-type="row"]')
for (let i = 0; i < rows.length; i++) {
const el = rows[i] as HTMLElement
const idx = el.dataset.index
@@ -41,7 +41,7 @@ const useIndexMaps = (refs: HookRefs): IndexMapsResult => {
const buildColumnMap = useCallback((header: HTMLElement) => {
colIndexMapRef.current.clear()
- const cols = header.querySelectorAll('.draggable[data-type="column"]')
+ const cols = header.querySelectorAll('[data-rtdnd="draggable"][data-type="column"]')
for (let i = 0; i < cols.length; i++) {
const el = cols[i] as HTMLElement
const idx = el.dataset.index
@@ -53,7 +53,7 @@ const useIndexMaps = (refs: HookRefs): IndexMapsResult => {
const buildCellMap = useCallback((body: HTMLElement) => {
cellIndexMapRef.current.clear()
- const cells = body.querySelectorAll('.td[data-col-index]')
+ const cells = body.querySelectorAll('[data-rtdnd="td"][data-col-index]')
for (let i = 0; i < cells.length; i++) {
const cell = cells[i] as HTMLElement
const idx = +cell.dataset.colIndex!
diff --git a/vite.config.docs.ts b/vite.config.docs.ts
index cef089b..f905294 100644
--- a/vite.config.docs.ts
+++ b/vite.config.docs.ts
@@ -1,8 +1,12 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
+import pkg from './package.json' with { type: 'json' }
export default defineConfig({
plugins: [react()],
+ define: {
+ __LIB_VERSION__: JSON.stringify(pkg.version),
+ },
base: './',
build: {
outDir: 'docs-dist',