UNPKG

@grafana/ui

Version:
1 lines • 47.2 kB
{"version":3,"file":"hooks.cjs","sources":["../../../../../src/components/Table/TableNG/hooks.ts"],"sourcesContent":["import { debounce } from 'lodash';\nimport {\n useState,\n useMemo,\n useCallback,\n useRef,\n useLayoutEffect,\n type RefObject,\n type CSSProperties,\n useEffect,\n} from 'react';\n\nimport { type DataFrame, type Field, FieldType, formattedValueToString, reduceField, ReducerID } from '@grafana/data';\nimport {\n type Column,\n type ColumnWidths,\n type DataGridHandle,\n type DataGridProps,\n type SortColumn,\n} from '@grafana/react-data-grid';\nimport { type MatcherScope } from '@grafana/schema';\n\nimport { type TableColumnResizeActionCallback } from '../types';\n\nimport { TABLE } from './constants';\nimport {\n type FilterType,\n type FooterFieldState,\n type NestedRowEntry,\n type SortByBehavior,\n type TableRow,\n type TableSortByFieldState,\n type TableSummaryRow,\n type TypographyCtx,\n} from './types';\nimport {\n getDisplayName,\n applySort,\n getColumnTypes,\n getRowHeight,\n computeColWidths,\n buildNestedColumnWidthsMap,\n buildHeaderHeightMeasurers,\n buildCellHeightMeasurers,\n IS_SAFARI_26,\n applyFilter,\n compileFrameToRecordsV1,\n compileFrameToRecordsV2,\n} from './utils';\n\nexport function useFilteredRows(rows: TableRow[], fields: Field[], hasNestedFrames?: boolean) {\n const [filter, setFilter] = useState<FilterType>({});\n const filterResult = useMemo(\n () => applyFilter(rows, filter, fields, hasNestedFrames),\n [rows, filter, fields, hasNestedFrames]\n );\n return { rows: filterResult.filteredRows, filter, setFilter, filterResult };\n}\n\nexport interface SortedRowsOptions {\n hasNestedFrames: boolean;\n initialSortBy?: TableSortByFieldState[];\n}\n\nexport interface SortedRowsResult {\n rows: TableRow[];\n sortColumns: SortColumn[];\n setSortColumns: React.Dispatch<React.SetStateAction<SortColumn[]>>;\n}\n\ninterface ManagedSortProps {\n sortByBehavior: SortByBehavior;\n setSortColumns: React.Dispatch<React.SetStateAction<SortColumn[]>>;\n sortBy?: TableSortByFieldState[];\n}\n\nexport function useManagedSort({ sortByBehavior, setSortColumns, sortBy }: ManagedSortProps) {\n useEffect(() => {\n if (sortByBehavior === 'managed' && sortBy) {\n setSortColumns(\n sortBy.map(({ displayName, desc }) => ({\n columnKey: displayName,\n direction: desc === true ? 'DESC' : 'ASC',\n }))\n );\n }\n }, [setSortColumns, sortBy, sortByBehavior]);\n}\n\nexport function useSortedRows(\n rows: TableRow[],\n fields: Field[],\n nestedFields: Field[],\n { initialSortBy, hasNestedFrames }: SortedRowsOptions\n): SortedRowsResult {\n const allFields = useMemo(() => [...fields, ...nestedFields], [fields, nestedFields]);\n const initialSortColumns = useMemo<SortColumn[]>(\n () =>\n initialSortBy?.flatMap(({ displayName, desc }) => {\n if (!allFields.some((f) => getDisplayName(f) === displayName)) {\n return [];\n }\n return [\n {\n columnKey: displayName,\n direction: desc ? ('DESC' as const) : ('ASC' as const),\n },\n ];\n }) ?? [],\n [] // eslint-disable-line react-hooks/exhaustive-deps\n );\n const [sortColumns, setSortColumns] = useState<SortColumn[]>(initialSortColumns);\n const columnTypes = useMemo(() => getColumnTypes(fields), [fields]);\n\n const sortedRows = useMemo(\n () => applySort(rows, fields, sortColumns, columnTypes, hasNestedFrames),\n [rows, fields, sortColumns, columnTypes, hasNestedFrames]\n );\n\n return {\n rows: sortedRows,\n sortColumns,\n setSortColumns,\n };\n}\n\nexport interface PaginatedRowsOptions {\n height: number;\n width: number;\n rowHeight: NonNullable<CSSProperties['height']> | ((row: TableRow) => number);\n headerHeight: number;\n footerHeight: number;\n paginationHeight?: number;\n enabled: boolean;\n hasNestedFrames?: boolean;\n}\n\nexport interface PaginatedRowsResult {\n rows: TableRow[];\n page: number;\n setPage: React.Dispatch<React.SetStateAction<number>>;\n numPages: number;\n numRows: number;\n rowsPerPage: number;\n pageRangeStart: number;\n pageRangeEnd: number;\n smallPagination: boolean;\n}\n\n// hand-measured. pagination height is 30px, plus 8px top margin\nconst PAGINATION_HEIGHT = 38;\n\nexport function usePaginatedRows(\n rows: TableRow[],\n { height, width, headerHeight, footerHeight, rowHeight, enabled, hasNestedFrames }: PaginatedRowsOptions\n): PaginatedRowsResult {\n // TODO: allow persisted page selection via url\n const [page, setPage] = useState(0);\n const numRows = useMemo(() => rows.filter((r) => r.__depth === 0).length, [rows]);\n\n // calculate average row height if row height is variable.\n const avgRowHeight = useMemo(() => {\n if (!enabled) {\n return 0;\n }\n\n if (typeof rowHeight === 'number') {\n return rowHeight;\n }\n\n // when using auto-sized rows, we're just going to have to pick a number. the alternative\n // is to measure each row, which we could do but would be expensive.\n if (typeof rowHeight === 'string') {\n return TABLE.MAX_CELL_HEIGHT;\n }\n\n // we'll just measure 100 rows to estimate (skipping nested rows. we don't want to consider nested rows to avoid hiding and showing\n // them as they are collapsed and expanded)\n let sum = 0;\n let count = 0;\n for (let i = 0; i < Math.min(100, rows.length); i++) {\n const row = rows[i];\n if (row.__depth > 0) {\n continue;\n }\n sum += rowHeight(rows[i]);\n count++;\n }\n return sum / count;\n }, [rows, rowHeight, enabled]);\n\n const smallPagination = useMemo(() => enabled && width < TABLE.PAGINATION_LIMIT, [enabled, width]);\n\n // using dimensions of the panel, calculate pagination parameters\n const { numPages, rowsPerPage, pageRangeStart, pageRangeEnd } = useMemo((): {\n numPages: number;\n rowsPerPage: number;\n pageRangeStart: number;\n pageRangeEnd: number;\n } => {\n if (!enabled) {\n return { numPages: 0, rowsPerPage: 0, pageRangeStart: 1, pageRangeEnd: numRows };\n }\n\n // calculate number of rowsPerPage based on height stack\n const rowAreaHeight = height - headerHeight - footerHeight - PAGINATION_HEIGHT;\n const heightPerRow = Math.floor(rowAreaHeight / (avgRowHeight || 1));\n // ensure at least one row per page is displayed\n let rowsPerPage = heightPerRow > 1 ? heightPerRow : 1;\n\n // calculate row range for pagination summary display\n const pageRangeStart = page * rowsPerPage + 1;\n let pageRangeEnd = pageRangeStart + rowsPerPage - 1;\n if (pageRangeEnd > numRows) {\n pageRangeEnd = numRows;\n }\n\n const numPages = Math.ceil(numRows / rowsPerPage);\n return {\n numPages,\n rowsPerPage,\n pageRangeStart,\n pageRangeEnd,\n };\n }, [height, headerHeight, footerHeight, avgRowHeight, enabled, numRows, page]);\n\n // safeguard against page overflow on panel resize or other factors\n useLayoutEffect(() => {\n if (!enabled) {\n return;\n }\n\n if (page > numPages) {\n // resets pagination to end\n setPage(numPages - 1);\n }\n }, [numPages, enabled, page, setPage]);\n\n // apply pagination to the sorted rows\n const paginatedRows = useMemo(() => {\n if (!enabled) {\n return rows;\n }\n\n const result = [];\n const pageOffset = page * rowsPerPage;\n\n let count = hasNestedFrames ? -1 * pageOffset : 0;\n let i = hasNestedFrames ? 0 : pageOffset;\n while (count <= rowsPerPage && i < rows.length) {\n const currRow = rows[i];\n i++;\n\n if (currRow.__depth === 0) {\n count++;\n }\n if (count >= 1 && count <= rowsPerPage) {\n result.push(currRow);\n }\n }\n\n return result;\n }, [page, rowsPerPage, rows, enabled, hasNestedFrames]);\n\n return {\n rows: paginatedRows,\n page: enabled ? page : -1,\n numRows,\n setPage,\n numPages,\n rowsPerPage,\n pageRangeStart,\n pageRangeEnd,\n smallPagination,\n };\n}\n\nexport const useNestedRows = (\n rows: TableRow[],\n nestedData: DataFrame[] | undefined,\n hasNestedFrames: boolean,\n nestedFramesFieldName: string | undefined,\n filter: FilterType,\n sortColumns: SortColumn[],\n protoParserEnabled = false\n): NestedRowEntry[] => {\n const frameToRecords = useMemo(() => {\n if (!hasNestedFrames || !nestedFramesFieldName || !nestedData?.[0]) {\n return;\n }\n return protoParserEnabled\n ? compileFrameToRecordsV2(nestedData[0])\n : compileFrameToRecordsV1(nestedData[0], nestedFramesFieldName);\n }, [hasNestedFrames, nestedFramesFieldName, nestedData, protoParserEnabled]);\n\n return useMemo(() => {\n const result: NestedRowEntry[] = [];\n if (!hasNestedFrames || !nestedFramesFieldName || !frameToRecords || !nestedData) {\n return result;\n }\n\n for (const parentRow of rows) {\n // Type guard to check if data exists as it's optional\n const nestedFrame = nestedData[parentRow.__index];\n if (!nestedFrame) {\n continue;\n }\n\n const rawRows = frameToRecords(nestedFrame, parentRow.__index);\n const filterResult = applyFilter(rawRows, filter, nestedFrame.fields, false, parentRow.__index);\n const sortedRows = applySort(\n filterResult.filteredRows,\n nestedFrame.fields,\n sortColumns,\n getColumnTypes(nestedFrame.fields)\n );\n result[parentRow.__index] = { raw: rawRows, final: sortedRows, filterResult };\n }\n\n return result;\n }, [hasNestedFrames, nestedFramesFieldName, rows, sortColumns, filter, frameToRecords, nestedData]);\n};\n\nconst ICON_WIDTH = 16;\nconst ICON_GAP = 4;\n\ninterface UseHeaderHeightOptions {\n enabled: boolean;\n fields: Field[];\n columnWidths: number[];\n sortColumns: SortColumn[];\n typographyCtx: TypographyCtx;\n showTypeIcons?: boolean;\n}\n\nexport function useHeaderHeight({\n fields,\n enabled,\n columnWidths,\n sortColumns,\n typographyCtx,\n showTypeIcons = false,\n}: UseHeaderHeightOptions): number {\n const perIconSpace = ICON_WIDTH + ICON_GAP;\n\n const measurers = useMemo(() => buildHeaderHeightMeasurers(fields, typographyCtx), [fields, typographyCtx]);\n\n const columnAvailableWidths = useMemo(\n () =>\n columnWidths.map((c, idx) => {\n if (idx >= fields.length) {\n return 0; // no width available for this column yet\n }\n\n let width = c - 2 * TABLE.CELL_PADDING - TABLE.BORDER_RIGHT;\n const field = fields[idx];\n\n // filtering icon\n if (field.config?.custom?.filterable) {\n width -= perIconSpace;\n }\n // sorting icon\n if (sortColumns.some((col) => col.columnKey === getDisplayName(field))) {\n width -= perIconSpace;\n }\n // type icon\n if (showTypeIcons) {\n width -= perIconSpace;\n }\n // sadly, the math for this is off by exactly 1 pixel. shrug.\n return Math.floor(width) - 1;\n }),\n [fields, columnWidths, sortColumns, showTypeIcons, perIconSpace]\n );\n\n const headerHeight = useMemo(() => {\n if (!enabled) {\n return 0;\n }\n return getRowHeight(\n fields,\n { __index: -1, __depth: 0 },\n columnAvailableWidths,\n TABLE.HEADER_HEIGHT,\n measurers,\n TABLE.LINE_HEIGHT,\n TABLE.CELL_PADDING\n );\n }, [fields, enabled, columnAvailableWidths, measurers]);\n\n return headerHeight;\n}\n\ninterface UseRowHeightOptions {\n columnWidths: number[];\n fields: Field[];\n hasNestedFrames: boolean;\n defaultHeight: NonNullable<CSSProperties['height']>;\n defaultNestedHeight: NonNullable<CSSProperties['height']>;\n visibleNestedRowCounts: Array<number | null>;\n typographyCtx: TypographyCtx;\n maxHeight?: number;\n nestedData?: DataFrame[] | undefined;\n nestedRows: NestedRowEntry[];\n nestedFields: Field[];\n nestedColWidths: number[];\n nestedFooterHeight?: number;\n}\n\nconst getTrueColWidths = (cw: number[]): number[] => cw.map((c) => c - (2 * TABLE.CELL_PADDING + TABLE.BORDER_RIGHT));\n\n// TODO: maybe there's a way to decouple the nested rows from the top-level rows here.\nexport function useRowHeight({\n columnWidths,\n fields,\n defaultHeight,\n defaultNestedHeight,\n typographyCtx,\n maxHeight,\n hasNestedFrames,\n nestedData,\n nestedRows,\n nestedFields,\n nestedColWidths,\n visibleNestedRowCounts,\n nestedFooterHeight = 0,\n}: UseRowHeightOptions): NonNullable<CSSProperties['height']> | ((row: TableRow) => number) {\n const nestedMeasurers = useMemo(\n () => buildCellHeightMeasurers(nestedFields, typographyCtx, maxHeight),\n [nestedFields, typographyCtx, maxHeight]\n );\n\n const totalParentWidth = useMemo(() => columnWidths.reduce((acc, width) => acc + width, 0), [columnWidths]);\n const totalNestedWidth = useMemo(() => nestedColWidths.reduce((acc, width) => acc + width, 0), [nestedColWidths]);\n const nestedHasOverflow = useMemo(() => totalParentWidth < totalNestedWidth, [totalParentWidth, totalNestedWidth]);\n\n const getNestedRowHeightWithCache = useMemo(() => {\n if (typeof defaultNestedHeight === 'string') {\n return () => 0;\n }\n\n if ((nestedMeasurers?.length ?? 0) === 0) {\n return () => defaultNestedHeight;\n }\n\n const nestedRowCache: Array<number[] | undefined> = visibleNestedRowCounts.map((count) =>\n count == null ? undefined : Array(count)\n );\n\n return (row: TableRow) => {\n if (row.__parentIndex == null) {\n return 0;\n }\n\n const nestedRowCacheEntry = nestedRowCache[row.__parentIndex];\n if (nestedRowCacheEntry == null) {\n return 0;\n }\n\n const trueNestedColWidths = getTrueColWidths(nestedColWidths);\n let result = nestedRowCacheEntry[row.__index];\n if (result == null) {\n result = nestedRowCacheEntry[row.__index] = getRowHeight(\n nestedFields,\n row,\n trueNestedColWidths,\n defaultNestedHeight,\n nestedMeasurers\n );\n }\n return result;\n };\n }, [nestedFields, nestedColWidths, defaultNestedHeight, nestedMeasurers, visibleNestedRowCounts]);\n\n const measurers = useMemo(\n () => buildCellHeightMeasurers(fields, typographyCtx, maxHeight),\n [fields, typographyCtx, maxHeight]\n );\n const hasWrappedCols = (measurers?.length ?? 0) > 0;\n\n const getRowHeightWithCache = useMemo(() => {\n if (typeof defaultHeight === 'string') {\n return () => 0;\n }\n\n if (!hasWrappedCols) {\n return () => defaultHeight;\n }\n\n const trueColWidths = getTrueColWidths(columnWidths);\n const cache: Array<number | undefined> = Array(fields[0].values.length);\n return (row: TableRow) => {\n let result = cache[row.__index];\n if (result == null) {\n result = cache[row.__index] = getRowHeight(fields, row, trueColWidths, defaultHeight, measurers);\n }\n return result;\n };\n }, [fields, columnWidths, defaultHeight, measurers, hasWrappedCols]);\n\n const rowHeight = useMemo(() => {\n // row height is only complicated when there are nested frames or wrapped columns.\n if (typeof defaultHeight === 'string' || !(hasWrappedCols || hasNestedFrames)) {\n return defaultHeight;\n }\n\n if (typeof defaultNestedHeight === 'string') {\n return defaultNestedHeight;\n }\n\n return (row: TableRow): number => {\n // nested rows\n if (row.__depth > 0) {\n // if unexpanded, height === 0\n const visibleNestedRowCount = visibleNestedRowCounts[row.__index];\n if (visibleNestedRowCount == null) {\n return 0;\n }\n\n // if expanded with no rows, height === no data height\n if (visibleNestedRowCount === 0) {\n return TABLE.NESTED_NO_DATA_HEIGHT + TABLE.CELL_PADDING * 2 + nestedFooterHeight;\n }\n\n const nestedHeaderHeight = nestedData?.[row.__index]?.meta?.custom?.noHeader ? 0 : defaultNestedHeight;\n const nestedRowsHeight = nestedRows[row.__index].final.reduce(\n (acc, row) => acc + getNestedRowHeightWithCache(row),\n 0\n );\n const scrollbarHeight = nestedHasOverflow ? TABLE.SCROLLBAR_AFFORDANCE : 0;\n return nestedRowsHeight + nestedHeaderHeight + nestedFooterHeight + TABLE.CELL_PADDING * 2 + scrollbarHeight;\n }\n\n return row.__parentIndex != null ? getNestedRowHeightWithCache(row) : getRowHeightWithCache(row);\n };\n }, [\n getNestedRowHeightWithCache,\n getRowHeightWithCache,\n defaultHeight,\n defaultNestedHeight,\n hasNestedFrames,\n hasWrappedCols,\n nestedFooterHeight,\n nestedHasOverflow,\n nestedRows,\n nestedData,\n visibleNestedRowCounts,\n ]);\n\n return rowHeight;\n}\n\n/**\n * react-data-grid is a little unwieldy when it comes to column resize events.\n * we want to detect a few different column resize signals:\n * - dragging the handle (only want to dispatch when handle is released)\n * - double-clicking the handle (sets the column to the minimum width to fit content)\n * `onColumnResize` dispatches events throughout a dragged resize, and `onColumnWidthsChanged` doesn't\n * emit an event when double-click resizing occurs, so we have to build something custom on top of these\n * behaviors in order to get everything working.\n */\ninterface UseColumnResizeState {\n columnKey: string | undefined;\n width: number;\n fieldScope?: MatcherScope;\n}\n\nconst INITIAL_COL_RESIZE_STATE = Object.freeze({ columnKey: undefined, width: 0 }) satisfies UseColumnResizeState;\n\nexport function useColumnResize(\n onColumnResize: TableColumnResizeActionCallback = () => {},\n fieldScope?: MatcherScope\n): DataGridProps<TableRow, TableSummaryRow>['onColumnResize'] {\n // these must be refs. if we used setState, we would run into race conditions with these event listeners\n const colResizeState = useRef<UseColumnResizeState>({ ...INITIAL_COL_RESIZE_STATE });\n const pointerIsDown = useRef(false);\n\n // to detect whether we got a double-click resize, we track whether the pointer is currently down\n useLayoutEffect(() => {\n function pointerDown(_event: PointerEvent) {\n pointerIsDown.current = true;\n }\n\n function pointerUp(_event: PointerEvent) {\n pointerIsDown.current = false;\n }\n\n window.addEventListener('pointerdown', pointerDown);\n window.addEventListener('pointerup', pointerUp);\n\n return () => {\n window.removeEventListener('pointerdown', pointerDown);\n window.removeEventListener('pointerup', pointerUp);\n };\n });\n\n const dispatchEvent = useCallback(() => {\n if (colResizeState.current.columnKey) {\n onColumnResize(\n colResizeState.current.columnKey,\n Math.floor(colResizeState.current.width),\n colResizeState.current.fieldScope\n );\n colResizeState.current = { ...INITIAL_COL_RESIZE_STATE };\n }\n window.removeEventListener('click', dispatchEvent, { capture: true });\n }, [onColumnResize]);\n\n // this is the callback that gets passed to react-data-grid\n const dataGridResizeHandler = useCallback(\n (column: Column<TableRow, TableSummaryRow>, width: number) => {\n if (!colResizeState.current.columnKey) {\n window.addEventListener('click', dispatchEvent, { capture: true });\n }\n\n colResizeState.current.columnKey = column.key;\n colResizeState.current.width = width;\n\n if (fieldScope) {\n colResizeState.current.fieldScope = fieldScope;\n }\n\n // when double clicking to resize, this handler will fire, but the pointer will not be down,\n // meaning that we should immediately flush the new width\n if (!pointerIsDown.current) {\n dispatchEvent();\n }\n },\n [fieldScope, dispatchEvent]\n );\n\n return dataGridResizeHandler;\n}\n\nexport function useScrollbarWidth(ref: RefObject<DataGridHandle | null>, height: number) {\n const [scrollbarWidth, setScrollbarWidth] = useState(0);\n\n const updateScrollbarDimensions = debounce(() => {\n const el = ref.current?.element;\n if (el) {\n setScrollbarWidth(el!.offsetWidth - el!.clientWidth);\n }\n }, 150);\n\n useLayoutEffect(() => {\n const el = ref.current?.element;\n if (!el || IS_SAFARI_26) {\n return;\n }\n\n updateScrollbarDimensions();\n\n const resizeObserver = new ResizeObserver(updateScrollbarDimensions);\n resizeObserver.observe(el);\n return () => {\n resizeObserver.disconnect();\n };\n }, [ref, height, updateScrollbarDimensions]);\n\n return scrollbarWidth;\n}\n\ninterface UseNestedColWidthsOptions {\n nestedVisibleFields: Field[];\n availableWidth: number;\n structureRev?: number;\n}\n\ninterface UseNestedColWidthsResult {\n nestedFieldWidths: number[];\n nestedColWidths: ColumnWidths;\n handleNestedColumnWidthsChange: (newColWidths: ColumnWidths) => void;\n}\n\n/**\n * Manages per-column widths for nested tables.\n */\nexport function useNestedColWidths({\n nestedVisibleFields,\n availableWidth,\n structureRev,\n}: UseNestedColWidthsOptions): UseNestedColWidthsResult {\n // before we do anything, figure out what the widths are based on the panel configuration.\n const configuredWidths = useMemo(\n () => computeColWidths(nestedVisibleFields, availableWidth),\n [nestedVisibleFields, availableWidth]\n );\n\n const [nestedFieldWidths, setNestedFieldWidths] = useState(() => configuredWidths);\n\n // on structureRev change, sync the widths from config and check whether we ought to dispatch an update.\n useEffect(() => {\n const newWidths = computeColWidths(nestedVisibleFields, availableWidth);\n let hasChanges = false;\n if (nestedFieldWidths.length !== newWidths.length) {\n // if we have fewer columns than the new widths, we have changes\n hasChanges = true;\n }\n for (let i = 0; i < newWidths.length; i++) {\n if (nestedFieldWidths[i] !== newWidths[i]) {\n hasChanges = true;\n break;\n }\n }\n\n if (hasChanges) {\n setNestedFieldWidths(newWidths);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [structureRev]);\n\n // this is the representation that react-data-grid wants, which we derive from the source of truth (nestedFieldWidths) on every render\n const nestedColWidths = useMemo(\n () => buildNestedColumnWidthsMap(nestedVisibleFields, nestedFieldWidths),\n [nestedVisibleFields, nestedFieldWidths]\n );\n\n const handleNestedColumnWidthsChange = useCallback(\n (newColWidths: ColumnWidths) => {\n setNestedFieldWidths(\n nestedVisibleFields.map((f, idx) => {\n const entry = newColWidths.get(getDisplayName(f));\n // ColumnWidth always has a width property (both 'resized' and 'measured' variants)\n return entry != null ? entry.width : nestedFieldWidths[idx];\n })\n );\n },\n [nestedVisibleFields, nestedFieldWidths]\n );\n\n return { nestedFieldWidths, nestedColWidths, handleNestedColumnWidthsChange };\n}\n\nexport function useColWidths(\n visibleFields: Field[],\n availableWidth: number,\n frozenColumns?: number,\n resetKey?: Symbol\n): [number[], number] {\n const widths = useMemo(\n () => computeColWidths(visibleFields, availableWidth),\n // Width override removals can mutate width config onto existing field objects.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [visibleFields, availableWidth, resetKey]\n );\n\n // this is to avoid buggy situations where all visible columns are frozen\n const numFrozenColsFullyInView = useMemo(() => {\n if (!frozenColumns || frozenColumns <= 0) {\n return -1;\n }\n\n const fullyVisibleCols = widths.reduce(\n ([count, remainingWidth], nextWidth) => {\n if (remainingWidth - nextWidth >= 0) {\n return [count + 1, remainingWidth - nextWidth];\n }\n return [count, 0];\n },\n [0, availableWidth]\n )[0];\n\n // de-noise memoized changes to the columns array, and only change this\n // number when the number of frozen columns changes or once there are fewer\n // visible columns than the number of frozen columns.\n return Math.min(fullyVisibleCols, frozenColumns);\n }, [widths, availableWidth, frozenColumns]);\n\n return [widths, numFrozenColsFullyInView];\n}\n\nconst isReducer = (maybeReducer: string): maybeReducer is ReducerID => maybeReducer in ReducerID;\nconst nonMathReducers = new Set<ReducerID>([\n ReducerID.allValues,\n ReducerID.changeCount,\n ReducerID.count,\n ReducerID.countAll,\n ReducerID.distinctCount,\n ReducerID.first,\n ReducerID.firstNotNull,\n ReducerID.last,\n ReducerID.lastNotNull,\n ReducerID.uniqueValues,\n]);\nconst isNonMathReducer = (reducer: string) => isReducer(reducer) && nonMathReducers.has(reducer);\nconst noFormattingReducers = new Set<ReducerID>([ReducerID.count, ReducerID.countAll]);\nconst shouldReducerSkipFormatting = (reducer: string) => isReducer(reducer) && noFormattingReducers.has(reducer);\n\nexport const useReducerEntries = (\n field: Field,\n rows: TableRow[],\n displayName: string,\n colIdx: number\n): Array<[string, string | null]> => {\n return useMemo(() => {\n const reducers: string[] = field.config.custom?.footer?.reducers ?? [];\n\n if (\n reducers.length === 0 ||\n (field.type !== FieldType.number && reducers.every((reducerId) => !isNonMathReducer(reducerId)))\n ) {\n return [];\n }\n\n // Create a new state object that matches the original behavior exactly\n const newState: FooterFieldState = {\n lastProcessedRowCount: 0,\n ...(field.state || {}), // Preserve any existing state properties\n };\n\n // Assign back to field\n field.state = newState;\n\n const currentRowCount = rows.length;\n const lastRowCount = newState.lastProcessedRowCount;\n\n // Check if we need to invalidate the cache\n if (lastRowCount !== currentRowCount) {\n // Cache should be invalidated as row count has changed\n if (newState.calcs) {\n delete newState.calcs;\n }\n // Update the row count tracker\n newState.lastProcessedRowCount = currentRowCount;\n }\n\n // Calculate all specified reducers\n const results: Record<string, number | null> = reduceField({\n field: {\n ...field,\n values: rows.map((row) => row[displayName]),\n },\n reducers,\n });\n\n return reducers.map((reducerId) => {\n if (\n results[reducerId] === undefined ||\n // For non-number fields, only show special count reducers\n (field.type !== FieldType.number && !isNonMathReducer(reducerId)) ||\n // for countAll, only show the reducer in the first column\n (reducerId === ReducerID.countAll && colIdx !== 0)\n ) {\n return [reducerId, null];\n }\n\n const value = results[reducerId];\n let result = null;\n if (!shouldReducerSkipFormatting(reducerId) && field.display) {\n result = formattedValueToString(field.display(value));\n } else if (value != null) {\n result = String(value);\n }\n\n return [reducerId, result];\n });\n }, [field, rows, displayName, colIdx]);\n};\n"],"names":["useState","useMemo","applyFilter","useEffect","getDisplayName","getColumnTypes","applySort","TABLE","rowsPerPage","pageRangeStart","pageRangeEnd","numPages","useLayoutEffect","compileFrameToRecordsV2","compileFrameToRecordsV1","buildHeaderHeightMeasurers","getRowHeight","buildCellHeightMeasurers","_a","row","useRef","useCallback","debounce","IS_SAFARI_26","computeColWidths","buildNestedColumnWidthsMap","ReducerID","FieldType","reduceField","formattedValueToString"],"mappings":"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"}