Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions content/docs/learn/playground/alignment.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
---
title: "Align cells and wrap text"
description: "Horizontal (left/center/right) and vertical (top/middle/bottom) alignment plus text wrap are per-cell format attributes; the toolbar sets them (Ctrl+Shift+L/E/R for horizontal), an explicit alignment overrides the type-based default, and a wrapped cell grows its row to fit its lines."
---

{/* GENERATED — do not edit by hand */}

## What it does

Select a cell or range and use the toolbar's **alignment** controls — a horizontal
group (**left / center / right**), a vertical group (**top / middle / bottom**), and a
**wrap** toggle — to place text inside each cell like Google Sheets. Horizontal
alignment also has keyboard shortcuts: **Ctrl+Shift+L** (left), **Ctrl+Shift+E**
(center), **Ctrl+Shift+R** (right).

**Horizontal** alignment defaults to the cell type — numbers, dates, and booleans hug
the right, text hugs the left. Choosing an explicit alignment **overrides** that default
(left-align a number and it moves left); re-choosing the alignment a cell already has
clears it back to automatic. **Vertical** alignment defaults to **bottom** (Sheets'
default) and is visible when the row is taller than one line.

**Wrap** breaks a value too wide for its column onto multiple lines at word boundaries
(a word longer than the column breaks mid-word) and **grows the row** so every line is
visible. With wrap off, long text is clipped at the cell edge and the row keeps its
default height.

All three are **presentation** attributes, separate from the cell's value: aligning or
wrapping `=A1+B1` repositions the number without touching the formula. They are per-cell,
survive value edits, and undo/redo like any other edit.

## Verified behavior

_Matches Google Sheets:_ In Google Sheets, horizontal alignment defaults to type-based (numbers/dates/booleans hug the right, text the left); an explicit Left/Center/Right (toolbar or Ctrl+Shift+L/E/R) overrides that default and re-selecting the current alignment clears it back to automatic. Vertical alignment (Top/Middle/Bottom, toolbar only) defaults to BOTTOM and is visible when a row is taller than one line. Text wrap breaks a value too wide for its column onto multiple lines at word boundaries (a word longer than the column breaks mid-word) and GROWS the row so every line is visible; with wrap off the text overflows/clips and the row stays default height. All three are per-cell presentation attributes: they survive value/formula edits, never change the computed value, and undo/redo like any edit. (Text rotation, also offered by Sheets, is a deferred follow-up — not built in this slice.)

#### Ctrl+Shift+E centers the selected cell

**Given**
- **A1** = `hello`

**When** I click **A1**, then press `Control+Shift+e`

**Then**
- **A1** is align=center

#### an explicit left-align overrides a number's automatic right-align

**Given**
- **A1** = `42`

**When** I click **A1**, then press `Control+Shift+l`

**Then**
- **A1** shows `42`
- **A1** is align=left

#### alignment is presentation only — the value and formula are untouched

**Given**
- **A1** = `=2+3`

**When** I click **A1**, then press `Control+Shift+r`

**Then**
- **A1** shows `5`
- **A1** has formula `=2+3`
- **A1** is align=right

#### alignment survives a value edit

**Given**
- **A1** = `x`

**When** I click **A1**, then press `Control+Shift+e`, then type `changed` into **A1**

**Then**
- **A1** shows `changed`
- **A1** is align=center

#### alignment undoes and redoes with the command log

**Given**
- **A1** = `x`

**When** I click **A1**, then press `Control+Shift+r`, then undo, then redo

**Then**
- **A1** is align=right
48 changes: 48 additions & 0 deletions content/docs/learn/playground/autofit-row-height.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
title: "Rows grow to fit the tallest cell font"
description: "Enlarging a cell's font grows its row to fit; reducing it (or clearing the cell) shrinks the row back."
---

{/* GENERATED — do not edit by hand */}

## What it does

Rows size themselves to their content. Type into a cell and make its font bigger — with the **[−] size [+]** stepper or **Ctrl+Shift+Period** — and the **whole row grows** so the larger text fits instead of overflowing into its neighbours. Shrink the font (or clear the cell) and the row **shrinks back**. The row always fits its **tallest** cell, so a big font in column A grows the entire row across every column.

