Controlling What Gets Copied: Masking & Clipboard Output
What a cell shows and what it copies are two separate hooks on a policy:
renderString / renderNumber decide the display, and serializeForClipboard decides what
Ctrl/Cmd+C puts on the clipboard. Masking only the display is not enough — copying falls back to
the raw value. This demo puts both side by side; copy the grid and paste it into the box to compare.
Select A1:F3, copy it (Ctrl/Cmd+C), and paste into the box below to see exactly what left the grid.
Implementation Guide
Section titled “Implementation Guide”| Column | Shows | Copies | How |
|---|---|---|---|
a••••@acme.io | a••••@acme.io | renderString + serializeForClipboard | |
| Card | •••• 1234 | •••• 1234 | renderString + serializeForClipboard |
| API key | •••••••• | [redacted] | serializeForClipboard returns a placeholder |
| ⚠ Phone | 090-••••-5678 | 090-1234-5678 | renderString only — the full value leaks on copy |
| Amount | $1,234.50 | 1234.5 | renderNumber only — the default copies the raw value |
Mask the display and the clipboard together
Section titled “Mask the display and the clipboard together”const maskCard = (value: unknown) => { const digits = String(value ?? '').replace(/\D/g, ''); return digits ? `•••• ${digits.slice(-4)}` : '';};
const CardPolicy: PolicyMixinType = { // What the cell shows. renderString: ({ value }) => maskCard(value), // What Ctrl/Cmd+C copies. Without this, the raw value is copied. serializeForClipboard: ({ point, sheet }) => maskCard(sheet.getSerializedValue({ point })),};Register it with useSpellbook({ policies: { card: new Policy({ mixins: [CardPolicy] }) } }) and
assign it to a column with C: { policy: 'card' } in buildInitialCells.
Block copying entirely
Section titled “Block copying entirely”serializeForClipboard can return anything — here a fixed placeholder, so the value never reaches
the clipboard:
const SecretPolicy: PolicyMixinType = { renderString: ({ value }) => (value ? '••••••••' : ''), serializeForClipboard: () => '[redacted]',};The default: copy the raw value
Section titled “The default: copy the raw value”When a policy defines no serializeForClipboard, copying uses the cell’s serialized raw value —
not what is displayed. That is what you want for formatting (the Amount column copies 1234.5,
which pastes cleanly into other spreadsheets), and exactly what you don’t want for a display-only
mask (the ⚠ Phone column).
Limits
Section titled “Limits”This controls the grid’s display and its clipboard output only. The real value is still in the
sheet: it appears in the formula bar and the cell editor, and formulas, getCell and exports such
as toValueMatrix return it. If a value must stay secret, don’t send it to the browser.