Skip to content

feat(text): chevron expand + Monaco diff for long text/longtext cells#208

Merged
debba merged 5 commits into
TabularisDB:mainfrom
NewtTheWolf:feat/longtext-chevron-expand-diff
May 18, 2026
Merged

feat(text): chevron expand + Monaco diff for long text/longtext cells#208
debba merged 5 commits into
TabularisDB:mainfrom
NewtTheWolf:feat/longtext-chevron-expand-diff

Conversation

@NewtTheWolf
Copy link
Copy Markdown
Contributor

@NewtTheWolf NewtTheWolf commented May 17, 2026

Summary

Extends the chevron-expand + Monaco diff affordance (PR #181) from JSON/JSONB cells to plain string columns whose value is long enough to be cumbersome inline. Closes #207.

  • New isLongTextCellTarget: text-like column AND value > 80 chars or contains a newline. Scoped so JSON / BLOB / geometry / date paths are untouched.
  • TextCell renders a single-line preview with a chevron (multi-line values get a substitution). Per request, no separate viewer window for text — the chevron is the only entry point.
  • TextExpansionEditor opens inline below the row: Monaco in plaintext mode with a manual Diff toggle (default off) against the original cell value.
  • FieldEditor swaps the plain textarea for a Monaco-based TextInput when the value is long, giving the sidebar a diff toggle too.
  • Side-by-side toggle added when diff is active — applied uniformly to JSON and text, in both the inline expansion and the input panel. Default stays unified.

Files

  • New: src/utils/text.ts, tests/utils/text.test.ts
  • New: TextCell, TextCodeEditor, TextDiffEditor, TextExpansionEditor, TextInput
  • Modified: DataGrid.tsx (expansion state generalised with a kind discriminator; JSON path unchanged), FieldEditor.tsx, JsonInput.tsx, JsonExpansionEditor.tsx (side-by-side toggle), i18n/locales/en.json
  • Seed: demo/init/{mysql,postgres}/04-text-demo.sqltabularis_demo.text_demo, 9 rows covering every edge case below

Test setup

docker compose -f demo/docker-compose.yml down -v
docker compose -f demo/docker-compose.yml up -d

Then open the tabularis_demo database (MySQL or Postgres) and browse the text_demo table.

Test plan

Automated:

  • pnpm typecheck
  • pnpm lint
  • pnpm test tests/utils/text.test.ts (15/15)
  • pnpm build

Manual — DataGrid chevron + inline expansion, by row in text_demo:

  • Row 1 (short): no chevron on any column — values stay in the inline textarea editor on double-click.
  • Row 2 (long single-line): body shows a chevron; preview is single-line; expand → plain Monaco editor, no symbol.
  • Row 3 (multi-line short): chevron triggers via newline branch even though length < 80; preview shows separators.
  • Row 4 (markdown article): expand body, edit a heading, toggle Diff on → modified lines highlighted; toggle Side-by-side → two-pane view; cancel restores original.
  • Row 5 (code snippet): expand body, change indentation on one line, Diff toggle shows whitespace-aware hunks.
  • Row 6 (SQL query): expand body, edit a clause, save → row gets the pending-change indicator; refresh confirms persistence.
  • Row 7 (long varchar): chevron fires on the summary VARCHAR(500) column, not just on TEXT.
  • Row 8 (all null): no chevron anywhere; null cells render the regular NULL placeholder.
  • Row 9 (unicode + emoji): Monaco renders multi-script + emoji glyphs correctly in editor, Diff, and Side-by-side.

Manual — RowEditorSidebar (open via context menu → "Open Sidebar Editor"):

  • Long fields (body on rows 2/4/5/6/9, summary on row 7) render the Monaco-based TextInput with the Diff / Side-by-side toggles.
  • Short fields (label everywhere, summary on row 1) keep the plain textarea.

Regressions:

  • JSON cells (tabularis_demo.json_demo) still get the chevron, the open-viewer window button, and the same JSON tokenizer — unchanged from main.
  • BLOB / geometry / date columns unchanged.

@NewtTheWolf NewtTheWolf marked this pull request as draft May 17, 2026 17:39
Mirrors the JSON cell affordance from PR TabularisDB#181 for plain string columns
whose value is long enough to be cumbersome in the inline grid cell.
Closes TabularisDB#207.

- isLongTextCellTarget — text-like column + value > 80 chars or contains
  a newline. JSON / BLOB / geometry / date paths stay untouched.
- TextCell renders a single-line preview with a chevron (multi-line
  values get a ⏎ substitution). No separate viewer window — chevron
  is the only entry point per design discussion.
- TextExpansionEditor opens inline below the row: Monaco in plaintext
  mode with a manual Diff toggle (default off) against the original.
- FieldEditor swaps the plain textarea for Monaco-based TextInput when
  the sidebar value is long, so the diff toggle is available there too.
- Width-aware Side-by-side toggle (Columns2) appears next to the Diff
  button whenever the editor's container is ≥ 480px. Below that the
  unified diff is the only mode, so the button doesn't promise a
  layout that won't fit. Same gating applied uniformly to JSON.
- Json/Text Monaco wrappers are unified into a single CellCodeEditor /
  CellDiffEditor pair that takes a language prop, replacing the four
  per-language wrappers.
Long-standing Monaco bug: the read-only original editor in a
side-by-side DiffEditor refuses to wrap long lines no matter how
wordWrap or diffWordWrap is set on the diff editor or via
updateOptions on the inner editors. Fixes here:

- useInlineViewWhenSpaceIsLimited: false — Monaco's inline-fallback
  code path poisons the original pane's wrap state even when the
  fallback isn't actually being used (Monaco discussions #4454, #4701).
- key={renderSideBySide ? "sbs" : "inline"} — toggling renderSideBySide
  at runtime can leave the original pane's wrap unrecoverable (issue
  #3346). React-key remounting sidesteps it by forcing a clean Monaco
  instance per mode.
- diffWordWrap: "on" — explicitly inherit wrap into the diff layer.
- Drop originalEditable: false and apply readOnly per-editor via
  updateOptions, which Monaco respects without breaking layout.
The fixed 384px (w-96) width left no room for the new Monaco-based
text input, especially with the side-by-side diff toggle. Adds a
4px drag handle on the left edge of RowEditorSidebar driven by a
new useRowEditorResize hook: width is clamped to [320px, 90% of
viewport] and persisted to localStorage. Default stays 384px so
nothing changes for users who don't drag.
…ting

Adds a focused seed alongside json_demo for the long-text chevron +
Monaco diff feature. Nine rows, each targeting a specific edge case:
short / long single-line / multi-line short / markdown article /
code snippet / multi-line SQL / long VARCHAR(500) / all-NULL / unicode.

MySQL relies on its default \\n-in-string handling; Postgres uses
E'...' escape-string syntax for the multi-line bodies.
The mysql client used by docker-entrypoint-initdb.d does not default
to utf8mb4 in MySQL 8's official image; emoji and CJK literals in
the JSON / blog seeds were double-encoded on insert, so drivers that
honor utf8mb4 read back mojibake even though the columns themselves
are utf8mb4. Adding SET NAMES utf8mb4 at the top of each seed makes
the insert path round-trip cleanly. Requires a fresh volume
(docker compose down -v) to take effect.
@NewtTheWolf NewtTheWolf force-pushed the feat/longtext-chevron-expand-diff branch from e1e07ed to e4cd824 Compare May 17, 2026 19:58
@NewtTheWolf NewtTheWolf marked this pull request as ready for review May 17, 2026 20:00
@debba
Copy link
Copy Markdown
Collaborator

debba commented May 18, 2026

LGTM.
I will merge it soon.

@debba debba merged commit 2934bc1 into TabularisDB:main May 18, 2026
1 check passed
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.

Extend chevron expand + diff view to text / longtext cells

2 participants