@alaarab/ogrid-react-fluent 2.0.17 → 2.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.
@@ -1,9 +1,17 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { Input, Checkbox, Spinner } from '@fluentui/react-components';
3
3
  import { SearchRegular } from '@fluentui/react-icons';
4
+ import { useListVirtualizer } from '@alaarab/ogrid-react';
4
5
  import styles from './ColumnHeaderFilter.module.css';
5
- export const MultiSelectFilterPopover = ({ searchText, onSearchChange, options, filteredOptions, selected, onOptionToggle, onSelectAll, onClearSelection, onApply, isLoading, onPopoverClick, onInputFocus, onInputMouseDown, onInputClick, onInputKeyDown, }) => (_jsxs(_Fragment, { children: [_jsxs("div", { className: styles.popoverSearch, onClick: onPopoverClick, children: [_jsx(Input, { placeholder: "Search...", value: searchText, onChange: (e, data) => onSearchChange(data.value ?? ''), onFocus: onInputFocus, onMouseDown: onInputMouseDown, onClick: onInputClick, onKeyDown: onInputKeyDown, autoComplete: "off", className: styles.searchInput, contentBefore: _jsx(SearchRegular, {}) }), _jsxs("div", { className: styles.resultCount, children: [filteredOptions.length, " of ", options.length, " options"] })] }), _jsxs("div", { className: styles.selectAllRow, onClick: onPopoverClick, children: [_jsxs("button", { type: "button", className: styles.selectAllButton, onClick: onSelectAll, children: ["Select All (", filteredOptions.length, ")"] }), _jsx("button", { type: "button", className: styles.selectAllButton, onClick: onClearSelection, children: "Clear" })] }), _jsx("div", { className: styles.popoverOptions, onClick: onPopoverClick, children: isLoading ? (_jsx("div", { className: styles.loadingContainer, children: _jsx(Spinner, { size: "small", label: "Loading..." }) })) : filteredOptions.length === 0 ? (_jsx("div", { className: styles.noResults, children: "No options found" })) : (filteredOptions.map((option) => (_jsx("div", { className: styles.popoverOption, children: _jsx(Checkbox, { label: option, checked: selected.has(option), onChange: (ev, data) => {
6
- ev.stopPropagation();
7
- onOptionToggle(option, data.checked === true);
8
- } }) }, option)))) }), _jsxs("div", { className: styles.popoverActions, onClick: onPopoverClick, children: [_jsx("button", { type: "button", className: styles.clearButton, onClick: onClearSelection, children: "Clear" }), _jsx("button", { type: "button", className: styles.applyButton, onClick: onApply, children: "Apply" })] })] }));
6
+ const ITEM_HEIGHT = 32;
7
+ export const MultiSelectFilterPopover = ({ searchText, onSearchChange, options, filteredOptions, selected, onOptionToggle, onSelectAll, onClearSelection, onApply, isLoading, onPopoverClick, onInputFocus, onInputMouseDown, onInputClick, onInputKeyDown, }) => {
8
+ const virt = useListVirtualizer({ count: filteredOptions.length, itemHeight: ITEM_HEIGHT });
9
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: styles.popoverSearch, onClick: onPopoverClick, children: [_jsx(Input, { placeholder: "Search...", value: searchText, onChange: (e, data) => onSearchChange(data.value ?? ''), onFocus: onInputFocus, onMouseDown: onInputMouseDown, onClick: onInputClick, onKeyDown: onInputKeyDown, autoComplete: "off", className: styles.searchInput, contentBefore: _jsx(SearchRegular, {}) }), _jsxs("div", { className: styles.resultCount, children: [filteredOptions.length, " of ", options.length, " options"] })] }), _jsxs("div", { className: styles.selectAllRow, onClick: onPopoverClick, children: [_jsxs("button", { type: "button", className: styles.selectAllButton, onClick: onSelectAll, children: ["Select All (", filteredOptions.length, ")"] }), _jsx("button", { type: "button", className: styles.selectAllButton, onClick: onClearSelection, children: "Clear" })] }), _jsx("div", { ref: virt.containerRef, onScroll: virt.onScroll, className: styles.popoverOptions, onClick: onPopoverClick, children: isLoading ? (_jsx("div", { className: styles.loadingContainer, children: _jsx(Spinner, { size: "small", label: "Loading..." }) })) : filteredOptions.length === 0 ? (_jsx("div", { className: styles.noResults, children: "No options found" })) : (_jsx("div", { style: { height: virt.totalHeight, position: 'relative' }, children: virt.visibleItems.map(({ index, offsetTop }) => {
10
+ const option = filteredOptions[index];
11
+ return (_jsx("div", { className: styles.popoverOption, style: { position: 'absolute', top: offsetTop, width: '100%', boxSizing: 'border-box' }, children: _jsx(Checkbox, { label: option, checked: selected.has(option), onChange: (ev, data) => {
12
+ ev.stopPropagation();
13
+ onOptionToggle(option, data.checked === true);
14
+ } }) }, option));
15
+ }) })) }), _jsxs("div", { className: styles.popoverActions, onClick: onPopoverClick, children: [_jsx("button", { type: "button", className: styles.clearButton, onClick: onClearSelection, children: "Clear" }), _jsx("button", { type: "button", className: styles.applyButton, onClick: onApply, children: "Apply" })] })] }));
16
+ };
9
17
  MultiSelectFilterPopover.displayName = 'MultiSelectFilterPopover';
