@equinor/eds-data-grid-react 0.8.0 → 0.9.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.
@@ -304,6 +304,12 @@ function TableHeaderCell({
304
304
  }
305
305
  return pinned === 'left' ? header.getStart() : table.getTotalSize() - header.getStart() - header.getSize();
306
306
  }, [pinned, header, table]);
307
+ const {
308
+ density
309
+ } = edsCoreReact.useEds();
310
+ // Future improvement: If we down the line end up granting the ability to customize row height, we should move this to the table-context
311
+ const rowHeight = density === 'compact' ? 32 : 48;
312
+ const vertOffset = ctx.stickyHeader ? (header.depth - 1) * rowHeight : undefined;
307
313
  const tableCellPadding = react.useMemo(() => {
308
314
  if (canSort && canFilter) {
309
315
  return '0 var(--eds_table__cell__padding_x, 16px) 0 0';
@@ -319,7 +325,8 @@ function TableHeaderCell({
319
325
  $pinned: pinned,
320
326
  className: ctx.headerClass ? ctx.headerClass(header.column) : '',
321
327
  style: {
322
- ...(ctx.headerStyle ? ctx.headerStyle(header.column) : {})
328
+ ...(ctx.headerStyle ? ctx.headerStyle(header.column) : {}),
329
+ top: vertOffset
323
330
  },
324
331
  "aria-hidden": true
325
332
  }) : /*#__PURE__*/jsxRuntime.jsxs(TableCell, {
@@ -334,7 +341,8 @@ function TableHeaderCell({
334
341
  width: header.getSize(),
335
342
  verticalAlign: ctx.enableColumnFiltering ? 'top' : 'middle',
336
343
  ...(ctx.headerStyle ? ctx.headerStyle(header.column) : {}),
337
- padding: tableCellPadding
344
+ padding: tableCellPadding,
345
+ top: vertOffset
338
346
  },
339
347
  children: [canSort ? /*#__PURE__*/jsxRuntime.jsxs(SortButton, {
340
348
  tabIndex: -1,
@@ -505,13 +513,18 @@ function TableRow({
505
513
  onCellClick,
506
514
  onClick,
507
515
  onDoubleClick,
508
- onContextMenu
516
+ onContextMenu,
517
+ rowVirtualizer,
518
+ virtualItem
509
519
  }) {
510
520
  const {
511
521
  rowClass,
512
522
  rowStyle
513
523
  } = useTableContext();
514
524
  return /*#__PURE__*/jsxRuntime.jsx(StyledTableRow, {
525
+ "data-index": virtualItem?.index,
526
+ ref: node => node && rowVirtualizer?.measureElement(node) //measure dynamic row height
527
+ ,
515
528
  style: {
516
529
  ...(rowStyle?.(row) ?? {})
517
530
  },
@@ -570,6 +583,12 @@ function logDevelopmentWarningOfPropUse(deprecatedProps) {
570
583
  }
571
584
  }
572
585
  }
586
+ const isFirefox = () => {
587
+ return typeof window !== 'undefined' && navigator.userAgent.indexOf('Firefox') !== -1;
588
+ };
589
+ const getMeasureElementHandler = () => {
590
+ return isFirefox() ? undefined : element => element?.getBoundingClientRect().height;
591
+ };
573
592
 
574
593
  /* eslint-disable @typescript-eslint/no-non-null-assertion */
575
594
  function EdsDataGridInner({
@@ -882,7 +901,9 @@ function EdsDataGridInner({
882
901
  const virtualizer = reactVirtual.useVirtualizer({
883
902
  count: table.getRowModel().rows.length,
884
903
  getScrollElement: () => parentRef.current,
885
- estimateSize
904
+ estimateSize,
905
+ //measure dynamic row height, except in firefox because it measures table border height incorrectly
906
+ measureElement: getMeasureElementHandler()
886
907
  });
887
908
  if (rowVirtualizerInstanceRef) rowVirtualizerInstanceRef.current = virtualizer;
888
909
 
@@ -939,7 +960,6 @@ function EdsDataGridInner({
939
960
  children: [caption && /*#__PURE__*/jsxRuntime.jsx(edsCoreReact.Table.Caption, {
940
961
  children: caption
941
962
  }), /*#__PURE__*/jsxRuntime.jsx(edsCoreReact.Table.Head, {
942
- sticky: stickyHeader,
943
963
  children: table.getHeaderGroups().map(headerGroup => /*#__PURE__*/jsxRuntime.jsx(TableHeaderRow, {
944
964
  table: table,
945
965
  headerGroup: headerGroup,
@@ -970,6 +990,8 @@ function EdsDataGridInner({
970
990
  }), virtualRows.map(virtualItem => {
971
991
  const row = table.getRowModel().rows[virtualItem.index];
972
992
  return /*#__PURE__*/jsxRuntime.jsx(TableRow, {
993
+ virtualItem: virtualItem,
994
+ rowVirtualizer: virtualizer,
973
995
  row: row,
974
996
  onContextMenu: onRowContextMenu ? event => onRowContextMenu(row, event) : undefined,
975
997
  onClick: onRowClick ? event => onRowClick(row, event) : undefined,
@@ -7,7 +7,7 @@ import { TableProvider } from './EdsDataGridContext.js';
7
7
  import { TableHeaderRow } from './components/TableHeaderRow.js';
8
8
  import { TableFooterRow } from './components/TableFooterRow.js';
9
9
  import { TableRow } from './components/TableRow.js';
10
- import { addPxSuffixIfInputHasNoPrefix, logDevelopmentWarningOfPropUse } from './utils.js';
10
+ import { addPxSuffixIfInputHasNoPrefix, logDevelopmentWarningOfPropUse, getMeasureElementHandler } from './utils.js';
11
11
  import { mergeRefs } from '@equinor/eds-utils';
12
12
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
13
13
 
@@ -322,7 +322,9 @@ function EdsDataGridInner({
322
322
  const virtualizer = useVirtualizer({
323
323
  count: table.getRowModel().rows.length,
324
324
  getScrollElement: () => parentRef.current,
325
- estimateSize
325
+ estimateSize,
326
+ //measure dynamic row height, except in firefox because it measures table border height incorrectly
327
+ measureElement: getMeasureElementHandler()
326
328
  });
327
329
  if (rowVirtualizerInstanceRef) rowVirtualizerInstanceRef.current = virtualizer;
328
330
 
@@ -379,7 +381,6 @@ function EdsDataGridInner({
379
381
  children: [caption && /*#__PURE__*/jsx(Table.Caption, {
380
382
  children: caption
381
383
  }), /*#__PURE__*/jsx(Table.Head, {
382
- sticky: stickyHeader,
383
384
  children: table.getHeaderGroups().map(headerGroup => /*#__PURE__*/jsx(TableHeaderRow, {
384
385
  table: table,
385
386
  headerGroup: headerGroup,
@@ -410,6 +411,8 @@ function EdsDataGridInner({
410
411
  }), virtualRows.map(virtualItem => {
411
412
  const row = table.getRowModel().rows[virtualItem.index];
412
413
  return /*#__PURE__*/jsx(TableRow, {
414
+ virtualItem: virtualItem,
415
+ rowVirtualizer: virtualizer,
413
416
  row: row,
414
417
  onContextMenu: onRowContextMenu ? event => onRowContextMenu(row, event) : undefined,
415
418
  onClick: onRowClick ? event => onRowClick(row, event) : undefined,
@@ -6,6 +6,7 @@ import { SortIndicator } from './SortIndicator.js';
6
6
  import { Resizer, ResizeInner } from './Resizer.js';
7
7
  import { TableCell, FilterVisibility } from './TableCell.js';
8
8
  import styled from 'styled-components';
9
+ import { useEds } from '@equinor/eds-core-react';
9
10
  import { jsx, jsxs } from 'react/jsx-runtime';
10
11
 
11
12
  const SortButton = styled.button.withConfig({
@@ -46,6 +47,12 @@ function TableHeaderCell({
46
47
  }
47
48
  return pinned === 'left' ? header.getStart() : table.getTotalSize() - header.getStart() - header.getSize();
48
49
  }, [pinned, header, table]);
50
+ const {
51
+ density
52
+ } = useEds();
53
+ // Future improvement: If we down the line end up granting the ability to customize row height, we should move this to the table-context
54
+ const rowHeight = density === 'compact' ? 32 : 48;
55
+ const vertOffset = ctx.stickyHeader ? (header.depth - 1) * rowHeight : undefined;
49
56
  const tableCellPadding = useMemo(() => {
50
57
  if (canSort && canFilter) {
51
58
  return '0 var(--eds_table__cell__padding_x, 16px) 0 0';
@@ -61,7 +68,8 @@ function TableHeaderCell({
61
68
  $pinned: pinned,
62
69
  className: ctx.headerClass ? ctx.headerClass(header.column) : '',
63
70
  style: {
64
- ...(ctx.headerStyle ? ctx.headerStyle(header.column) : {})
71
+ ...(ctx.headerStyle ? ctx.headerStyle(header.column) : {}),
72
+ top: vertOffset
65
73
  },
66
74
  "aria-hidden": true
67
75
  }) : /*#__PURE__*/jsxs(TableCell, {
@@ -76,7 +84,8 @@ function TableHeaderCell({
76
84
  width: header.getSize(),
77
85
  verticalAlign: ctx.enableColumnFiltering ? 'top' : 'middle',
78
86
  ...(ctx.headerStyle ? ctx.headerStyle(header.column) : {}),
79
- padding: tableCellPadding
87
+ padding: tableCellPadding,
88
+ top: vertOffset
80
89
  },
81
90
  children: [canSort ? /*#__PURE__*/jsxs(SortButton, {
82
91
  tabIndex: -1,
@@ -9,13 +9,18 @@ function TableRow({
9
9
  onCellClick,
10
10
  onClick,
11
11
  onDoubleClick,
12
- onContextMenu
12
+ onContextMenu,
13
+ rowVirtualizer,
14
+ virtualItem
13
15
  }) {
14
16
  const {
15
17
  rowClass,
16
18
  rowStyle
17
19
  } = useTableContext();
18
20
  return /*#__PURE__*/jsx(StyledTableRow, {
21
+ "data-index": virtualItem?.index,
22
+ ref: node => node && rowVirtualizer?.measureElement(node) //measure dynamic row height
23
+ ,
19
24
  style: {
20
25
  ...(rowStyle?.(row) ?? {})
21
26
  },
package/dist/esm/utils.js CHANGED
@@ -36,5 +36,11 @@ function logDevelopmentWarningOfPropUse(deprecatedProps) {
36
36
  }
37
37
  }
38
38
  }
39
+ const isFirefox = () => {
40
+ return typeof window !== 'undefined' && navigator.userAgent.indexOf('Firefox') !== -1;
41
+ };
42
+ const getMeasureElementHandler = () => {
43
+ return isFirefox() ? undefined : element => element?.getBoundingClientRect().height;
44
+ };
39
45
 
40
- export { addPxSuffixIfInputHasNoPrefix, isNumberOnlyString, logDevelopmentWarningOfPropUse };
46
+ export { addPxSuffixIfInputHasNoPrefix, getMeasureElementHandler, isFirefox, isNumberOnlyString, logDevelopmentWarningOfPropUse };
@@ -0,0 +1,12 @@
1
+ import React, { ButtonHTMLAttributes } from 'react';
2
+ export type ClickableCellProps = {
3
+ /** Cell content */
4
+ children: React.ReactNode;
5
+ /** Click handler */
6
+ onClick: () => void;
7
+ /** Accessible label for screen readers */
8
+ ariaLabel: string;
9
+ /** Indicates if the cell is selected */
10
+ isSelected?: boolean;
11
+ } & Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onClick' | 'children'>;
12
+ export declare function ClickableCell({ children, onClick, ariaLabel, isSelected, ...rest }: ClickableCellProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import type { ComponentToken } from '@equinor/eds-tokens';
2
+ export type ClickableCellToken = ComponentToken;
3
+ export declare const clickableCell: ClickableCellToken;
@@ -0,0 +1 @@
1
+ export { ClickableCell, type ClickableCellProps } from './ClickableCell';
@@ -1,9 +1,12 @@
1
1
  import { Row } from '@tanstack/react-table';
2
2
  import { HTMLAttributes } from 'react';
3
3
  import { EdsDataGridProps } from '../EdsDataGridProps';
4
+ import { VirtualItem, Virtualizer } from '@tanstack/react-virtual';
4
5
  type Props<T> = {
5
6
  row: Row<T>;
6
7
  onCellClick?: EdsDataGridProps<T>['onCellClick'];
8
+ rowVirtualizer?: Virtualizer<HTMLDivElement, HTMLTableRowElement>;
9
+ virtualItem?: VirtualItem;
7
10
  } & HTMLAttributes<HTMLTableRowElement>;
8
- export declare function TableRow<T>({ row, onCellClick, onClick, onDoubleClick, onContextMenu, }: Props<T>): import("react/jsx-runtime").JSX.Element;
11
+ export declare function TableRow<T>({ row, onCellClick, onClick, onDoubleClick, onContextMenu, rowVirtualizer, virtualItem, }: Props<T>): import("react/jsx-runtime").JSX.Element;
9
12
  export {};
@@ -20,3 +20,5 @@ export declare function logDevelopmentWarningOfPropUse(deprecatedProps: Record<s
20
20
  value: unknown;
21
21
  mitigationInfo?: string;
22
22
  }>): void;
23
+ export declare const isFirefox: () => boolean;
24
+ export declare const getMeasureElementHandler: () => (element: HTMLTableRowElement) => number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@equinor/eds-data-grid-react",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "A feature-rich data-grid written in React, implementing the Equinor Design System",
5
5
  "license": "MIT",
6
6
  "types": "dist/types/index.d.ts",
@@ -21,10 +21,10 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "@tanstack/react-table": "^8.21.3",
24
- "@tanstack/react-virtual": "^3.13.6",
24
+ "@tanstack/react-virtual": "^3.13.12",
25
25
  "@equinor/eds-icons": "^0.22.0",
26
26
  "@equinor/eds-tokens": "0.9.2",
27
- "@equinor/eds-utils": "^0.8.7"
27
+ "@equinor/eds-utils": "^0.8.8"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@rollup/plugin-babel": "^6.0.4",
@@ -54,16 +54,16 @@
54
54
  "jest-styled-components": "^7.2.0",
55
55
  "js-file-download": "^0.4.12",
56
56
  "postcss": "^8.5.3",
57
- "ramda": "^0.30.1",
57
+ "ramda": "^0.31.3",
58
58
  "react": "^18.3.1",
59
59
  "react-dom": "^18.3.1",
60
60
  "react-hook-form": "^7.56.1",
61
61
  "rollup": "^4.40.1",
62
62
  "rollup-plugin-delete": "^2.2.0",
63
63
  "rollup-plugin-postcss": "^4.0.2",
64
- "storybook": "^8.6.12",
65
- "styled-components": "6.1.17",
66
- "ts-jest": "29.3.2",
64
+ "storybook": "^8.6.14",
65
+ "styled-components": "6.1.19",
66
+ "ts-jest": "29.4.0",
67
67
  "ts-node": "10.9.2",
68
68
  "tsc-watch": "^6.2.1",
69
69
  "typescript": "~5.8.3"