From 1a651b8ef3cfcf9a63a99a4470032a6c46b5e529 Mon Sep 17 00:00:00 2001 From: Jason Smith Date: Thu, 28 Dec 2023 14:06:09 -0800 Subject: [PATCH] Make loading cell able to render a loading skeleton (#832) * Make loading cell able to render a loading skeleton * Fix imports * Add explanatory comment * Improve control over skeleton height and improve variability name to be specific to axis --- packages/core/src/cells/loading-cell.tsx | 34 ++++++++++++++++++- .../core/src/data-editor/stories/utils.tsx | 2 ++ .../src/internal/data-grid/data-grid-types.ts | 3 ++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/packages/core/src/cells/loading-cell.tsx b/packages/core/src/cells/loading-cell.tsx index 1090ad2cd..7b15d8b3a 100644 --- a/packages/core/src/cells/loading-cell.tsx +++ b/packages/core/src/cells/loading-cell.tsx @@ -1,6 +1,21 @@ +import { withAlpha } from "../internal/data-grid/color-parser.js"; +import { roundedRect } from "../internal/data-grid/data-grid-lib.js"; import { GridCellKind, type LoadingCell } from "../internal/data-grid/data-grid-types.js"; import type { InternalCellRenderer } from "./cell-types.js"; +// returns a "random" number between -1 and 1 +function getRandomNumber(x: number, y: number): number { + let seed = x * 49_632 + y * 325_176; + + // Inline Xorshift algorithm + seed ^= seed << 13; + seed ^= seed >> 17; + seed ^= seed << 5; + + // eslint-disable-next-line unicorn/number-literal-case + return (seed / 0xff_ff_ff_ff) * 2; +} + export const loadingCellRenderer: InternalCellRenderer = { getAccessibilityString: () => "", kind: GridCellKind.Loading, @@ -8,6 +23,23 @@ export const loadingCellRenderer: InternalCellRenderer = { useLabel: false, needsHoverPosition: false, measure: () => 120, - draw: () => undefined, + draw: a => { + const { cell, col, row, ctx, rect, theme } = a; + if (cell.skeletonWidth === undefined || cell.skeletonWidth === 0) { + return; + } + + let width = cell.skeletonWidth; + if (cell.skeletonWidthVariability !== undefined && cell.skeletonWidthVariability > 0) { + width += Math.round(getRandomNumber(col, row) * cell.skeletonWidthVariability); + } + + const hpad = theme.cellHorizontalPadding; + const rectHeight = cell.skeletonHeight ?? Math.min(18, rect.height - 2 * theme.cellVerticalPadding); + + roundedRect(ctx, rect.x + hpad, rect.y + (rect.height - rectHeight) / 2, width, rectHeight, 3); + ctx.fillStyle = withAlpha(theme.textDark, 0.1); + ctx.fill(); + }, onPaste: () => undefined, }; diff --git a/packages/core/src/data-editor/stories/utils.tsx b/packages/core/src/data-editor/stories/utils.tsx index c1ea85763..996b07398 100644 --- a/packages/core/src/data-editor/stories/utils.tsx +++ b/packages/core/src/data-editor/stories/utils.tsx @@ -601,6 +601,8 @@ function getColumnsForCellTypes(): GridColumnWithMockingInfo[] { return { kind: GridCellKind.Loading, allowOverlay: false, + skeletonWidth: 70, + skeletonVariability: 25, }; }, }, diff --git a/packages/core/src/internal/data-grid/data-grid-types.ts b/packages/core/src/internal/data-grid/data-grid-types.ts index 8b4f4c362..0d4a4c69b 100644 --- a/packages/core/src/internal/data-grid/data-grid-types.ts +++ b/packages/core/src/internal/data-grid/data-grid-types.ts @@ -313,6 +313,9 @@ export interface BaseGridCell { /** @category Cells */ export interface LoadingCell extends BaseGridCell { readonly kind: GridCellKind.Loading; + readonly skeletonWidth?: number; + readonly skeletonHeight?: number; + readonly skeletonWidthVariability?: number; } /** @category Cells */