From 948dfa7a0dec6b79bed30bd3a5cd9e12d25bfba1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Feb 2026 03:57:15 +0000 Subject: [PATCH 1/3] Initial plan From 147f931f650cd115ed087bc97f66ba2f78ffd083 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Feb 2026 03:59:02 +0000 Subject: [PATCH 2/3] Add comprehensive TextMorph component documentation Co-authored-by: lochie <1930210+lochie@users.noreply.github.com> --- packages/torph/TEXTMORPH.md | 440 ++++++++++++++++++++++++++++++++++++ 1 file changed, 440 insertions(+) create mode 100644 packages/torph/TEXTMORPH.md diff --git a/packages/torph/TEXTMORPH.md b/packages/torph/TEXTMORPH.md new file mode 100644 index 0000000..f63caeb --- /dev/null +++ b/packages/torph/TEXTMORPH.md @@ -0,0 +1,440 @@ +# TextMorph Component Documentation + +## Overview + +TextMorph is an animated text morphing component that smoothly transitions between text changes with character-level animations. It provides a fluid, visually appealing way to update text content by animating individual characters or words as they enter, exit, or move positions. + +## Core Architecture + +### TextMorph Class + +The `TextMorph` class is the core implementation that handles all text morphing animations. It works with any framework or vanilla JavaScript. + +#### Constructor + +```typescript +constructor(options: TextMorphOptions) +``` + +Creates a new TextMorph instance attached to an HTML element. + +**Example:** +```javascript +const morph = new TextMorph({ + element: document.getElementById('my-text'), + duration: 400, + ease: 'cubic-bezier(0.19, 1, 0.22, 1)', + locale: 'en', + debug: false +}); +``` + +#### Methods + +##### `update(value: string)` + +Updates the text content with a smooth animation transition. + +```javascript +morph.update('Hello World'); +``` + +##### `destroy()` + +Cleans up the TextMorph instance, canceling all animations and removing attributes. + +```javascript +morph.destroy(); +``` + +### How It Works + +1. **Text Segmentation**: TextMorph uses `Intl.Segmenter` to break text into graphemes (individual characters) or words based on locale. +2. **Position Tracking**: It measures the position of each text segment before and after updates. +3. **Animation**: Characters that exist in both old and new text are animated from their old position to their new position. +4. **Entry Animation**: New characters fade in and scale slightly. +5. **Exit Animation**: Removed characters fade out and move toward nearby characters. +6. **Container Resize**: The container smoothly animates its width and height to accommodate the new text. + +## Types + +### TextMorphOptions + +The main configuration interface for TextMorph instances. + +```typescript +interface TextMorphOptions { + element: HTMLElement; + locale?: Intl.LocalesArgument; + duration?: number; + ease?: string; + debug?: boolean; +} +``` + +#### Properties + +- **`element`** (required): `HTMLElement` + - The DOM element where text morphing will occur + - Must be a valid HTML element reference + +- **`locale`** (optional): `Intl.LocalesArgument` + - Controls text segmentation behavior using the Intl.Segmenter API + - Default: `"en"` + - Examples: `"en"`, `"es"`, `"ja"`, `["en-US", "en"]` + - Affects whether text is split by characters or words + +- **`duration`** (optional): `number` + - Animation duration in milliseconds + - Default: `400` + - Controls how long the morphing animation takes + +- **`ease`** (optional): `string` + - CSS easing function for animations + - Default: `"cubic-bezier(0.19, 1, 0.22, 1)"` + - Any valid CSS timing function string + - Examples: `"ease-in-out"`, `"cubic-bezier(0.4, 0, 0.2, 1)"` + +- **`debug`** (optional): `boolean` + - Enables debug mode with visual indicators + - Default: `false` + - When enabled, adds colored outlines around the container (magenta) and individual text segments (cyan) + +## Framework Implementations + +### React + +#### TextMorph Component + +The React component provides a declarative way to use TextMorph. + +```typescript +interface TextMorphProps extends Omit { + children: string; +} +``` + +**Usage:** +```tsx +import { TextMorph } from 'torph/react'; + +function App() { + const [text, setText] = useState('Hello World'); + + return ( + + {text} + + ); +} +``` + +#### useTextMorph Hook + +The `useTextMorph` hook provides more control over the TextMorph instance. + +```typescript +function useTextMorph( + props: Omit +): { + ref: React.RefObject; + update: (text: string) => void; +} +``` + +**Returns:** +- `ref`: React ref to attach to a DOM element +- `update`: Function to update the text programmatically + +**Usage:** +```tsx +import { useTextMorph } from 'torph/react'; + +function CustomComponent() { + const { ref, update } = useTextMorph({ + duration: 400, + ease: "cubic-bezier(0.19, 1, 0.22, 1)", + locale: "en" + }); + + useEffect(() => { + update('Hello World'); + }, []); + + return
; +} +``` + +### Vue + +```typescript +interface TextMorphProps extends Omit { + text: string; +} +``` + +**Usage:** +```vue + + + +``` + +### Svelte + +```typescript +interface TextMorphProps extends Omit { + text: string; + locale?: Intl.LocalesArgument; + duration?: number; + ease?: string; + debug?: boolean; +} +``` + +**Usage:** +```svelte + + + +``` + +### Vanilla JavaScript + +For direct DOM manipulation without a framework: + +```javascript +import { TextMorph } from 'torph'; + +const element = document.getElementById('morph'); +const morph = new TextMorph({ + element: element, + duration: 400, + ease: 'cubic-bezier(0.19, 1, 0.22, 1)', + locale: 'en', + debug: false +}); + +// Update text +morph.update('Hello World'); + +// Later, clean up +morph.destroy(); +``` + +## Advanced Usage + +### Debugging + +Enable debug mode to visualize the text morphing process: + +```tsx + + {text} + +``` + +This will add: +- Magenta outline around the container +- Cyan outlines around individual text segments +- Helps understand how text is being segmented and animated + +### Custom Easing + +You can use any CSS timing function: + +```tsx +// Ease-in-out +{text} + +// Custom cubic bezier +{text} + +// Steps +{text} +``` + +### Locale-Specific Segmentation + +Different locales segment text differently: + +```tsx +// English - segments by characters or words +{text} + +// Japanese - segments by grapheme clusters +{text} + +// Multi-locale fallback +{text} +``` + +### Performance Considerations + +- **Duration**: Shorter durations (200-400ms) feel snappier, longer durations (600-1000ms) feel more dramatic +- **Text Length**: Works best with short to medium text (1-100 characters) +- **Update Frequency**: Avoid updating text more than once every `duration` milliseconds to prevent animation conflicts + +## Internal Implementation Details + +### Text Segmentation Algorithm + +The component uses `Intl.Segmenter` to intelligently split text: +- If text contains spaces, it segments by words +- Otherwise, it segments by grapheme clusters (handles emojis and complex characters correctly) + +### Animation Strategy + +1. **Measure**: Records positions of all existing text segments +2. **Update DOM**: Removes moved segments and adds new ones +3. **Measure Again**: Records new positions +4. **Animate**: Calculates deltas and creates Web Animations API keyframes +5. **Cleanup**: Removes exiting elements after animation completes + +### Exiting Animation + +Characters being removed: +1. Are positioned absolutely +2. Find the nearest remaining character +3. Animate 50% of the way toward that character while fading out +4. Are removed from the DOM after animation completes + +### Container Sizing + +The container animates its width and height: +1. Captures old dimensions +2. Allows container to size to new content +3. Captures new dimensions +4. Animates from old to new dimensions +5. Resets to `auto` after animation + +## Browser Compatibility + +TextMorph requires: +- `Intl.Segmenter` - [Browser Support](https://caniuse.com/mdn-javascript_builtins_intl_segmenter) +- Web Animations API - [Browser Support](https://caniuse.com/web-animation) + +Supported in: +- Chrome/Edge 87+ +- Firefox 125+ +- Safari 14.1+ + +## Limitations + +- **Single Line**: Currently optimized for single-line text (uses `display: inline-flex`) +- **Text Only**: Only supports string content, not HTML elements +- **No Nested Elements**: Cannot contain other components or HTML tags + +## Examples + +### Counter Animation + +```tsx +function Counter() { + const [count, setCount] = useState(0); + + return ( +
+ {count.toString()} + +
+ ); +} +``` + +### Status Updates + +```tsx +function StatusIndicator() { + const [status, setStatus] = useState('Idle'); + + return ( + + {status} + + ); +} +``` + +### Word Rotation + +```tsx +function RotatingWord() { + const words = ['Amazing', 'Incredible', 'Fantastic', 'Wonderful']; + const [index, setIndex] = useState(0); + + useEffect(() => { + const interval = setInterval(() => { + setIndex(i => (i + 1) % words.length); + }, 2000); + return () => clearInterval(interval); + }, []); + + return ( +
+ This is {words[index]}! +
+ ); +} +``` + +## Styling + +The TextMorph component adds minimal styles: +- Container uses `display: inline-flex` and `position: relative` +- Individual segments use `display: inline-block` +- All necessary transitions and animations are applied automatically + +You can style the container element normally: + +```tsx + + {text} + +``` + +Or using CSS classes: + +```tsx + + {text} + +``` + +## License + +MIT From c2026725badd873f7cdb609c0f83a8b60b6e57d6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Feb 2026 04:08:24 +0000 Subject: [PATCH 3/3] Simplify documentation to concise API reference Co-authored-by: lochie <1930210+lochie@users.noreply.github.com> --- packages/torph/TEXTMORPH.md | 381 +++--------------------------------- 1 file changed, 28 insertions(+), 353 deletions(-) diff --git a/packages/torph/TEXTMORPH.md b/packages/torph/TEXTMORPH.md index f63caeb..10845b6 100644 --- a/packages/torph/TEXTMORPH.md +++ b/packages/torph/TEXTMORPH.md @@ -1,112 +1,34 @@ -# TextMorph Component Documentation - -## Overview - -TextMorph is an animated text morphing component that smoothly transitions between text changes with character-level animations. It provides a fluid, visually appealing way to update text content by animating individual characters or words as they enter, exit, or move positions. - -## Core Architecture - -### TextMorph Class - -The `TextMorph` class is the core implementation that handles all text morphing animations. It works with any framework or vanilla JavaScript. - -#### Constructor - -```typescript -constructor(options: TextMorphOptions) -``` - -Creates a new TextMorph instance attached to an HTML element. - -**Example:** -```javascript -const morph = new TextMorph({ - element: document.getElementById('my-text'), - duration: 400, - ease: 'cubic-bezier(0.19, 1, 0.22, 1)', - locale: 'en', - debug: false -}); -``` - -#### Methods - -##### `update(value: string)` - -Updates the text content with a smooth animation transition. - -```javascript -morph.update('Hello World'); -``` - -##### `destroy()` - -Cleans up the TextMorph instance, canceling all animations and removing attributes. - -```javascript -morph.destroy(); -``` - -### How It Works - -1. **Text Segmentation**: TextMorph uses `Intl.Segmenter` to break text into graphemes (individual characters) or words based on locale. -2. **Position Tracking**: It measures the position of each text segment before and after updates. -3. **Animation**: Characters that exist in both old and new text are animated from their old position to their new position. -4. **Entry Animation**: New characters fade in and scale slightly. -5. **Exit Animation**: Removed characters fade out and move toward nearby characters. -6. **Container Resize**: The container smoothly animates its width and height to accommodate the new text. +# TextMorph API Reference ## Types ### TextMorphOptions -The main configuration interface for TextMorph instances. - ```typescript interface TextMorphOptions { element: HTMLElement; - locale?: Intl.LocalesArgument; - duration?: number; - ease?: string; - debug?: boolean; + locale?: Intl.LocalesArgument; // default: "en" + duration?: number; // default: 400 (ms) + ease?: string; // default: "cubic-bezier(0.19, 1, 0.22, 1)" + debug?: boolean; // default: false } ``` -#### Properties - -- **`element`** (required): `HTMLElement` - - The DOM element where text morphing will occur - - Must be a valid HTML element reference - -- **`locale`** (optional): `Intl.LocalesArgument` - - Controls text segmentation behavior using the Intl.Segmenter API - - Default: `"en"` - - Examples: `"en"`, `"es"`, `"ja"`, `["en-US", "en"]` - - Affects whether text is split by characters or words - -- **`duration`** (optional): `number` - - Animation duration in milliseconds - - Default: `400` - - Controls how long the morphing animation takes - -- **`ease`** (optional): `string` - - CSS easing function for animations - - Default: `"cubic-bezier(0.19, 1, 0.22, 1)"` - - Any valid CSS timing function string - - Examples: `"ease-in-out"`, `"cubic-bezier(0.4, 0, 0.2, 1)"` +## Core API -- **`debug`** (optional): `boolean` - - Enables debug mode with visual indicators - - Default: `false` - - When enabled, adds colored outlines around the container (magenta) and individual text segments (cyan) - -## Framework Implementations +### TextMorph Class -### React +```typescript +class TextMorph { + constructor(options: TextMorphOptions) + update(value: string): void + destroy(): void +} +``` -#### TextMorph Component +## React -The React component provides a declarative way to use TextMorph. +### TextMorph Component ```typescript interface TextMorphProps extends Omit { @@ -114,29 +36,15 @@ interface TextMorphProps extends Omit { } ``` -**Usage:** ```tsx import { TextMorph } from 'torph/react'; -function App() { - const [text, setText] = useState('Hello World'); - - return ( - - {text} - - ); -} + + {text} + ``` -#### useTextMorph Hook - -The `useTextMorph` hook provides more control over the TextMorph instance. +### useTextMorph Hook ```typescript function useTextMorph( @@ -147,30 +55,13 @@ function useTextMorph( } ``` -**Returns:** -- `ref`: React ref to attach to a DOM element -- `update`: Function to update the text programmatically - -**Usage:** ```tsx import { useTextMorph } from 'torph/react'; -function CustomComponent() { - const { ref, update } = useTextMorph({ - duration: 400, - ease: "cubic-bezier(0.19, 1, 0.22, 1)", - locale: "en" - }); - - useEffect(() => { - update('Hello World'); - }, []); - - return
; -} +const { ref, update } = useTextMorph({ duration: 400 }); ``` -### Vue +## Vue ```typescript interface TextMorphProps extends Omit { @@ -178,27 +69,17 @@ interface TextMorphProps extends Omit { } ``` -**Usage:** ```vue ``` -### Svelte +## Svelte ```typescript interface TextMorphProps extends Omit { @@ -210,231 +91,25 @@ interface TextMorphProps extends Omit { } ``` -**Usage:** ```svelte - + ``` -### Vanilla JavaScript - -For direct DOM manipulation without a framework: +## Vanilla JS ```javascript import { TextMorph } from 'torph'; -const element = document.getElementById('morph'); const morph = new TextMorph({ - element: element, + element: document.getElementById('morph'), duration: 400, - ease: 'cubic-bezier(0.19, 1, 0.22, 1)', - locale: 'en', - debug: false + locale: 'en' }); -// Update text morph.update('Hello World'); - -// Later, clean up morph.destroy(); ``` - -## Advanced Usage - -### Debugging - -Enable debug mode to visualize the text morphing process: - -```tsx - - {text} - -``` - -This will add: -- Magenta outline around the container -- Cyan outlines around individual text segments -- Helps understand how text is being segmented and animated - -### Custom Easing - -You can use any CSS timing function: - -```tsx -// Ease-in-out -{text} - -// Custom cubic bezier -{text} - -// Steps -{text} -``` - -### Locale-Specific Segmentation - -Different locales segment text differently: - -```tsx -// English - segments by characters or words -{text} - -// Japanese - segments by grapheme clusters -{text} - -// Multi-locale fallback -{text} -``` - -### Performance Considerations - -- **Duration**: Shorter durations (200-400ms) feel snappier, longer durations (600-1000ms) feel more dramatic -- **Text Length**: Works best with short to medium text (1-100 characters) -- **Update Frequency**: Avoid updating text more than once every `duration` milliseconds to prevent animation conflicts - -## Internal Implementation Details - -### Text Segmentation Algorithm - -The component uses `Intl.Segmenter` to intelligently split text: -- If text contains spaces, it segments by words -- Otherwise, it segments by grapheme clusters (handles emojis and complex characters correctly) - -### Animation Strategy - -1. **Measure**: Records positions of all existing text segments -2. **Update DOM**: Removes moved segments and adds new ones -3. **Measure Again**: Records new positions -4. **Animate**: Calculates deltas and creates Web Animations API keyframes -5. **Cleanup**: Removes exiting elements after animation completes - -### Exiting Animation - -Characters being removed: -1. Are positioned absolutely -2. Find the nearest remaining character -3. Animate 50% of the way toward that character while fading out -4. Are removed from the DOM after animation completes - -### Container Sizing - -The container animates its width and height: -1. Captures old dimensions -2. Allows container to size to new content -3. Captures new dimensions -4. Animates from old to new dimensions -5. Resets to `auto` after animation - -## Browser Compatibility - -TextMorph requires: -- `Intl.Segmenter` - [Browser Support](https://caniuse.com/mdn-javascript_builtins_intl_segmenter) -- Web Animations API - [Browser Support](https://caniuse.com/web-animation) - -Supported in: -- Chrome/Edge 87+ -- Firefox 125+ -- Safari 14.1+ - -## Limitations - -- **Single Line**: Currently optimized for single-line text (uses `display: inline-flex`) -- **Text Only**: Only supports string content, not HTML elements -- **No Nested Elements**: Cannot contain other components or HTML tags - -## Examples - -### Counter Animation - -```tsx -function Counter() { - const [count, setCount] = useState(0); - - return ( -
- {count.toString()} - -
- ); -} -``` - -### Status Updates - -```tsx -function StatusIndicator() { - const [status, setStatus] = useState('Idle'); - - return ( - - {status} - - ); -} -``` - -### Word Rotation - -```tsx -function RotatingWord() { - const words = ['Amazing', 'Incredible', 'Fantastic', 'Wonderful']; - const [index, setIndex] = useState(0); - - useEffect(() => { - const interval = setInterval(() => { - setIndex(i => (i + 1) % words.length); - }, 2000); - return () => clearInterval(interval); - }, []); - - return ( -
- This is {words[index]}! -
- ); -} -``` - -## Styling - -The TextMorph component adds minimal styles: -- Container uses `display: inline-flex` and `position: relative` -- Individual segments use `display: inline-block` -- All necessary transitions and animations are applied automatically - -You can style the container element normally: - -```tsx - - {text} - -``` - -Or using CSS classes: - -```tsx - - {text} - -``` - -## License - -MIT