@@ -22,7 +22,7 @@ function GridRowInner(props) {
22
22
  const GridRow = React.memo(GridRowInner, areGridRowPropsEqual);
23
23
  function DataGridTableInner(props) {
24
24
  const o = useDataGridTableOrchestration({ props });
25
- const { wrapperRef, tableContainerRef, lastMouseShiftRef, interaction, pinning, handleResizeStart, getColumnWidth, isReorderDragging, dropIndicatorX, handleHeaderMouseDown, virtualScrollEnabled, visibleRange, items, getRowId, emptyState, rowSelection, freezeRows, freezeCols, isLoading, loadingMessage, ariaLabel, ariaLabelledBy, visibleColumns, columnOrder, columnReorder, density, rowNumberOffset, headerRows, allowOverflowX, fitToContent, editCallbacks, interactionHandlers, cellDescriptorInputRef, pendingEditorValueRef, popoverAnchorElRef, handleSingleRowClick, handlePasteVoid, visibleCols, totalColCount, hasCheckboxCol, hasRowNumbersCol, colOffset, containerWidth, minTableWidth, columnSizingOverrides, measuredColumnWidths, selectedRowIds, handleRowCheckboxChange, handleSelectAll, allSelected, someSelected, editingCell, setPopoverAnchorEl, cancelPopoverEdit, setActiveCell, selectionRange, hasCellSelection, handleGridKeyDown, handleFillHandleMouseDown, handleCopy, handleCut, cutRange, copyRange, canUndo, canRedo, onUndo, onRedo, isDragging, menuPosition, closeContextMenu, headerFilterInput, statusBarConfig, showEmptyInGrid, onCellError, headerMenu, } = o;
25
+ const { wrapperRef, tableContainerRef, lastMouseShiftRef, interaction, pinning, handleResizeStart, getColumnWidth, isReorderDragging, dropIndicatorX, handleHeaderMouseDown, virtualScrollEnabled, visibleRange, items, getRowId, emptyState, rowSelection, isLoading, loadingMessage, ariaLabel, ariaLabelledBy, visibleColumns, columnOrder, columnReorder, density, rowNumberOffset, headerRows, allowOverflowX, fitToContent, editCallbacks, interactionHandlers, cellDescriptorInputRef, pendingEditorValueRef, popoverAnchorElRef, handleSingleRowClick, handlePasteVoid, visibleCols, totalColCount, hasCheckboxCol, hasRowNumbersCol, colOffset, containerWidth, minTableWidth, columnSizingOverrides, measuredColumnWidths, selectedRowIds, handleRowCheckboxChange, handleSelectAll, allSelected, someSelected, editingCell, setPopoverAnchorEl, cancelPopoverEdit, setActiveCell, selectionRange, hasCellSelection, handleGridKeyDown, handleFillHandleMouseDown, handleCopy, handleCut, cutRange, copyRange, canUndo, canRedo, onUndo, onRedo, isDragging, menuPosition, closeContextMenu, headerFilterInput, statusBarConfig, showEmptyInGrid, onCellError, headerMenu, } = o;
26
26
  // Pre-compute column styles and classNames (avoids per-cell object creation in the row loop)
27
27
  const columnMeta = useMemo(() => {
28
28
  const cellStyles = {};
@@ -33,7 +33,6 @@ function DataGridTableInner(props) {
33
33
  const col = visibleCols[i];
34
34
  const columnWidth = getColumnWidth(col);
35
35
  const hasExplicitWidth = !!(columnSizingOverrides[col.columnId] || col.idealWidth != null || col.defaultWidth != null);
36
- const isFreezeCol = freezeCols != null && freezeCols >= 1 && i < freezeCols;
37
36
  const isPinnedLeft = pinning.pinnedColumns[col.columnId] === 'left';
38
37
  const isPinnedRight = pinning.pinnedColumns[col.columnId] === 'right';
39
38
  const hasResizeOverride = !!columnSizingOverrides[col.columnId];
@@ -63,10 +62,6 @@ function DataGridTableInner(props) {
63
62
  ...(isPinnedRight && pinning.rightOffsets[col.columnId] != null ? { right: pinning.rightOffsets[col.columnId] } : undefined),
64
63
  };
65
64
  const parts = [];
66
- if (isFreezeCol)
67
- parts.push(styles.freezeCol);
68
- if (isFreezeCol && i === 0)
69
- parts.push(styles.freezeColFirst);
70
65
  if (isPinnedLeft)
71
66
  parts.push(styles.pinnedColLeft);
72
67
  if (isPinnedRight)
@@ -76,7 +71,7 @@ function DataGridTableInner(props) {
76
71
  hdrClasses[col.columnId] = cn;
77
72
  }
78
73
  return { cellStyles, cellClasses, hdrStyles, hdrClasses };
79
- }, [visibleCols, getColumnWidth, columnSizingOverrides, measuredColumnWidths, freezeCols, pinning.pinnedColumns, pinning.leftOffsets, pinning.rightOffsets]);
74
+ }, [visibleCols, getColumnWidth, columnSizingOverrides, measuredColumnWidths, pinning.pinnedColumns, pinning.leftOffsets, pinning.rightOffsets]);
80
75
  // renderCellContent reads volatile state from refs -- keeps function identity stable so
81
76
  // GridRow's React.memo comparator can skip rows whose selection state hasn't changed.
82
77
  const renderCellContent = useCallback((item, col, rowIndex, colIdx) => {
@@ -105,7 +100,7 @@ function DataGridTableInner(props) {
105
100
  },
106
101
  // eslint-disable-next-line react-hooks/exhaustive-deps -- *Ref vars are stable refs from useLatestRef
107
102
  [editCallbacks, interactionHandlers, handleFillHandleMouseDown, setPopoverAnchorEl, cancelPopoverEdit, getRowId, onCellError]);
108
- return (_jsxs("div", { style: GRID_ROOT_STYLE, children: [_jsxs("div", { ref: wrapperRef, tabIndex: 0, onMouseDown: (e) => { lastMouseShiftRef.current = e.shiftKey; }, className: `${styles.tableWrapper} ${rowSelection !== 'none' ? styles.selectableGrid : ''} ${styles[`density-${density}`] || ''}`, role: "region", "aria-label": ariaLabel ?? (ariaLabelledBy ? undefined : 'Data grid'), "aria-labelledby": ariaLabelledBy, "data-empty": showEmptyInGrid ? 'true' : undefined, "data-loading": isLoading && items.length === 0 ? 'true' : undefined, "data-column-count": totalColCount, "data-freeze-rows": freezeRows != null && freezeRows >= 1 ? freezeRows : undefined, "data-freeze-cols": freezeCols != null && freezeCols >= 1 ? freezeCols : undefined, "data-overflow-x": allowOverflowX ? 'true' : 'false', "data-container-width": containerWidth, "data-min-table-width": Math.round(minTableWidth), "data-has-selection": rowSelection !== 'none' ? 'true' : undefined, onContextMenu: PREVENT_DEFAULT, onKeyDown: handleGridKeyDown, style: {
103
+ return (_jsxs("div", { style: GRID_ROOT_STYLE, children: [_jsxs("div", { ref: wrapperRef, tabIndex: 0, onMouseDown: (e) => { lastMouseShiftRef.current = e.shiftKey; }, className: `${styles.tableWrapper} ${rowSelection !== 'none' ? styles.selectableGrid : ''} ${styles[`density-${density}`] || ''}`, role: "region", "aria-label": ariaLabel ?? (ariaLabelledBy ? undefined : 'Data grid'), "aria-labelledby": ariaLabelledBy, "data-empty": showEmptyInGrid ? 'true' : undefined, "data-loading": isLoading && items.length === 0 ? 'true' : undefined, "data-column-count": totalColCount, "data-overflow-x": allowOverflowX ? 'true' : 'false', "data-container-width": containerWidth, "data-min-table-width": Math.round(minTableWidth), "data-has-selection": rowSelection !== 'none' ? 'true' : undefined, onContextMenu: PREVENT_DEFAULT, onKeyDown: handleGridKeyDown, style: {
109
104
  ['--data-table-column-count']: totalColCount,
110
105
  ['--data-table-width']: showEmptyInGrid ? '100%' : allowOverflowX ? 'fit-content' : fitToContent ? 'fit-content' : '100%',
111
106
  ['--data-table-min-width']: showEmptyInGrid ? '100%' : allowOverflowX ? 'max-content' : fitToContent ? 'max-content' : '100%',
@@ -159,13 +159,6 @@
159
159
  pointer-events: none;
160
160
  }
161
161
 
162
- .freezeColFirst {
163
- position: sticky;
164
- left: 0;
165
- z-index: 6;
166
- background: var(--ogrid-bg, #ffffff);
167
- }
168
-
169
162
  .cellContent {
170
163
  width: 100%;
171
164
  height: 100%;
@@ -661,15 +654,6 @@
661
654
  background-color: var(--colorSubtleBackgroundSelected, var(--ogrid-header-bg, #f3f2f1));
662
655
  }
663
656
 
664
- .freezeColFirst {
665
- background-color: var(--colorNeutralBackground1, #ffffff);
666
- }
667
-
668
- .dataTable :global(.fui-TableHeader) .freezeColFirst {
669
- background-color: var(--colorSubtleBackgroundSelected, var(--ogrid-header-bg, #f3f2f1));
670
- }
671
-
672
- .stickyHeader .freezeColFirst,
673
657
  .stickyHeader .pinnedColLeft,
674
658
  .stickyHeader .pinnedColRight {
675
659
  top: 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alaarab/ogrid-react-fluent",
3
- "version": "2.0.17",
3
+ "version": "2.0.18",
4
4
  "description": "OGrid React Fluent implementation – DataGrid-powered data table with sorting, filtering, pagination, column chooser, and CSV export.",
5
5
  "main": "dist/esm/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -40,7 +40,7 @@
40
40
  "node": ">=18"
41
41
  },
42
42
  "dependencies": {
43
- "@alaarab/ogrid-react": "2.0.17"
43
+ "@alaarab/ogrid-react": "2.0.18"
44
44
  },
45
45
  "peerDependencies": {
46
46
  "@fluentui/react-components": "^9.0.0",