Only cells that actually **hold content** drive the height: a cell formatted large but left empty leaves its row at the default height — matching Google Sheets.

## Verified behavior

_Matches Google Sheets:_ In Google Sheets every row auto-fits its content: a row's height is the height of its tallest cell, so increasing a cell's font size grows the whole row to fit the larger text and reducing it (or clearing the cell) shrinks the row back. Only NON-EMPTY cells count — a cell that carries a large font but no content does not grow its row. The tallest cell in the row wins (a big font in column A grows the entire row across every column). Row height is a layout consequence of the per-cell font-size presentation attribute; it never changes the cell's value or formula and undoes/redoes with the edit that caused it. Studio floors row height at its 24px default (Sheets' default is ~21px) so unrelated rows never reflow, and models the grown height with a line-box formula rather than pixel-matching Sheets' proprietary canvas metrics.

#### Enlarging a cell's font records the size that grows its row

**Given**
- **A1** = `Big`

**When** I click **A1**, then press `Control+Shift+Period`

**Then**
- **A1** is fontSize=11

#### Reducing the font records the size that shrinks the row back

**Given**
- **A1** = `Big`

**When** I click **A1**, then press `Control+Shift+Comma`

**Then**
- **A1** is fontSize=9

#### Row auto-fit is presentation — it never touches the value

**Given**
- **A1** = `=6*7`

**When** I click **A1**, then press `Control+Shift+Period`

**Then**
- **A1** shows `42`
- **A1** has formula `=6*7`
- **A1** is fontSize=11
99 changes: 99 additions & 0 deletions content/docs/learn/playground/cell-editing-modes.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
---
title: "Enter mode vs edit mode"
description: "Typing seeds a fresh value and arrows commit + move; F2 / Enter / double-click open the cell for editing so arrows move the caret; in a formula an arrow only steers a reference when the caret sits at a reference-valid position — so editing a formula never corrupts it."
---

{/* GENERATED — do not edit by hand */}

## What it does

There are two ways to start editing a cell, and they treat the arrow keys
differently — exactly like Google Sheets:

- **Enter mode** — *type a character*. It replaces the cell's contents, and pressing
an **arrow commits the value and moves the selection** one cell in that direction
(the fast data-entry flow: `42` → Down → `7` → Down …).
- **Edit mode** — press **F2**, press **Enter** on a selected cell, or
**double-click**. The existing content opens with a **caret**, and **arrows move
the caret** through the text (**Home** / **End** jump to the ends). Double-click
drops the caret near where you clicked.

## Editing a formula (point mode)

While editing a **formula**, an arrow key does one of two things depending on where
the caret is:

- **Steer a reference** ("point mode") — only when the caret is at the **end** of the
text, right after `=`, an operator (`+ - * / ^ & < > =`), `(` or `,`. This is how you
build a formula by pointing: type `=`, arrow to a cell; type `+`, arrow to the next.
- **Move the caret** — everywhere else. Moving the caret through a completed formula
such as `=B2+B1+C1` **never** rewrites a reference into it.

This caret gate is the fix for a data-corruption bug: previously *any* arrow, at any
caret position, rewrote a reference into a formula you were only trying to move the
caret through (`=B2+B1` → `=B2+B1+D42+C1`).

## Try it

<TrueCalc mode="standalone" seed="A1==B2+B1+C1;B1=10;B2=20;C1=3" />

## Verified behavior

_Matches Google Sheets:_ In Google Sheets there are two ways an in-cell edit begins, and they behave differently. TYPING a character starts "enter" mode: the character replaces the cell's contents and pressing an arrow commits the value and moves the selection one cell in that direction. F2, Enter on a selected cell, or a DOUBLE-CLICK start "edit" mode: the existing text opens with a caret and arrows move the caret through it (Home/End jump to the ends). While editing a FORMULA, an arrow steers a cell reference ("point mode") ONLY when the caret sits at the end of the text right after "=", an operator, "(" or "," — i.e. the formula is expecting a reference next. Anywhere else the arrow moves the caret, so moving through an existing formula such as =B2+B1+C1 never rewrites a reference into it. Every edit is undoable.

#### Typing a value then pressing an arrow commits it (enter mode)

**Given**

