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>
55 lines
1.5 KiB
TypeScript
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]
|
|
}
|