Files
calctext/calcpad-web/src/editor/inline-results.ts
C. Cassel 0d38bd3108 feat(web): implement complete workspace with themes, tabs, sidebar, and mobile
Transform CalcText from a single-document calculator into a full workspace
application with multi-document support, theming, and responsive mobile experience.

- Theme system: 5 presets (Light, Dark, Matrix, Midnight, Warm) + accent colors
- Document model with localStorage persistence and auto-save
- Tab bar with keyboard shortcuts (Ctrl+N/W/Tab/1-9), rename, close
- Sidebar with search, recent, favorites, folders, templates, drag-and-drop
- 5 templates: Budget, Invoice, Unit Converter, Trip Planner, Loan Calculator
- Status bar with cursor position, engine status, dedication to Igor Cassel
- Results panel: type-specific colors, click-to-copy, error hints
- Format toolbar: H, B, I, //, color labels with live preview toggle
- Syntax highlighting using theme CSS variables
- Error hover tooltips
- Mobile: bottom results tray, sidebar drawer, touch targets, safe areas
- Docker multi-stage build (Rust WASM + Vite + Nginx)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 09:12:05 -04:00

55 lines
1.5 KiB
TypeScript

/**
* CodeMirror 6 extension for zebra-striped editor lines.
*
* Previously also contained inline result widgets, but results
* are now rendered in a separate ResultsPanel component.
*/
import { Decoration, EditorView, ViewPlugin } from '@codemirror/view'
import type { DecorationSet, ViewUpdate } from '@codemirror/view'
import type { Extension } from '@codemirror/state'
/**
* ViewPlugin that applies alternating background colors (zebra striping)
* to even-numbered editor lines, helping users visually connect
* expressions on the left to their inline results on the right.
*/
export const stripedLines = ViewPlugin.fromClass(
class {
decorations: DecorationSet
constructor(view: EditorView) {
this.decorations = buildStripeDecorations(view)
}
update(update: ViewUpdate) {
if (update.docChanged || update.viewportChanged) {
this.decorations = buildStripeDecorations(update.view)
}
}
},
{
decorations: (v) => v.decorations,
},
)
const stripeDeco = Decoration.line({ class: 'cm-stripe' })
function buildStripeDecorations(view: EditorView): DecorationSet {
const decorations: Array<ReturnType<typeof stripeDeco.range>> = []
for (let i = 1; i <= view.state.doc.lines; i++) {
if (i % 2 === 0) {
const line = view.state.doc.line(i)
decorations.push(stripeDeco.range(line.from))
}
}
return Decoration.set(decorations)
}
/**
* Creates the striped-lines extension for the editor.
*/
export function stripedLinesExtension(): Extension {
return [stripedLines]
}