@scriptural/react
Version:
A React-based Bible editor component library built on top of Lexical, providing components, hooks, and utilities for creating scripture editing applications
105 lines (70 loc) • 4.12 kB
Markdown
# Changelog
All notable changes to the `@scriptural/react` package will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.0.18] - 2025-01-08
### Added
- **SaveStateContext**: New context provider for tracking save state using deterministic USJ comparison
- Provides `useSaveState()` hook with `hasUnsavedChanges`, `checkForChanges`, `markAsSaved`, `getCurrentUsj`, and `getSavedUsj`
- Automatically integrated into `ScripturalEditorComposer`
- Solves the checksum inconsistency problem by comparing canonical USJ output instead of non-deterministic Lexical state
- **SaveStatePlugin**: New plugin for integrating save state tracking with history changes
- Provides `useSaveStateTracking()` hook to wrap `HistoryPlugin` onChange callbacks
- Automatically triggers USJ comparison on content changes
- Ignores non-content changes (cursor movements, selection changes)
- **Enhanced SaveButton**:
- Now includes automatic unsaved changes detection
- Shows visual indicator (red dot) when there are unsaved changes
- Automatically marks content as saved after successful `onSave` callback
- New optional prop: `showUnsavedIndicator` (default: true)
- Handles async save operations
- **Visual Feedback**: Added CSS styling for unsaved changes indicator
- `.has-unsaved-changes` class with red dot indicator
- Positioned in top-right corner of save button with subtle shadow
- **Documentation**:
- Added comprehensive "Tracking Unsaved Changes" section to GUIDES.md
- Updated API.md with detailed SaveButton documentation
- Includes examples for both basic and advanced usage patterns
- Explains the technical solution to the checksum inconsistency problem
### Changed
- **ScripturalEditorComposer**: Now wraps content with `SaveStateProvider` for automatic save state tracking
- **SaveButton**: Enhanced to use `SaveStateContext` internally for change detection
- Exported `SaveStateContext` and related hooks from package index
### Fixed
- **Checksum Inconsistency**: Resolved the issue where Lexical's internal state produced different checksums for the same logical content
- Previously, adding and removing a character would not return to the original checksum
- Clicking in the editor would change state even without content changes
- Raw Lexical JSON comparison produced false positives for "changes"
- Now uses deterministic USJ comparison which only detects actual content changes
### Technical Details
**Problem Solved**: Lexical's internal editor state is non-deterministic due to:
- Internal "dirty nodes" tracking metadata
- Selection state affecting structure
- Undo/redo stack not perfectly restoring exact internal structure
**Solution**: Compare at the USJ (Unified Scripture JSON) level instead of Lexical state level:
- USJ is deterministic - same content always produces same structure
- USJ is canonical - it's the output format
- USJ comparison only tracks actual content changes, not internal editor metadata
**Architecture**:
```
User edits → HistoryPlugin → useSaveStateTracking → SaveStateContext
→ USJ comparison → hasUnsavedChanges state → SaveButton visual indicator
```
### Migration Guide
**For Library Consumers:**
If you previously implemented custom change tracking:
```tsx
// Before (custom implementation)
const { hasUnsavedChanges, handleSave } = useUnsavedChanges(editor, onSave);
// After (use library's built-in support)
import { SaveButton } from "@scriptural/react";
<SaveButton onSave={(usj) => handleSave(usj)}>
<SaveIcon />
</SaveButton>;
// Or access state anywhere
const { hasUnsavedChanges } = useSaveState();
```
No breaking changes - the enhancement is backward compatible. Existing `SaveButton` usage continues to work, with added change detection functionality.
### References
- Addresses issue: https://github.com/pankosmia/core-client-workspace/issues/114
- Related: Lexical editor state non-determinism in history operations