From fe05211ad88daef7c671457fd02389b9cf3b8acc Mon Sep 17 00:00:00 2001 From: amahajan Date: Tue, 7 Oct 2025 09:26:04 -0500 Subject: [PATCH] Remove `clsx` dependency --- README.md | 2 +- package.json | 4 +--- src/DataGrid.tsx | 11 +++++++---- src/GroupRow.tsx | 5 ++--- src/GroupedColumnHeaderCell.tsx | 6 ++---- src/HeaderRow.tsx | 5 ++--- src/Row.tsx | 5 ++--- src/SummaryRow.tsx | 5 ++--- src/utils/styleUtils.ts | 29 +++++++++++++++++++++++++---- 9 files changed, 44 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index af2fe41d01..bde3617286 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ The DataGrid component is designed to handle large datasets efficiently while of - [React 19.2+](package.json) support - Evergreen browsers and server-side rendering support -- Tree-shaking support and only [one npm dependency](package.json) to keep your bundles slim +- Tree-shaking support with no external dependencies to keep your bundles slim - Great performance thanks to virtualization: columns and rows outside the viewport are not rendered - Strictly typed with TypeScript - [Keyboard accessibility](https://comcast.github.io/react-data-grid/#/CommonFeatures) diff --git a/package.json b/package.json index b26c99cd33..2600121513 100644 --- a/package.json +++ b/package.json @@ -48,9 +48,6 @@ "prepublishOnly": "npm install && node --run build", "postpublish": "git push --follow-tags origin HEAD" }, - "dependencies": { - "clsx": "^2.0.0" - }, "devDependencies": { "@babel/preset-typescript": "^7.27.1", "@biomejs/biome": "2.2.5", @@ -72,6 +69,7 @@ "@vitest/eslint-plugin": "^1.3.4", "@wyw-in-js/rollup": "^0.7.0", "@wyw-in-js/vite": "^0.7.0", + "clsx": "^2.1.1", "eslint": "^9.36.0", "eslint-plugin-jest-dom": "^5.5.0", "eslint-plugin-react": "^7.37.5", diff --git a/src/DataGrid.tsx b/src/DataGrid.tsx index 18f99cf024..27d34b0ab7 100644 --- a/src/DataGrid.tsx +++ b/src/DataGrid.tsx @@ -8,7 +8,6 @@ import { } from 'react'; import type { Key, KeyboardEvent } from 'react'; import { flushSync } from 'react-dom'; -import clsx from 'clsx'; import { HeaderRowSelectionChangeContext, @@ -26,6 +25,7 @@ import { abs, assertIsValidKeyGetter, canExitGrid, + classnames, createCellEvent, getCellStyle, getColSpan, @@ -991,7 +991,10 @@ export function DataGrid(props: DataGridPr return (
(props: DataGridPr // Scrollable containers without tabIndex are keyboard focusable in Chrome only if there is no focusable element inside // whereas they are always focusable in Firefox. We need to set tabIndex to have a consistent behavior across browsers. tabIndex={-1} - className={clsx( + className={classnames( rootClassname, { [viewportDraggingClassname]: isDragging @@ -1329,7 +1332,7 @@ export function DataGrid(props: DataGridPr
({ aria-setsize={row.setSize} aria-posinset={row.posInSet + 1} // aria-posinset is 1-based aria-expanded={row.isExpanded} - className={clsx( + className={classnames( rowClassname, groupRowClassname, `rdg-row-${rowIdx % 2 === 0 ? 'even' : 'odd'}`, diff --git a/src/GroupedColumnHeaderCell.tsx b/src/GroupedColumnHeaderCell.tsx index cc0b3ce761..7f3b4182d5 100644 --- a/src/GroupedColumnHeaderCell.tsx +++ b/src/GroupedColumnHeaderCell.tsx @@ -1,7 +1,5 @@ -import clsx from 'clsx'; - import { useRovingTabIndex } from './hooks'; -import { getHeaderCellRowSpan, getHeaderCellStyle } from './utils'; +import { classnames, getHeaderCellRowSpan, getHeaderCellStyle } from './utils'; import type { CalculatedColumnParent } from './types'; import type { GroupedColumnHeaderRowProps } from './GroupedColumnHeaderRow'; import { cellClassname } from './style/cell'; @@ -39,7 +37,7 @@ export default function GroupedColumnHeaderCell({ aria-rowspan={rowSpan} aria-selected={isCellSelected} tabIndex={tabIndex} - className={clsx(cellClassname, column.headerCellClass)} + className={classnames(cellClassname, column.headerCellClass)} style={{ ...getHeaderCellStyle(column, rowIdx, rowSpan), gridColumnStart: index, diff --git a/src/HeaderRow.tsx b/src/HeaderRow.tsx index 20f532bc1d..dee50b215b 100644 --- a/src/HeaderRow.tsx +++ b/src/HeaderRow.tsx @@ -1,8 +1,7 @@ import { memo, useState } from 'react'; import { css } from '@linaria/core'; -import clsx from 'clsx'; -import { getColSpan } from './utils'; +import { classnames, getColSpan } from './utils'; import type { CalculatedColumn, Direction, Maybe, Position, ResizedWidth } from './types'; import type { DataGridProps } from './DataGrid'; import HeaderCell from './HeaderCell'; @@ -97,7 +96,7 @@ function HeaderRow({
({ onRowChange(column, rowIdx, newRow); }); - className = clsx( + className = classnames( rowClassname, `rdg-row-${rowIdx % 2 === 0 ? 'even' : 'odd'}`, { diff --git a/src/SummaryRow.tsx b/src/SummaryRow.tsx index 8b71936603..67d9ef1ada 100644 --- a/src/SummaryRow.tsx +++ b/src/SummaryRow.tsx @@ -1,8 +1,7 @@ import { memo } from 'react'; import { css } from '@linaria/core'; -import clsx from 'clsx'; -import { getColSpan, getRowStyle } from './utils'; +import { classnames, getColSpan, getRowStyle } from './utils'; import type { RenderRowProps } from './types'; import { cell, cellFrozen } from './style/cell'; import { @@ -90,7 +89,7 @@ function SummaryRow({
( }; } +type ClassValue = Maybe | Record | false; + +export function classnames(...args: readonly ClassValue[]) { + let classname = ''; + + for (const arg of args) { + if (arg) { + if (typeof arg === 'string') { + classname += ` ${arg}`; + } else if (typeof arg === 'object') { + for (const key in arg) { + if (arg[key]) { + classname += ` ${key}`; + } + } + } + } + } + + return classname.trimStart(); +} + export function getCellClassname( column: CalculatedColumn, - ...extraClasses: Parameters + ...extraClasses: readonly ClassValue[] ): string { - return clsx( + return classnames( cellClassname, { [cellFrozenClassname]: column.frozen