feat: add platform shells, CLI, formatting, plugins, tests, and benchmarks

Phase 4 — Platform shells:
- calcpad-macos/: SwiftUI two-column editor with Rust FFI bridge (16 files)
- calcpad-windows/: iced GUI with Windows 11 Fluent theme (7 files, 13 tests)
- calcpad-web/: React 18 + CodeMirror 6 + WASM Worker + PWA (20 files)
- calcpad-cli/: clap-based CLI with expression eval, pipe/stdin, JSON/CSV
  output, and interactive REPL with rustyline history

Phase 5 — Engine modules:
- formatting/: answer formatting (decimal/scientific/SI notation, thousands
  separators, currency), line type classification, clipboard values (93 tests)
- plugins/: CalcPadPlugin trait, PluginRegistry, Rhai scripting stub (43 tests)
- benches/: criterion benchmarks (single-line, 100/500-line sheets, DAG, incremental)
- tests/sheet_scenarios.rs: 20 real-world integration tests
- tests/proptest_fuzz.rs: 12 property-based fuzz tests

771 tests passing across workspace, 0 failures.
This commit is contained in:
C. Cassel
2026-03-17 09:46:40 -04:00
committed by C. Cassel
parent 68fa54615a
commit 806e2f1ec6
73 changed files with 11715 additions and 32 deletions

View File

@@ -0,0 +1,69 @@
/**
* React hook that captures the beforeinstallprompt event for PWA install.
* Adapted from epic/9-3-pwa-support.
*/
import { useState, useEffect, useCallback } from 'react'
interface BeforeInstallPromptEvent extends Event {
prompt(): Promise<void>
userChoice: Promise<{ outcome: 'accepted' | 'dismissed' }>
}
export interface InstallPromptState {
promptEvent: BeforeInstallPromptEvent | null
isInstalled: boolean
handleInstall: () => Promise<void>
handleDismiss: () => void
}
export function useInstallPrompt(): InstallPromptState {
const [promptEvent, setPromptEvent] = useState<BeforeInstallPromptEvent | null>(null)
const [isInstalled, setIsInstalled] = useState(false)
useEffect(() => {
// Check if already installed (standalone mode)
const isStandalone =
window.matchMedia('(display-mode: standalone)').matches ||
('standalone' in navigator && (navigator as unknown as { standalone: boolean }).standalone)
if (isStandalone) {
setIsInstalled(true)
return
}
const handler = (e: Event) => {
e.preventDefault()
setPromptEvent(e as BeforeInstallPromptEvent)
}
const installedHandler = () => {
setIsInstalled(true)
setPromptEvent(null)
}
window.addEventListener('beforeinstallprompt', handler)
window.addEventListener('appinstalled', installedHandler)
return () => {
window.removeEventListener('beforeinstallprompt', handler)
window.removeEventListener('appinstalled', installedHandler)
}
}, [])
const handleInstall = useCallback(async () => {
if (!promptEvent) return
await promptEvent.prompt()
const result = await promptEvent.userChoice
if (result.outcome === 'accepted') {
setIsInstalled(true)
}
setPromptEvent(null)
}, [promptEvent])
const handleDismiss = useCallback(() => {
setPromptEvent(null)
}, [])
return { promptEvent, isInstalled, handleInstall, handleDismiss }
}

View File

@@ -0,0 +1,27 @@
/**
* React hook that tracks whether the browser is online or offline.
* Adapted from epic/9-3-pwa-support.
*/
import { useState, useEffect } from 'react'
export function useOnlineStatus(): boolean {
const [isOnline, setIsOnline] = useState(
typeof navigator !== 'undefined' ? navigator.onLine : true,
)
useEffect(() => {
const handleOnline = () => setIsOnline(true)
const handleOffline = () => setIsOnline(false)
window.addEventListener('online', handleOnline)
window.addEventListener('offline', handleOffline)
return () => {
window.removeEventListener('online', handleOnline)
window.removeEventListener('offline', handleOffline)
}
}, [])
return isOnline
}