feat(abacus-react): comprehensive README overhaul with current capabilities

- Complete documentation of interactive features and tutorial system
- Detailed examples for all major use cases and APIs
- Place-value based targeting system documentation
- Progressive tutorial steps and directional gesture guides
- Granular styling customization examples
- Educational use case implementations
- Full TypeScript interface documentation
- Accessibility and color scheme information
- Live Storybook documentation links

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Thomas Hallock 2025-09-28 09:16:10 -05:00
parent 176a1961d0
commit 0ce351e572
1 changed files with 350 additions and 175 deletions

View File

@ -1,18 +1,21 @@
# @soroban/abacus-react
A comprehensive React component for rendering interactive Soroban (Japanese abacus) visualizations with advanced customization and tutorial capabilities.
A comprehensive React component for rendering interactive Soroban (Japanese abacus) visualizations with advanced tutorial capabilities, directional gestures, and complete visual customization.
## Features
- 🎯 **Interactive beads** - Click to toggle or use directional gestures
- 🎨 **Complete visual customization** - Style every element individually
- 📱 **Responsive scaling** - Configurable scale factor for different sizes
- 🎯 **Interactive beads** - Click to toggle or use directional drag gestures
- 🎨 **Complete visual customization** - Style every element individually with granular control
- 📱 **Responsive scaling** - Configurable scale factor for different display sizes
- 🌈 **Multiple color schemes** - Monochrome, place-value, alternating, heaven-earth
- 🎭 **Flexible shapes** - Diamond, square, or circle beads
- ⚡ **React Spring animations** - Smooth bead movements and transitions
- 🔧 **Developer-friendly** - Comprehensive hooks and callback system
- 🎓 **Tutorial system** - Built-in overlay and guidance capabilities
- 🧩 **Framework-free SVG** - Complete control over rendering
- 🎭 **Flexible bead shapes** - Diamond, square, or circle beads
- ⚡ **React Spring animations** - Smooth bead movements and state transitions
- 🔧 **Developer-friendly** - Comprehensive hooks, callbacks, and ref system
- 🎓 **Tutorial system** - Built-in overlay system with tooltips and highlights
- 🧩 **Framework-free SVG** - Complete control over rendering and styling
- 🏗️ **Type-safe APIs** - Full TypeScript support with branded types
- 📐 **Precise positioning** - Place-value based bead targeting system
- 🎮 **Directional gestures** - Natural drag interactions for bead manipulation
## Installation
@ -40,14 +43,13 @@ The package is published to both npm and GitHub Packages simultaneously for redu
## Quick Start
### Basic Usage
Simple abacus showing a number
<img src="https://raw.githubusercontent.com/antialias/soroban-abacus-flashcards/main/packages/abacus-react/examples/basic-usage.svg" alt="Basic Usage">
Simple static abacus display:
```tsx
import { AbacusReact } from '@soroban/abacus-react';
<AbacusReact
value={123}
columns={3}
@ -58,9 +60,7 @@ Simple abacus showing a number
### Interactive Mode
Clickable abacus with animations
<img src="https://raw.githubusercontent.com/antialias/soroban-abacus-flashcards/main/packages/abacus-react/examples/interactive.svg" alt="Interactive Mode">
Clickable abacus with animations and callbacks:
```tsx
<AbacusReact
@ -68,6 +68,7 @@ Clickable abacus with animations
columns={3}
interactive={true}
animated={true}
gestures={true}
showNumbers={true}
callbacks={{
onValueChange: (newValue) => console.log('New value:', newValue),
@ -78,9 +79,7 @@ Clickable abacus with animations
### Custom Styling
Personalized colors and highlights
<img src="https://raw.githubusercontent.com/antialias/soroban-abacus-flashcards/main/packages/abacus-react/examples/custom-styling.svg" alt="Custom Styling">
Personalized colors and visual themes:
```tsx
<AbacusReact
@ -88,22 +87,23 @@ Personalized colors and highlights
columns={3}
colorScheme="place-value"
beadShape="circle"
colorPalette="nature"
customStyles={{
heavenBeads: { fill: '#ff6b35' },
earthBeads: { fill: '#3498db' },
numerals: { color: '#2c3e50', fontWeight: 'bold' }
heavenBeads: { fill: '#2ecc71', stroke: '#27ae60' },
earthBeads: { fill: '#3498db', stroke: '#2980b9' },
numerals: { color: '#2c3e50', fontWeight: 'bold' },
reckoningBar: { stroke: '#34495e', strokeWidth: 3 }
}}
highlightBeads={[
{ columnIndex: 1, beadType: 'heaven' }
{ placeValue: 2, beadType: 'heaven' }, // Hundreds place heaven bead
{ placeValue: 0, beadType: 'earth', position: 1 } // Ones place, second earth bead
]}
/>
```
### Tutorial System
Educational guidance with tooltips
<img src="https://raw.githubusercontent.com/antialias/soroban-abacus-flashcards/main/packages/abacus-react/examples/tutorial-mode.svg" alt="Tutorial System">
Educational guidance with interactive overlays:
```tsx
<AbacusReact
@ -111,34 +111,58 @@ Educational guidance with tooltips
columns={2}
interactive={true}
overlays={[{
id: 'tip',
id: 'tutorial-tip',
type: 'tooltip',
target: { type: 'bead', columnIndex: 0, beadType: 'earth', beadPosition: 1 },
content: <div>Click this bead!</div>,
target: {
type: 'bead',
columnIndex: 0,
beadType: 'earth',
beadPosition: 1
},
content: (
<div style={{
background: '#333',
color: 'white',
padding: '8px',
borderRadius: '4px',
fontSize: '14px'
}}>
Click this bead to add 1!
</div>
),
offset: { x: 0, y: -30 }
}]}
stepBeadHighlights={[{
placeValue: 0,
beadType: 'earth',
position: 1,
stepIndex: 0,
direction: 'activate',
order: 1
}]}
showDirectionIndicators={true}
callbacks={{
onBeadClick: (event) => {
if (event.columnIndex === 0 && event.beadType === 'earth' && event.position === 1) {
console.log('Correct!');
if (event.placeValue === 0 && event.beadType === 'earth' && event.position === 1) {
console.log('Tutorial step completed!');
}
}
}}
/>
```
## Core API
### Basic Props
### AbacusConfig Interface
```tsx
interface AbacusConfig {
// Display
value?: number; // 0-99999, number to display
columns?: number | 'auto'; // Number of columns or auto-calculate
showNumbers?: boolean; // Show place value numbers
showNumbers?: boolean; // Show place value numbers below
scaleFactor?: number; // 0.5 - 3.0, size multiplier
showEmptyColumns?: boolean; // Display columns with value 0
// Appearance
beadShape?: 'diamond' | 'square' | 'circle';
@ -148,12 +172,21 @@ interface AbacusConfig {
// Interaction
interactive?: boolean; // Enable user interactions
animated?: boolean; // Enable animations
gestures?: boolean; // Enable drag gestures
animated?: boolean; // Enable React Spring animations
gestures?: boolean; // Enable directional drag gestures
// Advanced
customStyles?: AbacusCustomStyles; // Granular styling control
callbacks?: AbacusCallbacks; // Event handlers
overlays?: AbacusOverlay[]; // Tutorial overlay system
highlightBeads?: BeadHighlight[]; // Highlight specific beads
stepBeadHighlights?: StepBeadHighlight[]; // Progressive tutorial highlighting
showDirectionIndicators?: boolean; // Show movement direction indicators
disabledBeads?: BeadHighlight[]; // Disable specific bead interactions
}
```
### Event Callbacks
### Event System
```tsx
interface AbacusCallbacks {
@ -161,117 +194,211 @@ interface AbacusCallbacks {
onBeadClick?: (event: BeadClickEvent) => void;
onBeadHover?: (event: BeadClickEvent) => void;
onBeadLeave?: (event: BeadClickEvent) => void;
onColumnClick?: (columnIndex: number) => void;
onNumeralClick?: (columnIndex: number, value: number) => void;
onColumnClick?: (columnIndex: number, event: React.MouseEvent) => void;
onNumeralClick?: (columnIndex: number, value: number, event: React.MouseEvent) => void;
onBeadRef?: (bead: BeadConfig, element: SVGElement | null) => void;
}
interface BeadClickEvent {
columnIndex: number; // 0, 1, 2...
bead: BeadConfig; // Complete bead configuration
columnIndex: number; // 0, 1, 2... (array index)
placeValue: ValidPlaceValues; // 0=ones, 1=tens, 2=hundreds...
beadType: 'heaven' | 'earth'; // Type of bead
position: number; // Position within type (0-3 for earth)
active: boolean; // Current state
active: boolean; // Current activation state
value: number; // Numeric value (1 or 5)
bead: BeadConfig; // Full bead configuration
event: React.MouseEvent; // Original mouse event
}
```
## Advanced Customization
## Advanced Features
### Granular Styling
### Place-Value Based Targeting
Target beads by mathematical place value instead of visual column position:
```tsx
// Target beads by place value (recommended)
const placeValueHighlights = [
{ placeValue: 0, beadType: 'earth', position: 2 }, // Ones place, 3rd earth bead
{ placeValue: 1, beadType: 'heaven' }, // Tens place, heaven bead
{ placeValue: 2, beadType: 'earth', position: 0 } // Hundreds place, 1st earth bead
];
// Legacy column-index targeting (still supported)
const columnHighlights = [
{ columnIndex: 2, beadType: 'earth', position: 2 }, // Rightmost column
{ columnIndex: 1, beadType: 'heaven' }, // Middle column
{ columnIndex: 0, beadType: 'earth', position: 0 } // Leftmost column
];
<AbacusReact highlightBeads={placeValueHighlights} />
```
### Progressive Tutorial Steps
Create multi-step interactive tutorials:
```tsx
const tutorialSteps = [
{
placeValue: 0,
beadType: 'earth',
position: 0,
stepIndex: 0,
direction: 'activate',
order: 1
},
{
placeValue: 0,
beadType: 'earth',
position: 1,
stepIndex: 1,
direction: 'activate',
order: 1
},
{
placeValue: 1,
beadType: 'heaven',
stepIndex: 2,
direction: 'activate',
order: 1
}
];
<AbacusReact
stepBeadHighlights={tutorialSteps}
currentStep={currentStepIndex}
showDirectionIndicators={true}
interactive={true}
/>
```
### Granular Style Customization
Target any visual element with precise control:
```tsx
const customStyles = {
const advancedStyles = {
// Global defaults
heavenBeads: { fill: '#ff6b35' },
earthBeads: { fill: '#3498db' },
heavenBeads: { fill: '#e74c3c', stroke: '#c0392b' },
earthBeads: { fill: '#3498db', stroke: '#2980b9' },
activeBeads: { opacity: 1.0 },
inactiveBeads: { opacity: 0.3 },
// Column-specific overrides
// Column-specific overrides (by array index)
columns: {
0: { // Hundreds column
heavenBeads: { fill: '#e74c3c' },
earthBeads: { fill: '#2ecc71' }
0: { // Leftmost column (highest place value)
heavenBeads: { fill: '#f39c12' },
earthBeads: { fill: '#e67e22' },
backgroundGlow: { fill: '#fff3cd', opacity: 0.3 }
}
},
// Individual bead targeting
// Individual bead targeting (by array index)
beads: {
1: { // Middle column
heaven: { fill: '#f39c12' },
heaven: { fill: '#9b59b6' },
earth: {
0: { fill: '#1abc9c' }, // First earth bead
3: { fill: '#e67e22' } // Fourth earth bead
1: { fill: '#16a085' }, // Second earth bead
2: { fill: '#17a2b8' }, // Third earth bead
3: { fill: '#138496' } // Fourth earth bead
}
}
},
// UI elements
reckoningBar: { stroke: '#34495e', strokeWidth: 3 },
columnPosts: { stroke: '#7f8c8d' },
columnPosts: { stroke: '#7f8c8d', strokeWidth: 2 },
numerals: {
color: '#2c3e50',
fontSize: '14px',
fontFamily: 'monospace'
fontSize: '16px',
fontFamily: 'monospace',
fontWeight: 'bold'
}
};
<AbacusReact customStyles={customStyles} />
<AbacusReact customStyles={advancedStyles} />
```
### Tutorial and Overlay System
### Overlay System
Create interactive educational experiences:
Create rich interactive educational experiences:
```tsx
const overlays = [
const educationalOverlays = [
{
id: 'welcome-tooltip',
id: 'value-explanation',
type: 'tooltip',
target: {
type: 'bead',
columnIndex: 0,
beadType: 'earth',
beadPosition: 0
},
target: { type: 'bead', columnIndex: 0, beadType: 'heaven' },
content: (
<div style={{
background: '#333',
color: 'white',
padding: '8px',
borderRadius: '4px'
}}>
Click me to start!
<div className="tutorial-tooltip">
<h4>Heaven Bead</h4>
<p>Worth 5 in this place value</p>
<button onClick={() => nextStep()}>Got it!</button>
</div>
),
offset: { x: 0, y: -30 }
offset: { x: 0, y: -40 }
},
{
id: 'direction-arrow',
type: 'arrow',
target: { type: 'bead', columnIndex: 1, beadType: 'earth', beadPosition: 0 },
content: <div className="arrow-down"></div>,
offset: { x: 0, y: -20 }
}
];
<AbacusReact
overlays={overlays}
highlightBeads={[
{ columnIndex: 0, beadType: 'earth', position: 0 }
]}
overlays={educationalOverlays}
interactive={true}
callbacks={{
onBeadClick: (event) => {
if (event.columnIndex === 0 && event.beadType === 'earth' && event.position === 0) {
console.log('Tutorial step completed!');
}
}
onBeadClick: handleTutorialProgression
}}
/>
```
### Dimension Calculation Hook
Get exact sizing information for layout planning:
```tsx
import { useAbacusDimensions } from '@soroban/abacus-react';
function ResponsiveAbacusContainer() {
const dimensions = useAbacusDimensions(
5, // columns
1.2, // scale factor
true // show numbers
);
return (
<div
style={{
width: dimensions.width,
height: dimensions.height,
border: '1px solid #ccc',
padding: '10px'
}}
>
<AbacusReact
columns={5}
scaleFactor={1.2}
showNumbers={true}
value={12345}
/>
</div>
);
}
```
### Bead Reference System
Access individual bead DOM elements for advanced positioning:
```tsx
function AdvancedExample() {
function AdvancedPositioning() {
const beadRefs = useRef(new Map<string, SVGElement>());
const handleBeadRef = (bead: BeadConfig, element: SVGElement | null) => {
@ -279,92 +406,16 @@ function AdvancedExample() {
if (element) {
beadRefs.current.set(key, element);
// Now you can position tooltips, highlights, etc. precisely
// Position custom elements relative to beads
const rect = element.getBoundingClientRect();
console.log(`Bead at column ${bead.columnIndex} is at:`, rect);
console.log(`Bead at column ${bead.columnIndex} positioned at:`, rect);
}
};
return (
<AbacusReact
callbacks={{ onBeadRef: handleBeadRef }}
// ... other props
/>
);
}
```
## Hooks
### useAbacusDimensions
Get exact sizing information for layout planning:
```tsx
import { useAbacusDimensions } from '@soroban/abacus-react';
function MyComponent() {
const dimensions = useAbacusDimensions(3, 1.2); // 3 columns, 1.2x scale
return (
<div style={{ width: dimensions.width, height: dimensions.height }}>
<AbacusReact columns={3} scaleFactor={1.2} />
</div>
);
}
```
## Educational Use Cases
### Interactive Math Lessons
```tsx
function MathLesson() {
const [problem, setProblem] = useState({ a: 23, b: 45 });
const [step, setStep] = useState('show-first');
return (
<div>
<h3>Add {problem.a} + {problem.b}</h3>
<AbacusReact
value={step === 'show-first' ? problem.a : 0}
interactive={step === 'add-second'}
callbacks={{
onValueChange: (value) => {
if (value === problem.a + problem.b) {
celebrate();
}
}
}}
/>
</div>
);
}
```
### Assessment Tools
```tsx
function AbacusQuiz() {
const [answers, setAnswers] = useState([]);
const checkAnswer = (event: BeadClickEvent) => {
const isCorrect = validateBeadClick(event, expectedAnswer);
recordAnswer(event, isCorrect);
if (isCorrect) {
showSuccessFeedback();
} else {
showHint(event);
}
};
return (
<AbacusReact
interactive={true}
callbacks={{ onBeadClick: checkAnswer }}
customStyles={getAnswerHighlighting(answers)}
/>
);
}
@ -372,7 +423,7 @@ function AbacusQuiz() {
## TypeScript Support
Full TypeScript definitions included:
Full TypeScript definitions with branded types for enhanced type safety:
```tsx
import {
@ -383,15 +434,134 @@ import {
AbacusCustomStyles,
AbacusOverlay,
AbacusCallbacks,
useAbacusDimensions
useAbacusDimensions,
PlaceValueBead,
ColumnIndexBead,
StepBeadHighlight,
PlaceValue,
ColumnIndex,
ValidPlaceValues,
EarthBeadPosition
} from '@soroban/abacus-react';
// All interfaces fully typed for excellent developer experience
// Branded types prevent mixing place values and column indices
const placeValue: ValidPlaceValues = 2; // hundreds place
const earthPosition: EarthBeadPosition = 3; // fourth earth bead
// Type-safe bead specification
const bead: PlaceValueBead = {
placeValue: 1, // tens place
beadType: 'earth',
position: 2 // third earth bead
};
```
## Educational Use Cases
### Interactive Math Lessons
```tsx
function AdditionLesson() {
const [problem] = useState({ a: 23, b: 45 });
const [step, setStep] = useState('show-first');
const [userValue, setUserValue] = useState(0);
const checkAnswer = (newValue: number) => {
setUserValue(newValue);
if (newValue === problem.a + problem.b) {
setStep('completed');
showCelebration();
}
};
return (
<div className="math-lesson">
<h3>Add {problem.a} + {problem.b}</h3>
<AbacusReact
value={step === 'show-first' ? problem.a : userValue}
columns={3}
interactive={step === 'user-input'}
animated={true}
showNumbers={true}
callbacks={{ onValueChange: checkAnswer }}
highlightBeads={step === 'hint' ? getHintBeads() : []}
/>
{step === 'completed' && (
<div className="success">
🎉 Correct! {problem.a} + {problem.b} = {problem.a + problem.b}
</div>
)}
</div>
);
}
```
### Assessment and Quizzing
```tsx
function AbacusQuiz() {
const [answers, setAnswers] = useState<BeadClickEvent[]>([]);
const [feedback, setFeedback] = useState<string>('');
const validateAnswer = (event: BeadClickEvent) => {
const isCorrect = checkBeadClick(event, expectedAnswer);
setAnswers(prev => [...prev, event]);
if (isCorrect) {
setFeedback('Correct! Well done.');
advanceToNextQuestion();
} else {
setFeedback('Try again. Remember: this bead represents...');
showHint(event);
}
};
return (
<div className="abacus-quiz">
<AbacusReact
value={currentQuestionValue}
interactive={true}
callbacks={{ onBeadClick: validateAnswer }}
customStyles={getAnswerHighlighting(answers)}
overlays={currentHints}
/>
<div className="feedback">{feedback}</div>
</div>
);
}
```
## Color Schemes and Accessibility
### Built-in Color Schemes
- **`monochrome`** - Single color for all beads
- **`place-value`** - Different colors for each place value column
- **`alternating`** - Alternating colors between columns
- **`heaven-earth`** - Different colors for heaven vs earth beads
### Accessibility Palettes
- **`colorblind`** - High contrast, colorblind-friendly palette
- **`grayscale`** - Monochrome grayscale for maximum compatibility
- **`mnemonic`** - Colors that aid memory and learning
- **`nature`** - Earth-tone palette for reduced eye strain
```tsx
<AbacusReact
colorScheme="place-value"
colorPalette="colorblind"
value={12345}
columns={5}
/>
```
## Publishing and Versioning
This package uses [semantic-release](https://semantic-release.gitbook.io/) for automated publishing to npm. Versions are determined by conventional commit messages:
This package uses [semantic-release](https://semantic-release.gitbook.io/) for automated publishing. Versions are determined by conventional commit messages:
### Commit Message Format
@ -399,18 +569,18 @@ Use these prefixes for commits that affect the `packages/abacus-react` directory
```bash
# New features (minor version bump)
feat(abacus-react): add new bead animation system
feat(abacus-react): add gesture recognition system
# Bug fixes (patch version bump)
fix(abacus-react): resolve gesture detection issue
fix(abacus-react): resolve animation timing issues
# Performance improvements (patch version bump)
perf(abacus-react): optimize bead rendering
perf(abacus-react): optimize bead rendering performance
# Breaking changes (major version bump)
feat(abacus-react)!: change callback signature
feat(abacus-react)!: redesign callback API
# or
feat(abacus-react): redesign API
feat(abacus-react): change component interface
BREAKING CHANGE: callback functions now receive different parameters
```
@ -438,10 +608,15 @@ pnpm storybook
pnpm release:dry-run
```
## Live Documentation
- **Storybook**: [Component examples and documentation](https://antialias.github.io/soroban-abacus-flashcards/abacus-react/)
- **Source Code**: [GitHub Repository](https://github.com/antialias/soroban-abacus-flashcards/tree/main/packages/abacus-react)
## Contributing
Contributions welcome! Please see our contributing guidelines and feel free to submit issues or pull requests.
Contributions welcome! Please see our [contributing guidelines](../../CONTRIBUTING.md) and feel free to submit issues or pull requests.
## License
MIT License - see LICENSE file for details.
MIT License - see [LICENSE](../../LICENSE) file for details.