**When** I click **A1**, then press `4`, then press `2`, then press `ArrowDown`

**Then**
- **A1** shows `42`

#### Editing a formula with arrows moves the caret and never corrupts it

**Given**
- **A1** = `=B2+B1+C1`
- **B1** = `10`
- **B2** = `20`
- **C1** = `3`

**When** I click **A1**, then press `F2`, then press `ArrowLeft`, then press `ArrowLeft`, then press `ArrowRight`, then press `Enter`

**Then**
- **A1** shows `33`
- **A1** has formula `=B2+B1+C1`

#### Arrowing from the start through a formula inserts no references

**Given**
- **A1** = `=B2+B1`
- **B1** = `10`
- **B2** = `20`

**When** I click **A1**, then press `F2`, then press `Home`, then press `ArrowRight`, then press `ArrowRight`, then press `ArrowRight`, then press `Enter`

**Then**
- **A1** shows `30`
- **A1** has formula `=B2+B1`

#### Point mode — typing = then arrowing inserts a reference

**Given**
- **B1** = `10`

**When** I click **A1**, then press `=`, then press `ArrowRight`, then press `Enter`

**Then**
- **A1** shows `10`
- **A1** has formula `=B1`

#### An edit is undoable

**Given**
- **A1** = `5`

**When** I click **A1**, then press `9`, then press `Enter`, then undo

**Then**
- **A1** shows `5`
12 changes: 3 additions & 9 deletions content/docs/learn/playground/clipboard.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,18 @@ title: "Copy, cut, and paste"
description: "Copy adjusts references to the paste target; cut moves a cell verbatim."
---

{/* GENERATED — do not edit by hand */}

## What it does

Select a cell and press **Ctrl+C** to copy or **Ctrl+X** to cut, then select a target and press **Ctrl+V** to paste.

- **Copy + paste** adjusts the formula's relative references by the paste offset — `=A1+B1` copied from **C1** to **C3** becomes `=A3+B3`, while `$`-anchored parts stay put (`=$A$1+B1` → `=$A$1+B3`). The source is left untouched and the clipboard stays loaded, so you can paste it again.
- **Cut + paste** _moves_ the cell: the formula is written to the destination **verbatim** (no reference adjustment) and the source cell is cleared. The clipboard is consumed after that one paste.

## Try it

<TrueCalc mode="standalone" seed="A1=10;B1=20;C1==A1+B1;A3=5;B3=7" />

## How it works

TrueCalc owns the calc. Copy and cut record the source cell's raw input; paste branches on which one it was. A copy adjusts the input (relative references shift, `$`-anchored references stay fixed) and writes the adjusted text to the target. A cut skips adjustment entirely — it writes the raw text unchanged and clears the source as a single undoable move — because a move should preserve exactly what the formula pointed at. Every result recomputes through the single engine, so the grid matches Google Sheets.

## Verified behavior

_Matches Google Sheets:_ In Google Sheets, copying a formula and pasting it adjusts the formula's relative references by the row/column offset (copying "=A1+B1" from C1 to C3 yields "=A3+B3"), while $-anchored parts stay fixed ("=$A$1+B1" → "=$A$1+B3"); copy leaves the source and the clipboard intact, so it can be pasted again. Cutting and pasting instead MOVES the cell: the formula is written to the destination verbatim (no reference adjustment) and the source is cleared, and the clipboard is consumed after that one paste.
_Matches Google Sheets:_ In Google Sheets, copying a formula and pasting it adjusts the formula's relative references by the row/column offset (copying "=A1+B1" from C1 to C3 yields "=A3+B3"), while $-anchored parts stay fixed ("=$A$1+B1" → "=$A$1+B3"); copy leaves the source and the clipboard intact, so it can be pasted again. Cutting and pasting instead MOVES the cell: the formula is written to the destination verbatim (no reference adjustment) and the source is cleared, and the clipboard is consumed after that one paste. (Sheets additionally rewrites OTHER formulas that referenced the moved cell so they keep pointing at it — that cross-reference remap needs engine support and is not yet modeled here; tracked as a follow-up.)

#### Copy a relative formula and paste — references shift by the offset

