Skip to content

Add cellStyleRevision prop for animated cell styling - #9

Closed
tothienbao6a0 wants to merge 2 commits into
extend-hq:mainfrom
tothienbao6a0:feat/cell-style-revision
Closed

Add cellStyleRevision prop for animated cell styling#9
tothienbao6a0 wants to merge 2 commits into
extend-hq:mainfrom
tothienbao6a0:feat/cell-style-revision

Conversation

@tothienbao6a0

Copy link
Copy Markdown
Contributor

Summary

Adds an optional cellStyleRevision prop to XlsxViewer. Bumping the counter forces the viewer to re-run getCellStyle and repaint cells, so consumers can animate or refresh custom cell styling while keeping a stable getCellStyle callback.

The pattern: store transient styling state in a ref, update it (e.g. from a requestAnimationFrame loop or timer), and bump cellStyleRevision to flush the new styles.

const pulseRef = React.useRef(0);
const [revision, setRevision] = React.useState(0);

React.useEffect(() => {
  let frame = 0;
  const start = performance.now();
  const tick = (now: number) => {
    pulseRef.current = (Math.sin((now - start) / 800) + 1) / 2;
    setRevision((value) => value + 1);
    frame = window.requestAnimationFrame(tick);
  };
  frame = window.requestAnimationFrame(tick);
  return () => window.cancelAnimationFrame(frame);
}, []);

const getCellStyle = React.useCallback<NonNullable<XlsxViewerProps["getCellStyle"]>>(
  ({ cell }) =>
    cell.row === 2 && cell.col === 1
      ? { backgroundColor: `rgba(37, 99, 235, ${(0.1 + pulseRef.current * 0.2).toFixed(3)})` }
      : undefined,
  []
);

<XlsxViewer file={buffer} getCellStyle={getCellStyle} cellStyleRevision={revision} />;

Why

getCellStyle (#8) re-resolves whenever the callback identity changes. For animation you'd otherwise have to recreate the callback every frame, which is non-obvious and creates churn. cellStyleRevision is an explicit, cheap animation primitive: keep the callback memoized and bump a number.

Note

Stacked on #8 (getCellStyle). Please review/merge that first — this PR's diff includes that commit until #8 lands, after which it will show only the cellStyleRevision commit. cellStyleRevision has no effect without getCellStyle.

Implementation

  • Wired into the same getCellData chokepoint and cache invalidation as getCellStyle, so a revision bump re-resolves styles and repaints both the DOM and canvas renderers.
  • cellStyleRevision is intentionally a getCellData dependency (commented in code): a new value gives getCellData a new identity, which clears the cell render cache and triggers a canvas repaint and DOM row re-render.

Changes

  • cellStyleRevision prop on XlsxViewerProps
  • Wiring through XlsxViewerInnerXlsxGrid → cache invalidation + getCellData
  • Playground: an "Animate" toggle that pulses the highlight via a rAF loop + cellStyleRevision
  • README docs (root + package) with the animation pattern and renderer notes

Test plan

  • pnpm typecheck (package + playground)
  • pnpm build (package)
  • Enable "Highlight" + "Animate" in the playground and confirm the tint pulses smoothly in both renderers

Made with Cursor

tothienbao6a0 and others added 2 commits June 18, 2026 01:51
Adds an optional `getCellStyle` viewer prop that returns CSS overrides
merged on top of each cell's resolved style. This is a generic escape
hatch for per-cell styling (highlights, outlines, status tints) without
forking the workbook data.

The hook is applied at the single getCellData chokepoint so both the DOM
and canvas renderers honor it, and is wired into the cell render cache
invalidation so changing the callback re-resolves and repaints cells.
The callback receives an XlsxCellStyleContext with the cell address,
sheet, resolved style, value, and flags (validation, hyperlink,
conditional format, chart highlight, merge, table header).

Also adds a "Highlight" toggle to the playground demonstrating the prop
and documents it in both READMEs.

Co-authored-by: Cursor <cursoragent@cursor.com>
Adds an optional `cellStyleRevision` viewer prop. Bumping the counter
forces the viewer to re-run `getCellStyle` and repaint cells, so consumers
can animate or refresh custom cell styling while keeping a stable
`getCellStyle` callback (store transient state in a ref, update it from a
rAF loop or timer, and bump the revision to flush).

Wired into the same getCellData chokepoint and cache invalidation as
`getCellStyle` so both the DOM and canvas renderers repaint. Adds an
"Animate" toggle to the playground and documents the pattern in the READMEs.

Co-authored-by: Cursor <cursoragent@cursor.com>
@vercel

vercel Bot commented Jun 18, 2026

Copy link
Copy Markdown

@tothienbao6a0 is attempting to deploy a commit to the Extend Team on Vercel.

A member of the Team first needs to authorize it.

@tothienbao6a0

Copy link
Copy Markdown
Contributor Author

Withdrawing this from upstream for now — keeping it as a personal/experimental branch. The generally-useful capability is #8 (getCellStyle); cellStyleRevision is niche enough that it shouldn't add API surface here yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant