@pie-players/pie-calculator-mathjs
v0.3.3
Published
Math.js calculator provider for PIE Assessment Toolkit - Open-source, always-available fallback
Readme
@pie-players/pie-calculator-mathjs
Professional, accessible calculator implementation using Math.js with DaisyUI theming.
Features
- ✅ Open Source: No licensing fees, always available
- ✅ WCAG 2.2 Level AA: Fully accessible with screen reader support
- ✅ DaisyUI Theming: Consistent design with your application
- ✅ Keyboard Navigation: Complete keyboard control with industry-standard shortcuts
- ✅ Touch-Friendly: 48x48px buttons for mobile/tablet
- ✅ High Contrast: Automatic support for high contrast and forced colors modes
- ✅ Zero Dependencies: Only requires Math.js library
- ✅ TypeScript: Full type safety
Installation
npm install @pie-players/pie-calculator-mathjs @pie-players/pie-calculatorLoad Math.js Library
The calculator requires the Math.js library to be loaded:
Via CDN (Recommended for quick start)
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/12.4.3/math.min.js"></script>Via npm
npm install mathjsimport * as math from 'mathjs';
// Make it globally available
(window as any).math = math;Usage
Basic Calculator
import { MathJsCalculatorProvider } from '@pie-players/pie-calculator-mathjs';
// Create provider
const provider = new MathJsCalculatorProvider();
// Initialize
await provider.initialize();
// Create calculator instance
const container = document.getElementById('calculator-container');
const calculator = await provider.createCalculator('basic', container, {
theme: 'light' // or 'dark', 'auto'
});
// Calculator is now ready to use!Scientific Calculator
const calculator = await provider.createCalculator('scientific', container, {
theme: 'dark'
});With DaisyUI Themes
The calculator automatically inherits your DaisyUI theme:
<div data-theme="corporate">
<div id="calculator-container"></div>
</div>Or set the theme programmatically:
const calculator = await provider.createCalculator('basic', container, {
theme: 'auto' // Respects system preference
});API
CalculatorProvider Methods
initialize()
Initialize the provider. Must be called before creating calculators.
await provider.initialize();createCalculator(type, container, config?)
Create a calculator instance.
const calculator = await provider.createCalculator(
'basic', // or 'scientific'
document.getElementById('calculator'),
{
theme: 'light', // optional: 'light' | 'dark' | 'auto'
restrictedMode: false // optional: disable advanced features
}
);Calculator Methods
getValue(): string
Get the current calculator value.
const result = calculator.getValue();
console.log(result); // "42"setValue(value: string): void
Set the calculator value.
calculator.setValue("123");clear(): void
Clear the calculator.
calculator.clear();evaluate(expression: string): Promise<string>
Evaluate a mathematical expression.
const result = await calculator.evaluate("2 + 3 * 4");
console.log(result); // "14"getHistory(): CalculationHistoryEntry[]
Get calculation history.
const history = calculator.getHistory();
history.forEach(entry => {
console.log(`${entry.expression} = ${entry.result}`);
});clearHistory(): void
Clear calculation history.
calculator.clearHistory();exportState(): CalculatorState
Export calculator state for persistence.
const state = calculator.exportState();
localStorage.setItem('calculator-state', JSON.stringify(state));importState(state: CalculatorState): void
Restore calculator state.
const state = JSON.parse(localStorage.getItem('calculator-state'));
calculator.importState(state);destroy(): void
Clean up and remove the calculator.
calculator.destroy();Keyboard Shortcuts
Basic Shortcuts
| Key | Action |
|-----|--------|
| 0-9 | Input digits |
| + - * / | Operators |
| . | Decimal point |
| Enter or = | Calculate |
| Escape or C | Clear |
| Backspace | Delete last character |
| % | Percent |
Grid Navigation
| Key | Action |
|-----|--------|
| ↑ ↓ ← → | Navigate between buttons |
| Home | First button in row |
| End | Last button in row |
| Enter or Space | Activate button |
Scientific Calculator
| Key | Function |
|-----|----------|
| S | Sine |
| O | Cosine |
| T | Tangent |
| Q | Square root |
Accessibility
This calculator is WCAG 2.2 Level AA compliant and includes:
- ✅ Full keyboard navigation
- ✅ Screen reader support (NVDA, JAWS, VoiceOver, TalkBack)
- ✅ ARIA labels and live regions
- ✅ High contrast mode support
- ✅ Focus indicators (3px solid outline)
- ✅ Touch-friendly buttons (48x48px)
- ✅ Reduced motion support
- ✅ Proper color contrast (4.5:1+ for text, 3:1+ for UI)
See ACCESSIBILITY.md for complete accessibility documentation.
Styling
DaisyUI Classes Used
The calculator uses these DaisyUI components:
card- Containerbtn- Buttonsbtn-square- Square buttonsbtn-lg- Large touch targetsbtn-primary- Operator buttonsbtn-error- Clear buttonbtn-success- Equals buttonbtn-warning- Special functionsalert alert-error- Error messagesinput- Display field
Custom Styling
You can customize the calculator using CSS:
/* Customize primary button color */
[data-theme="custom"] .btn-primary {
background-color: #your-color;
}
/* Customize calculator container */
.calculator-mathjs {
max-width: 400px;
margin: 0 auto;
}
/* Customize display */
.calculator-display-input {
font-size: 3rem;
}Examples
React Integration
import { useEffect, useRef } from 'react';
import { MathJsCalculatorProvider } from '@pie-players/pie-calculator-mathjs';
export function Calculator() {
const containerRef = useRef<HTMLDivElement>(null);
const calculatorRef = useRef<any>(null);
useEffect(() => {
const provider = new MathJsCalculatorProvider();
provider.initialize().then(() => {
if (containerRef.current) {
provider.createCalculator('basic', containerRef.current, {
theme: 'light'
}).then(calc => {
calculatorRef.current = calc;
});
}
});
return () => {
calculatorRef.current?.destroy();
};
}, []);
return <div ref={containerRef} />;
}Svelte Integration
<script lang="ts">
import { onMount, onDestroy } from 'svelte';
import { MathJsCalculatorProvider } from '@pie-players/pie-calculator-mathjs';
let container: HTMLDivElement;
let calculator: any;
onMount(async () => {
const provider = new MathJsCalculatorProvider();
await provider.initialize();
calculator = await provider.createCalculator('scientific', container, {
theme: 'dark'
});
});
onDestroy(() => {
calculator?.destroy();
});
</script>
<div bind:this={container}></div>Vue Integration
<template>
<div ref="container"></div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import { MathJsCalculatorProvider } from '@pie-players/pie-calculator-mathjs';
const container = ref(null);
const calculator = ref(null);
onMounted(async () => {
const provider = new MathJsCalculatorProvider();
await provider.initialize();
calculator.value = await provider.createCalculator(
'basic',
container.value,
{ theme: 'light' }
);
});
onUnmounted(() => {
calculator.value?.destroy();
});
</script>Modal/Dialog Usage
// Show calculator in a modal
async function showCalculatorModal() {
const modal = document.getElementById('calculator-modal');
const container = modal.querySelector('.calculator-container');
const provider = new MathJsCalculatorProvider();
await provider.initialize();
const calculator = await provider.createCalculator('basic', container);
// Show modal
modal.showModal();
// Focus trap is automatic (WCAG 2.1.2)
// Close handler
modal.addEventListener('close', () => {
calculator.destroy();
});
}Advanced Usage
Programmatic Calculation
// Perform calculation without user input
const result = await calculator.evaluate("sqrt(144) + 5 * 3");
console.log(result); // "27"State Persistence
// Save state on page unload
window.addEventListener('beforeunload', () => {
const state = calculator.exportState();
localStorage.setItem('calc-state', JSON.stringify(state));
});
// Restore state on page load
window.addEventListener('load', async () => {
const savedState = localStorage.getItem('calc-state');
if (savedState) {
const state = JSON.parse(savedState);
calculator.importState(state);
}
});Memory Operations
Memory operations are built-in:
- MC - Memory Clear
- MR - Memory Recall
- M+ - Memory Add
- M- - Memory Subtract
// Memory is automatically managed
// Access via UI or keyboard shortcuts (Alt+P, Alt+Q, Alt+R, Alt+M)Troubleshooting
Math.js Not Found
Error: Math.js library not found
Solution: Ensure Math.js is loaded before initializing the calculator:
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/12.4.3/math.min.js"></script>
<script src="your-app.js"></script>Styling Not Applied
Problem: Calculator doesn't match your DaisyUI theme
Solution: Ensure DaisyUI is loaded and the calculator is inside a themed container:
<div data-theme="corporate">
<div id="calculator-container"></div>
</div>TypeScript Errors
Error: Type errors with calculator methods
Solution: Install type definitions:
npm install --save-dev @types/mathjsBrowser Support
- ✅ Chrome/Edge 90+
- ✅ Firefox 88+
- ✅ Safari 14+
- ✅ iOS Safari 14+
- ✅ Android Chrome 90+
License
MIT
Related Packages
- @pie-players/pie-calculator - Base calculator interfaces
- @pie-players/pie-calculator-desmos - Desmos graphing calculator
- @pie-players/assessment-toolkit - Assessment player with calculator integration
Contributing
This package is part of the PIE Players monorepo. See the root README for contribution guidelines.
Support
For issues or questions:
- File an issue on GitHub
- See ACCESSIBILITY.md for accessibility-specific documentation
- Check the examples for more usage patterns