Expand Down
35 changes: 35 additions & 0 deletions content/docs/learn/playground/command-history.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
title: "Command history panel"
description: "A togglable side panel lists every committed operation with a human label, the cells it touched, and a timestamp; clicking an entry reverts the document to that state."
---

{/* GENERATED — do not edit by hand */}

## What it does

A togglable **History** panel (the clock-arrow icon at the right of the toolbar) lists every committed operation — typed edits, fills, pastes, clears, and every formatting toggle — as a labeled row: a human-readable story ("Bold on B2", "Filled A2:A5"), the affected cell(s) in monospace, and a timestamp. Clicking a row **reverts the document to that state** and highlights what changed. The log isn't persisted across reloads yet.

## Verified behavior

_Matches Google Sheets:_ Google Sheets has a Version History feature (File > Version history), but it operates on named SNAPSHOTS of the whole spreadsheet at a point in time — it does not list individual operations (each keystroke, each formatting toggle) as discrete, clickable, labeled entries the way this panel does. There is no Sheets equivalent to reproduce: this is a TrueCalc-original feature, built from the Store's own command log rather than replicated oracle behavior.

#### An edit and a bold each add one entry to the command log

**Given**
- **A1** = `10`

**When** I type `20` into **A2**, then click **A2**, then press `Control+b`

**Then**
- **A2** shows `20`
- **A2** is bold

#### Undoing a command removes it from the visible (committed) log

**Given**
- **A1** = `10`

**When** I type `20` into **A2**, then undo

**Then**
- **A2** shows `null`
71 changes: 71 additions & 0 deletions content/docs/learn/playground/data-import.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
title: "Import data (CSV, TSV, custom separator, XLSX)"
description: "Bring an external file into the grid — delimited text or a spreadsheet — with values, dates, and formulas coming in through the same coercion as typing, as one undoable step."
---

{/* GENERATED — do not edit by hand */}

## What it does

**Save, load, export → Import data…** brings an external file into Studio. Pick a file and the options dialog opens:

- **Delimited text** — CSV, TSV, or a **custom single-character separator**. CSV-vs-TSV is auto-detected as the default; a custom field lets you type any separator (`;`, `|`, …).
- **XLSX** — a real spreadsheet workbook. The first sheet imports by default; a multi-tab workbook lets you pick one sheet or bring in **all sheets** (one Studio sheet each).

You choose the **destination**: a **new sheet** (named from the file — the default), or the **current sheet starting at your selection**.

Everything happens **on your device** — the file is read with the browser's FileReader (delimited) or as an in-memory ArrayBuffer (XLSX) and never uploaded, so import works offline and in try mode.

## Try it

<TrueCalc mode="standalone" />

## Verified behavior

_Matches Google Sheets:_ In Google Sheets, File → Import lets you bring in a CSV/TSV/custom-separator text file or an.xlsx workbook. Imported cells are interpreted exactly as if typed: a bare number becomes a number, a date string like "7/15/2026" becomes a real (computable) date, and a cell beginning "=" becomes a formula that evaluates. A delimited parser respects double-quoted fields, so a quoted field keeps embedded separators, embedded newlines, and doubled quotes ("") as literal text. You choose where the data lands (a new sheet, or the current sheet at the selection) and, for a multi-tab workbook, which sheet(s) to bring in. The whole import is a single action that one Undo reverts.

#### Imported cells get the right types (number, date, formula)

**Given**

**When** I import `10,20,=A1+B1\n7/15/2026`

**Then**
- **A1** shows `10`
- **B1** shows `20`
- **C1** shows `30`
- **A2** shows `46218`
- **C1** has formula `=A1+B1`
- **A2** is numberFormat=date

#### One Undo reverts the whole import

**Given**

**When** I import `10,20,=A1+B1\n7/15/2026`, then click **A1**, then undo

**Then**
- **A1** shows `null`
- **B1** shows `null`
- **C1** shows `null`
- **A2** shows `null`

#### Quoted fields keep embedded separators

**Given**

**When** I import `"a,b",c`

**Then**
- **A1** shows `a,b`
- **B1** shows `c`

#### A custom separator splits columns

**Given**

**When** I import `p q` (separator ` `)

**Then**
- **A1** shows `p`
- **B1** shows `q`
Loading
Loading