torph 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -7
- package/dist/{TextMorph-SZJHGWGL.vue → TextMorph-LC6RO5C5.vue} +15 -10
- package/dist/index.d.mts +10 -12
- package/dist/index.d.ts +10 -12
- package/dist/index.js +8 -10
- package/dist/index.mjs +8 -10
- package/dist/react/index.d.mts +8 -1
- package/dist/react/index.d.ts +8 -1
- package/dist/react/index.js +8 -10
- package/dist/react/index.mjs +8 -10
- package/dist/svelte/index.d.mts +19 -1
- package/dist/svelte/index.d.ts +28 -0
- package/dist/svelte/index.js +1 -2
- package/dist/svelte/index.mjs +1 -2
- package/dist/vue/index.d.mts +19 -1
- package/dist/vue/index.d.ts +28 -0
- package/dist/vue/index.js +1 -2
- package/dist/vue/index.mjs +1 -2
- package/package.json +11 -3
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/react/index.js.map +0 -1
- package/dist/react/index.mjs.map +0 -1
- package/dist/svelte/index.js.map +0 -1
- package/dist/svelte/index.mjs.map +0 -1
- package/dist/vue/index.js.map +0 -1
- package/dist/vue/index.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Torph
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Dependency-free animated text morphing component for React, Vue, Svelte, and vanilla JavaScript.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -124,6 +124,31 @@ const morph = new TextMorph({
|
|
|
124
124
|
morph.update("Hello World");
|
|
125
125
|
```
|
|
126
126
|
|
|
127
|
+
## Spring Animations
|
|
128
|
+
|
|
129
|
+
Pass spring parameters to `ease` for physics-based easing. The duration is computed automatically from the spring physics.
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
import { TextMorph } from "torph/react";
|
|
133
|
+
|
|
134
|
+
function App() {
|
|
135
|
+
const [text, setText] = useState("Hello World");
|
|
136
|
+
|
|
137
|
+
return (
|
|
138
|
+
<TextMorph ease={{ stiffness: 200, damping: 20 }}>{text}</TextMorph>
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Spring Parameters
|
|
144
|
+
|
|
145
|
+
| Parameter | Type | Default | Description |
|
|
146
|
+
| ----------- | -------- | ------- | ----------------------------------------- |
|
|
147
|
+
| `stiffness` | `number` | `100` | Spring stiffness coefficient |
|
|
148
|
+
| `damping` | `number` | `10` | Damping coefficient |
|
|
149
|
+
| `mass` | `number` | `1` | Mass of the spring |
|
|
150
|
+
| `precision` | `number` | `0.001` | Threshold for determining settled position |
|
|
151
|
+
|
|
127
152
|
## API
|
|
128
153
|
|
|
129
154
|
### Options
|
|
@@ -131,17 +156,18 @@ morph.update("Hello World");
|
|
|
131
156
|
All components accept the following props/options:
|
|
132
157
|
|
|
133
158
|
- `text` / `children: string` - The text to display (required)
|
|
134
|
-
- `duration?: number` - Animation duration in milliseconds (default: 400)
|
|
135
|
-
- `ease?: string` - CSS easing function (default: "cubic-bezier(0.19, 1, 0.22, 1)")
|
|
136
|
-
- `
|
|
159
|
+
- `duration?: number` - Animation duration in milliseconds (default: `400`)
|
|
160
|
+
- `ease?: string | SpringParams` - CSS easing function or spring parameters (default: `"cubic-bezier(0.19, 1, 0.22, 1)"`)
|
|
161
|
+
- `scale?: boolean` - Enable scale animation on exiting segments (default: `true`)
|
|
162
|
+
- `locale?: Intl.LocalesArgument` - Locale for text segmentation (default: `"en"`)
|
|
137
163
|
- `debug?: boolean` - Enable debug mode with visual indicators
|
|
138
|
-
- `disabled?: boolean` - Disable all morphing animations (default: false)
|
|
139
|
-
- `respectReducedMotion?: boolean` - Respect user's prefers-reduced-motion setting (default: true)
|
|
164
|
+
- `disabled?: boolean` - Disable all morphing animations (default: `false`)
|
|
165
|
+
- `respectReducedMotion?: boolean` - Respect user's prefers-reduced-motion setting (default: `true`)
|
|
140
166
|
- `onAnimationStart?: () => void` - Callback fired when animation begins
|
|
141
167
|
- `onAnimationComplete?: () => void` - Callback fired when animation completes
|
|
142
168
|
- `className?: string` - CSS class name (React/Vue: `class`)
|
|
143
169
|
- `style?: object | string` - Inline styles
|
|
144
|
-
- `as?: string` - HTML element type (default: "
|
|
170
|
+
- `as?: string` - HTML element type (default: `"span"`)
|
|
145
171
|
|
|
146
172
|
## Found this useful?
|
|
147
173
|
|
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
</template>
|
|
9
9
|
|
|
10
10
|
<script setup lang="ts">
|
|
11
|
-
import { ref,
|
|
11
|
+
import { ref, computed, onUnmounted, watch } from "vue";
|
|
12
12
|
import {
|
|
13
13
|
DEFAULT_AS,
|
|
14
14
|
DEFAULT_TEXT_MORPH_OPTIONS,
|
|
15
|
-
TextMorph as Morph,
|
|
16
15
|
} from "../lib/text-morph";
|
|
16
|
+
import { MorphController } from "../lib/text-morph/controller";
|
|
17
17
|
import type { TextMorphProps } from "./types";
|
|
18
18
|
|
|
19
19
|
const props = withDefaults(defineProps<TextMorphProps>(), {
|
|
@@ -27,12 +27,15 @@ const props = withDefaults(defineProps<TextMorphProps>(), {
|
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
const containerRef = ref<HTMLElement | null>(null);
|
|
30
|
-
|
|
30
|
+
const controller = new MorphController();
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
const configKey = computed(() =>
|
|
33
|
+
MorphController.serializeConfig(props),
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
function createInstance() {
|
|
33
37
|
if (containerRef.value) {
|
|
34
|
-
|
|
35
|
-
element: containerRef.value,
|
|
38
|
+
controller.attach(containerRef.value, {
|
|
36
39
|
locale: props.locale,
|
|
37
40
|
duration: props.duration,
|
|
38
41
|
ease: props.ease,
|
|
@@ -43,18 +46,20 @@ onMounted(() => {
|
|
|
43
46
|
onAnimationStart: props.onAnimationStart,
|
|
44
47
|
onAnimationComplete: props.onAnimationComplete,
|
|
45
48
|
});
|
|
46
|
-
morphInstance.update(props.text);
|
|
47
49
|
}
|
|
48
|
-
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
watch(containerRef, () => createInstance(), { flush: "post" });
|
|
53
|
+
watch(configKey, () => createInstance());
|
|
49
54
|
|
|
50
55
|
onUnmounted(() => {
|
|
51
|
-
|
|
56
|
+
controller.destroy();
|
|
52
57
|
});
|
|
53
58
|
|
|
54
59
|
watch(
|
|
55
60
|
() => props.text,
|
|
56
61
|
(newText) => {
|
|
57
|
-
|
|
62
|
+
controller.update(newText);
|
|
58
63
|
},
|
|
59
64
|
);
|
|
60
65
|
</script>
|
package/dist/index.d.mts
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
|
+
interface SpringParams {
|
|
2
|
+
stiffness?: number;
|
|
3
|
+
damping?: number;
|
|
4
|
+
mass?: number;
|
|
5
|
+
precision?: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
1
8
|
interface TextMorphOptions {
|
|
2
9
|
debug?: boolean;
|
|
3
10
|
element: HTMLElement;
|
|
4
11
|
locale?: Intl.LocalesArgument;
|
|
5
12
|
scale?: boolean;
|
|
6
13
|
duration?: number;
|
|
7
|
-
ease?: string;
|
|
14
|
+
ease?: string | SpringParams;
|
|
8
15
|
disabled?: boolean;
|
|
9
16
|
respectReducedMotion?: boolean;
|
|
10
17
|
onAnimationStart?: () => void;
|
|
@@ -28,22 +35,13 @@ declare class TextMorph {
|
|
|
28
35
|
private currentMeasures;
|
|
29
36
|
private prevMeasures;
|
|
30
37
|
private isInitialRender;
|
|
31
|
-
private
|
|
32
|
-
private mediaQuery?;
|
|
33
|
-
static styleEl: HTMLStyleElement;
|
|
38
|
+
private reducedMotion;
|
|
34
39
|
constructor(options: TextMorphOptions);
|
|
35
40
|
destroy(): void;
|
|
36
|
-
private handleMediaQueryChange;
|
|
37
41
|
private isDisabled;
|
|
38
42
|
update(value: HTMLElement | string): void;
|
|
39
43
|
private createTextGroup;
|
|
40
|
-
private measure;
|
|
41
44
|
private updateStyles;
|
|
42
|
-
private addStyles;
|
|
43
|
-
private removeStyles;
|
|
44
|
-
private blocks;
|
|
45
|
-
private blocksFallback;
|
|
46
|
-
private log;
|
|
47
45
|
}
|
|
48
46
|
|
|
49
|
-
export { DEFAULT_AS, DEFAULT_TEXT_MORPH_OPTIONS, TextMorph, type TextMorphOptions };
|
|
47
|
+
export { DEFAULT_AS, DEFAULT_TEXT_MORPH_OPTIONS, type SpringParams, TextMorph, type TextMorphOptions };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
|
+
interface SpringParams {
|
|
2
|
+
stiffness?: number;
|
|
3
|
+
damping?: number;
|
|
4
|
+
mass?: number;
|
|
5
|
+
precision?: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
1
8
|
interface TextMorphOptions {
|
|
2
9
|
debug?: boolean;
|
|
3
10
|
element: HTMLElement;
|
|
4
11
|
locale?: Intl.LocalesArgument;
|
|
5
12
|
scale?: boolean;
|
|
6
13
|
duration?: number;
|
|
7
|
-
ease?: string;
|
|
14
|
+
ease?: string | SpringParams;
|
|
8
15
|
disabled?: boolean;
|
|
9
16
|
respectReducedMotion?: boolean;
|
|
10
17
|
onAnimationStart?: () => void;
|
|
@@ -28,22 +35,13 @@ declare class TextMorph {
|
|
|
28
35
|
private currentMeasures;
|
|
29
36
|
private prevMeasures;
|
|
30
37
|
private isInitialRender;
|
|
31
|
-
private
|
|
32
|
-
private mediaQuery?;
|
|
33
|
-
static styleEl: HTMLStyleElement;
|
|
38
|
+
private reducedMotion;
|
|
34
39
|
constructor(options: TextMorphOptions);
|
|
35
40
|
destroy(): void;
|
|
36
|
-
private handleMediaQueryChange;
|
|
37
41
|
private isDisabled;
|
|
38
42
|
update(value: HTMLElement | string): void;
|
|
39
43
|
private createTextGroup;
|
|
40
|
-
private measure;
|
|
41
44
|
private updateStyles;
|
|
42
|
-
private addStyles;
|
|
43
|
-
private removeStyles;
|
|
44
|
-
private blocks;
|
|
45
|
-
private blocksFallback;
|
|
46
|
-
private log;
|
|
47
45
|
}
|
|
48
46
|
|
|
49
|
-
export { DEFAULT_AS, DEFAULT_TEXT_MORPH_OPTIONS, TextMorph, type TextMorphOptions };
|
|
47
|
+
export { DEFAULT_AS, DEFAULT_TEXT_MORPH_OPTIONS, type SpringParams, TextMorph, type TextMorphOptions };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
[
|
|
1
|
+
'use strict';function $(n,e,t){if(t<1){let u=e*Math.sqrt(1-t*t);return 1-Math.exp(-t*e*n)*(Math.cos(u*n)+t*e/u*Math.sin(u*n))}let i=Math.sqrt(t*t-1),s=-e*(t+i),r=-e*(t-i),o=-s/(r-s);return 1-(1-o)*Math.exp(s*n)-o*Math.exp(r*n)}function B(n,e,t){let r=0;for(let o=0;o<10;o+=.001)if(Math.abs($(o,n,e)-1)>t)r=0;else if(r+=.001,r>.1)return Math.ceil((o-r+.001)*1e3);return Math.ceil(10*1e3)}var I=new Map;function D(n){let{stiffness:e=100,damping:t=10,mass:i=1,precision:s=.001}=n??{},r=`${e}:${t}:${i}:${s}`,o=I.get(r);if(o)return o;let a=Math.sqrt(e/i),u=t/(2*Math.sqrt(e*i)),m=B(a,u,s),c=Math.min(100,Math.max(32,Math.round(m/15))),l=[];for(let g=0;g<c;g++){let b=g/(c-1)*(m/1e3),E=g===c-1?1:$(b,a,u);l.push(Math.round(E*1e4)/1e4+"");}for(;l.length>2&&l[l.length-2]==="1";)l.splice(l.length-2,1);let p={easing:`linear(${l.join(", ")})`,duration:m};return I.set(r,p),p}function H(n,e){let t=n.includes(" ");if(typeof Intl.Segmenter<"u"){let s=new Intl.Segmenter(e,{granularity:t?"word":"grapheme"}).segment(n)[Symbol.iterator]();return j(s)}return Y(n,t)}function j(n){return Array.from(n).reduce((e,t)=>t.segment===" "?[...e,{id:`space-${t.index}`,string:"\xA0"}]:e.find(s=>s.string===t.segment)?[...e,{id:`${t.segment}-${t.index}`,string:t.segment}]:[...e,{id:t.segment,string:t.segment}],[])}function q(n,e,t){let i=n.find(s=>s.string===e);n.push(i?{id:`${e}-${t}`,string:e}:{id:e,string:e});}function Y(n,e){let t=e?n.split(" "):n.split(""),i=[];return t.forEach((s,r)=>{e&&r>0&&i.push({id:`space-${r}`,string:"\xA0"}),q(i,s,r);}),i}var y="torph-root",T="torph-item",f="torph-id",d="torph-exiting",M="torph-debug";function A(n){let e=Array.from(n.children),t={};return e.forEach((i,s)=>{if(i.hasAttribute(d))return;let r=i.getAttribute(f)||`child-${s}`;t[r]={x:i.offsetLeft,y:i.offsetTop};}),t}function S(n,e,t){let i=n[t],s=e[t];return !i||!s?{dx:0,dy:0}:{dx:i.x-s.x,dy:i.y-s.y}}function w(n,e,t,i="backward-first"){let[s,r]=i==="backward-first"?["backward","forward"]:["forward","backward"],o=a=>{if(a==="backward"){for(let u=n-1;u>=0;u--)if(t.has(e[u]))return e[u]}else for(let u=n+1;u<e.length;u++)if(t.has(e[u]))return e[u];return null};return o(s)??o(r)}function _(n,e,t,i){let s=new Set(t.filter((o,a)=>i.has(o)&&!e.has(n[a]))),r=new Map;for(let o=0;o<n.length;o++){let a=n[o];e.has(a)&&r.set(a,w(o,t,s,"forward-first"));}return r}function O(n,e){return Math.min(n*e,150)}function R(n){let e=getComputedStyle(n).transform;if(!e||e==="none")return {tx:0,ty:0};let t=e.match(/matrix\(([^)]+)\)/);if(!t)return {tx:0,ty:0};let i=t[1].split(",").map(Number);return {tx:i[4]||0,ty:i[5]||0}}function Q(n){let{tx:e,ty:t}=R(n),i=Number(getComputedStyle(n).opacity)||1;return n.getAnimations().forEach(s=>s.cancel()),{tx:e,ty:t,opacity:i}}function N(n,e){let{dx:t,dy:i,duration:s,ease:r,scale:o}=e;n.animate({transform:o?`translate(${t}px, ${i}px) scale(0.95)`:`translate(${t}px, ${i}px)`,offset:1},{duration:s,easing:r,fill:"both"});let a=n.animate({opacity:0,offset:1},{duration:O(s,.25),easing:"linear",fill:"both"});a.onfinish=()=>n.remove();}function C(n,e){let{deltaX:t,deltaY:i,isNew:s,duration:r,ease:o}=e,a=Q(n),u=t+a.tx,m=i+a.ty;n.animate({transform:`translate(${u}px, ${m}px) scale(${s?.95:1})`,offset:0},{duration:r,easing:o,fill:"both"});let c=s&&a.opacity>=1?0:a.opacity;c<1&&n.animate([{opacity:c},{opacity:1}],{duration:O(r,s?.5:.25),easing:"linear",fill:"both"});}var x=null;function k(n,e,t,i,s){if(x&&(x(),x=null),e===0||t===0)return;n.style.width="auto",n.style.height="auto",n.offsetWidth;let r=n.offsetWidth,o=n.offsetHeight;n.style.width=`${e}px`,n.style.height=`${t}px`,n.offsetWidth,n.style.width=`${r}px`,n.style.height=`${o}px`;function a(){n.removeEventListener("transitionend",u),clearTimeout(m),x=null,n.style.width="auto",n.style.height="auto",s?.();}function u(c){c.target===n&&(c.propertyName!=="width"&&c.propertyName!=="height"||a());}n.addEventListener("transitionend",u);let m=setTimeout(a,i+50);x=()=>{n.removeEventListener("transitionend",u),clearTimeout(m),x=null;};}function F(n){let e=n.map(t=>{let{tx:i,ty:s}=R(t),r=Number(getComputedStyle(t).opacity)||1;return t.getAnimations().forEach(o=>o.cancel()),{left:t.offsetLeft+i,top:t.offsetTop+s,width:t.offsetWidth,height:t.offsetHeight,opacity:r}});n.forEach((t,i)=>{let s=e[i];t.setAttribute(d,""),t.style.position="absolute",t.style.pointerEvents="none",t.style.left=`${s.left}px`,t.style.top=`${s.top}px`,t.style.width=`${s.width}px`,t.style.height=`${s.height}px`,t.style.opacity=String(s.opacity);});}function P(n,e,t,i){let s=new Map;e.forEach(r=>{let o=r.getAttribute(f);t.has(o)&&!r.hasAttribute(d)&&(s.set(o,r),r.remove());}),Array.from(n.childNodes).forEach(r=>{r.nodeType===Node.TEXT_NODE&&r.remove();}),i.forEach(r=>{let o=s.get(r.id);if(o)o.textContent=r.string,n.appendChild(o);else {let a=document.createElement("span");a.setAttribute(T,""),a.setAttribute(f,r.id),a.textContent=r.string,n.appendChild(a);}});}var K=`
|
|
2
|
+
[${y}] {
|
|
3
3
|
display: inline-flex;
|
|
4
4
|
position: relative;
|
|
5
5
|
will-change: width, height;
|
|
@@ -7,19 +7,17 @@
|
|
|
7
7
|
white-space: nowrap;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
[
|
|
10
|
+
[${T}] {
|
|
11
11
|
display: inline-block;
|
|
12
12
|
will-change: opacity, transform;
|
|
13
13
|
transform: none;
|
|
14
14
|
opacity: 1;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
[
|
|
18
|
-
outline:2px solid magenta;
|
|
19
|
-
[
|
|
20
|
-
outline:2px solid cyan;
|
|
17
|
+
[${y}][${M}] {
|
|
18
|
+
outline: 2px solid magenta;
|
|
19
|
+
[${T}] {
|
|
20
|
+
outline: 2px solid cyan;
|
|
21
21
|
outline-offset: -4px;
|
|
22
22
|
}
|
|
23
|
-
}
|
|
24
|
-
`,document.head.appendChild(e),g.styleEl=e;}removeStyles(){g.styleEl&&(g.styleEl.remove(),g.styleEl=void 0);}blocks(e){return Array.from(e).reduce((h,i)=>i.segment===" "?[...h,{id:`space-${i.index}`,string:"\xA0"}]:h.find(p=>p.string===i.segment)?[...h,{id:`${i.segment}-${i.index}`,string:i.segment}]:[...h,{id:i.segment,string:i.segment}],[])}blocksFallback(e,s){let h=s?e.split(" "):e.split(""),i=[];return s?h.forEach((a,p)=>{p>0&&i.push({id:`space-${p}`,string:"\xA0"}),i.find(d=>d.string===a)?i.push({id:`${a}-${p}`,string:a}):i.push({id:a,string:a});}):h.forEach((a,p)=>{i.find(d=>d.string===a)?i.push({id:`${a}-${p}`,string:a}):i.push({id:a,string:a});}),i}log(...e){this.options.debug&&console.log("[TextMorph]",...e);}};exports.DEFAULT_AS=T;exports.DEFAULT_TEXT_MORPH_OPTIONS=A;exports.TextMorph=b;//# sourceMappingURL=index.js.map
|
|
25
|
-
//# sourceMappingURL=index.js.map
|
|
23
|
+
}`,h=null,v=0;function X(){v++,!h&&(h=document.createElement("style"),h.dataset.torph="true",h.textContent=K,document.head.appendChild(h));}function G(){v--,!(v>0||!h)&&(h.remove(),h=null);}function U(){if(typeof window>"u")return {prefersReducedMotion:false,destroy:()=>{}};let n=window.matchMedia("(prefers-reduced-motion: reduce)"),e={prefersReducedMotion:n.matches,destroy:i};function t(s){e.prefersReducedMotion=s.matches;}function i(){n.removeEventListener("change",t);}return n.addEventListener("change",t),e}var J="span",W={debug:false,locale:"en",duration:400,scale:true,ease:"cubic-bezier(0.19, 1, 0.22, 1)",disabled:false,respectReducedMotion:true},L=class{element;options={};data;currentMeasures={};prevMeasures={};isInitialRender=true;reducedMotion=null;constructor(e){let{ease:t,...i}={...W,...e},s,r;if(typeof t=="object"){let o=D(t);s=o.easing,r=o.duration;}else s=t,r=i.duration;this.options={...i,ease:s,duration:r},this.element=e.element,this.options.respectReducedMotion&&(this.reducedMotion=U()),this.isDisabled()||(this.element.setAttribute(y,""),this.element.style.transitionDuration=`${this.options.duration}ms`,this.element.style.transitionTimingFunction=this.options.ease,e.debug&&this.element.setAttribute(M,"")),this.data="",this.isDisabled()||X();}destroy(){this.reducedMotion?.destroy(),this.element.getAnimations().forEach(e=>e.cancel()),this.element.removeAttribute(y),this.element.removeAttribute(M),G();}isDisabled(){return !!(this.options.disabled||this.reducedMotion?.prefersReducedMotion)}update(e){if(e!==this.data){if(this.data=e,this.isDisabled()){typeof e=="string"&&(this.element.textContent=e);return}if(this.data instanceof HTMLElement)throw new Error("HTMLElement not yet supported");this.options.onAnimationStart&&!this.isInitialRender&&this.options.onAnimationStart(),this.createTextGroup(this.data,this.element);}}createTextGroup(e,t){let i=t.offsetWidth,s=t.offsetHeight,r=H(e,this.options.locale);this.prevMeasures=A(this.element);let o=Array.from(t.children),a=new Set(r.map(p=>p.id)),u=o.filter(p=>!a.has(p.getAttribute(f))&&!p.hasAttribute(d)),m=new Set(u),c=o.map(p=>p.getAttribute(f)),l=_(o,m,c,a);if(F(u),P(t,o,a,r),this.currentMeasures=A(this.element),this.updateStyles(r),u.forEach(p=>{if(this.isInitialRender){p.remove();return}let g=l.get(p),{dx:b,dy:E}=g?S(this.currentMeasures,this.prevMeasures,g):{dx:0,dy:0};N(p,{dx:b,dy:E,duration:this.options.duration,ease:this.options.ease,scale:this.options.scale});}),this.isInitialRender){this.isInitialRender=false,t.style.width="auto",t.style.height="auto";return}k(t,i,s,this.options.duration,this.options.onAnimationComplete);}updateStyles(e){if(this.isInitialRender)return;let t=Array.from(this.element.children),i=e.map(r=>r.id),s=new Set(i.filter(r=>this.prevMeasures[r]));t.forEach((r,o)=>{if(r.hasAttribute(d))return;let a=r.getAttribute(f)||`child-${o}`,u=!this.prevMeasures[a],m=u?w(e.findIndex(p=>p.id===a),i,s):a,{dx:c,dy:l}=m?S(this.prevMeasures,this.currentMeasures,m):{dx:0,dy:0};C(r,{deltaX:c,deltaY:l,isNew:u,duration:this.options.duration,ease:this.options.ease});});}};exports.DEFAULT_AS=J;exports.DEFAULT_TEXT_MORPH_OPTIONS=W;exports.TextMorph=L;
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
[
|
|
1
|
+
function $(n,e,t){if(t<1){let u=e*Math.sqrt(1-t*t);return 1-Math.exp(-t*e*n)*(Math.cos(u*n)+t*e/u*Math.sin(u*n))}let i=Math.sqrt(t*t-1),s=-e*(t+i),r=-e*(t-i),o=-s/(r-s);return 1-(1-o)*Math.exp(s*n)-o*Math.exp(r*n)}function B(n,e,t){let r=0;for(let o=0;o<10;o+=.001)if(Math.abs($(o,n,e)-1)>t)r=0;else if(r+=.001,r>.1)return Math.ceil((o-r+.001)*1e3);return Math.ceil(10*1e3)}var I=new Map;function D(n){let{stiffness:e=100,damping:t=10,mass:i=1,precision:s=.001}=n??{},r=`${e}:${t}:${i}:${s}`,o=I.get(r);if(o)return o;let a=Math.sqrt(e/i),u=t/(2*Math.sqrt(e*i)),m=B(a,u,s),c=Math.min(100,Math.max(32,Math.round(m/15))),l=[];for(let g=0;g<c;g++){let b=g/(c-1)*(m/1e3),E=g===c-1?1:$(b,a,u);l.push(Math.round(E*1e4)/1e4+"");}for(;l.length>2&&l[l.length-2]==="1";)l.splice(l.length-2,1);let p={easing:`linear(${l.join(", ")})`,duration:m};return I.set(r,p),p}function H(n,e){let t=n.includes(" ");if(typeof Intl.Segmenter<"u"){let s=new Intl.Segmenter(e,{granularity:t?"word":"grapheme"}).segment(n)[Symbol.iterator]();return j(s)}return Y(n,t)}function j(n){return Array.from(n).reduce((e,t)=>t.segment===" "?[...e,{id:`space-${t.index}`,string:"\xA0"}]:e.find(s=>s.string===t.segment)?[...e,{id:`${t.segment}-${t.index}`,string:t.segment}]:[...e,{id:t.segment,string:t.segment}],[])}function q(n,e,t){let i=n.find(s=>s.string===e);n.push(i?{id:`${e}-${t}`,string:e}:{id:e,string:e});}function Y(n,e){let t=e?n.split(" "):n.split(""),i=[];return t.forEach((s,r)=>{e&&r>0&&i.push({id:`space-${r}`,string:"\xA0"}),q(i,s,r);}),i}var y="torph-root",T="torph-item",f="torph-id",d="torph-exiting",M="torph-debug";function A(n){let e=Array.from(n.children),t={};return e.forEach((i,s)=>{if(i.hasAttribute(d))return;let r=i.getAttribute(f)||`child-${s}`;t[r]={x:i.offsetLeft,y:i.offsetTop};}),t}function S(n,e,t){let i=n[t],s=e[t];return !i||!s?{dx:0,dy:0}:{dx:i.x-s.x,dy:i.y-s.y}}function w(n,e,t,i="backward-first"){let[s,r]=i==="backward-first"?["backward","forward"]:["forward","backward"],o=a=>{if(a==="backward"){for(let u=n-1;u>=0;u--)if(t.has(e[u]))return e[u]}else for(let u=n+1;u<e.length;u++)if(t.has(e[u]))return e[u];return null};return o(s)??o(r)}function _(n,e,t,i){let s=new Set(t.filter((o,a)=>i.has(o)&&!e.has(n[a]))),r=new Map;for(let o=0;o<n.length;o++){let a=n[o];e.has(a)&&r.set(a,w(o,t,s,"forward-first"));}return r}function O(n,e){return Math.min(n*e,150)}function R(n){let e=getComputedStyle(n).transform;if(!e||e==="none")return {tx:0,ty:0};let t=e.match(/matrix\(([^)]+)\)/);if(!t)return {tx:0,ty:0};let i=t[1].split(",").map(Number);return {tx:i[4]||0,ty:i[5]||0}}function Q(n){let{tx:e,ty:t}=R(n),i=Number(getComputedStyle(n).opacity)||1;return n.getAnimations().forEach(s=>s.cancel()),{tx:e,ty:t,opacity:i}}function N(n,e){let{dx:t,dy:i,duration:s,ease:r,scale:o}=e;n.animate({transform:o?`translate(${t}px, ${i}px) scale(0.95)`:`translate(${t}px, ${i}px)`,offset:1},{duration:s,easing:r,fill:"both"});let a=n.animate({opacity:0,offset:1},{duration:O(s,.25),easing:"linear",fill:"both"});a.onfinish=()=>n.remove();}function C(n,e){let{deltaX:t,deltaY:i,isNew:s,duration:r,ease:o}=e,a=Q(n),u=t+a.tx,m=i+a.ty;n.animate({transform:`translate(${u}px, ${m}px) scale(${s?.95:1})`,offset:0},{duration:r,easing:o,fill:"both"});let c=s&&a.opacity>=1?0:a.opacity;c<1&&n.animate([{opacity:c},{opacity:1}],{duration:O(r,s?.5:.25),easing:"linear",fill:"both"});}var x=null;function k(n,e,t,i,s){if(x&&(x(),x=null),e===0||t===0)return;n.style.width="auto",n.style.height="auto",n.offsetWidth;let r=n.offsetWidth,o=n.offsetHeight;n.style.width=`${e}px`,n.style.height=`${t}px`,n.offsetWidth,n.style.width=`${r}px`,n.style.height=`${o}px`;function a(){n.removeEventListener("transitionend",u),clearTimeout(m),x=null,n.style.width="auto",n.style.height="auto",s?.();}function u(c){c.target===n&&(c.propertyName!=="width"&&c.propertyName!=="height"||a());}n.addEventListener("transitionend",u);let m=setTimeout(a,i+50);x=()=>{n.removeEventListener("transitionend",u),clearTimeout(m),x=null;};}function F(n){let e=n.map(t=>{let{tx:i,ty:s}=R(t),r=Number(getComputedStyle(t).opacity)||1;return t.getAnimations().forEach(o=>o.cancel()),{left:t.offsetLeft+i,top:t.offsetTop+s,width:t.offsetWidth,height:t.offsetHeight,opacity:r}});n.forEach((t,i)=>{let s=e[i];t.setAttribute(d,""),t.style.position="absolute",t.style.pointerEvents="none",t.style.left=`${s.left}px`,t.style.top=`${s.top}px`,t.style.width=`${s.width}px`,t.style.height=`${s.height}px`,t.style.opacity=String(s.opacity);});}function P(n,e,t,i){let s=new Map;e.forEach(r=>{let o=r.getAttribute(f);t.has(o)&&!r.hasAttribute(d)&&(s.set(o,r),r.remove());}),Array.from(n.childNodes).forEach(r=>{r.nodeType===Node.TEXT_NODE&&r.remove();}),i.forEach(r=>{let o=s.get(r.id);if(o)o.textContent=r.string,n.appendChild(o);else {let a=document.createElement("span");a.setAttribute(T,""),a.setAttribute(f,r.id),a.textContent=r.string,n.appendChild(a);}});}var K=`
|
|
2
|
+
[${y}] {
|
|
3
3
|
display: inline-flex;
|
|
4
4
|
position: relative;
|
|
5
5
|
will-change: width, height;
|
|
@@ -7,19 +7,17 @@ var T="span",A={debug:false,locale:"en",duration:400,scale:true,ease:"cubic-bezi
|
|
|
7
7
|
white-space: nowrap;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
[
|
|
10
|
+
[${T}] {
|
|
11
11
|
display: inline-block;
|
|
12
12
|
will-change: opacity, transform;
|
|
13
13
|
transform: none;
|
|
14
14
|
opacity: 1;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
[
|
|
18
|
-
outline:2px solid magenta;
|
|
19
|
-
[
|
|
20
|
-
outline:2px solid cyan;
|
|
17
|
+
[${y}][${M}] {
|
|
18
|
+
outline: 2px solid magenta;
|
|
19
|
+
[${T}] {
|
|
20
|
+
outline: 2px solid cyan;
|
|
21
21
|
outline-offset: -4px;
|
|
22
22
|
}
|
|
23
|
-
}
|
|
24
|
-
`,document.head.appendChild(e),g.styleEl=e;}removeStyles(){g.styleEl&&(g.styleEl.remove(),g.styleEl=void 0);}blocks(e){return Array.from(e).reduce((h,i)=>i.segment===" "?[...h,{id:`space-${i.index}`,string:"\xA0"}]:h.find(p=>p.string===i.segment)?[...h,{id:`${i.segment}-${i.index}`,string:i.segment}]:[...h,{id:i.segment,string:i.segment}],[])}blocksFallback(e,s){let h=s?e.split(" "):e.split(""),i=[];return s?h.forEach((a,p)=>{p>0&&i.push({id:`space-${p}`,string:"\xA0"}),i.find(d=>d.string===a)?i.push({id:`${a}-${p}`,string:a}):i.push({id:a,string:a});}):h.forEach((a,p)=>{i.find(d=>d.string===a)?i.push({id:`${a}-${p}`,string:a}):i.push({id:a,string:a});}),i}log(...e){this.options.debug&&console.log("[TextMorph]",...e);}};export{T as DEFAULT_AS,A as DEFAULT_TEXT_MORPH_OPTIONS,b as TextMorph};//# sourceMappingURL=index.mjs.map
|
|
25
|
-
//# sourceMappingURL=index.mjs.map
|
|
23
|
+
}`,h=null,v=0;function X(){v++,!h&&(h=document.createElement("style"),h.dataset.torph="true",h.textContent=K,document.head.appendChild(h));}function G(){v--,!(v>0||!h)&&(h.remove(),h=null);}function U(){if(typeof window>"u")return {prefersReducedMotion:false,destroy:()=>{}};let n=window.matchMedia("(prefers-reduced-motion: reduce)"),e={prefersReducedMotion:n.matches,destroy:i};function t(s){e.prefersReducedMotion=s.matches;}function i(){n.removeEventListener("change",t);}return n.addEventListener("change",t),e}var J="span",W={debug:false,locale:"en",duration:400,scale:true,ease:"cubic-bezier(0.19, 1, 0.22, 1)",disabled:false,respectReducedMotion:true},L=class{element;options={};data;currentMeasures={};prevMeasures={};isInitialRender=true;reducedMotion=null;constructor(e){let{ease:t,...i}={...W,...e},s,r;if(typeof t=="object"){let o=D(t);s=o.easing,r=o.duration;}else s=t,r=i.duration;this.options={...i,ease:s,duration:r},this.element=e.element,this.options.respectReducedMotion&&(this.reducedMotion=U()),this.isDisabled()||(this.element.setAttribute(y,""),this.element.style.transitionDuration=`${this.options.duration}ms`,this.element.style.transitionTimingFunction=this.options.ease,e.debug&&this.element.setAttribute(M,"")),this.data="",this.isDisabled()||X();}destroy(){this.reducedMotion?.destroy(),this.element.getAnimations().forEach(e=>e.cancel()),this.element.removeAttribute(y),this.element.removeAttribute(M),G();}isDisabled(){return !!(this.options.disabled||this.reducedMotion?.prefersReducedMotion)}update(e){if(e!==this.data){if(this.data=e,this.isDisabled()){typeof e=="string"&&(this.element.textContent=e);return}if(this.data instanceof HTMLElement)throw new Error("HTMLElement not yet supported");this.options.onAnimationStart&&!this.isInitialRender&&this.options.onAnimationStart(),this.createTextGroup(this.data,this.element);}}createTextGroup(e,t){let i=t.offsetWidth,s=t.offsetHeight,r=H(e,this.options.locale);this.prevMeasures=A(this.element);let o=Array.from(t.children),a=new Set(r.map(p=>p.id)),u=o.filter(p=>!a.has(p.getAttribute(f))&&!p.hasAttribute(d)),m=new Set(u),c=o.map(p=>p.getAttribute(f)),l=_(o,m,c,a);if(F(u),P(t,o,a,r),this.currentMeasures=A(this.element),this.updateStyles(r),u.forEach(p=>{if(this.isInitialRender){p.remove();return}let g=l.get(p),{dx:b,dy:E}=g?S(this.currentMeasures,this.prevMeasures,g):{dx:0,dy:0};N(p,{dx:b,dy:E,duration:this.options.duration,ease:this.options.ease,scale:this.options.scale});}),this.isInitialRender){this.isInitialRender=false,t.style.width="auto",t.style.height="auto";return}k(t,i,s,this.options.duration,this.options.onAnimationComplete);}updateStyles(e){if(this.isInitialRender)return;let t=Array.from(this.element.children),i=e.map(r=>r.id),s=new Set(i.filter(r=>this.prevMeasures[r]));t.forEach((r,o)=>{if(r.hasAttribute(d))return;let a=r.getAttribute(f)||`child-${o}`,u=!this.prevMeasures[a],m=u?w(e.findIndex(p=>p.id===a),i,s):a,{dx:c,dy:l}=m?S(this.prevMeasures,this.currentMeasures,m):{dx:0,dy:0};C(r,{deltaX:c,deltaY:l,isNew:u,duration:this.options.duration,ease:this.options.ease});});}};export{J as DEFAULT_AS,W as DEFAULT_TEXT_MORPH_OPTIONS,L as TextMorph};
|
package/dist/react/index.d.mts
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
+
interface SpringParams {
|
|
4
|
+
stiffness?: number;
|
|
5
|
+
damping?: number;
|
|
6
|
+
mass?: number;
|
|
7
|
+
precision?: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
3
10
|
interface TextMorphOptions {
|
|
4
11
|
debug?: boolean;
|
|
5
12
|
element: HTMLElement;
|
|
6
13
|
locale?: Intl.LocalesArgument;
|
|
7
14
|
scale?: boolean;
|
|
8
15
|
duration?: number;
|
|
9
|
-
ease?: string;
|
|
16
|
+
ease?: string | SpringParams;
|
|
10
17
|
disabled?: boolean;
|
|
11
18
|
respectReducedMotion?: boolean;
|
|
12
19
|
onAnimationStart?: () => void;
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
+
interface SpringParams {
|
|
4
|
+
stiffness?: number;
|
|
5
|
+
damping?: number;
|
|
6
|
+
mass?: number;
|
|
7
|
+
precision?: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
3
10
|
interface TextMorphOptions {
|
|
4
11
|
debug?: boolean;
|
|
5
12
|
element: HTMLElement;
|
|
6
13
|
locale?: Intl.LocalesArgument;
|
|
7
14
|
scale?: boolean;
|
|
8
15
|
duration?: number;
|
|
9
|
-
ease?: string;
|
|
16
|
+
ease?: string | SpringParams;
|
|
10
17
|
disabled?: boolean;
|
|
11
18
|
respectReducedMotion?: boolean;
|
|
12
19
|
onAnimationStart?: () => void;
|
package/dist/react/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
'use strict';var
|
|
2
|
-
[
|
|
1
|
+
'use strict';var g=require('react');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var g__default=/*#__PURE__*/_interopDefault(g);function H(n,e,t){if(t<1){let u=e*Math.sqrt(1-t*t);return 1-Math.exp(-t*e*n)*(Math.cos(u*n)+t*e/u*Math.sin(u*n))}let i=Math.sqrt(t*t-1),s=-e*(t+i),r=-e*(t-i),o=-s/(r-s);return 1-(1-o)*Math.exp(s*n)-o*Math.exp(r*n)}function Y(n,e,t){let r=0;for(let o=0;o<10;o+=.001)if(Math.abs(H(o,n,e)-1)>t)r=0;else if(r+=.001,r>.1)return Math.ceil((o-r+.001)*1e3);return Math.ceil(10*1e3)}var $=new Map;function D(n){let{stiffness:e=100,damping:t=10,mass:i=1,precision:s=.001}=n??{},r=`${e}:${t}:${i}:${s}`,o=$.get(r);if(o)return o;let a=Math.sqrt(e/i),u=t/(2*Math.sqrt(e*i)),p=Y(a,u,s),l=Math.min(100,Math.max(32,Math.round(p/15))),m=[];for(let y=0;y<l;y++){let S=y/(l-1)*(p/1e3),R=y===l-1?1:H(S,a,u);m.push(Math.round(R*1e4)/1e4+"");}for(;m.length>2&&m[m.length-2]==="1";)m.splice(m.length-2,1);let c={easing:`linear(${m.join(", ")})`,duration:p};return $.set(r,c),c}function _(n,e){let t=n.includes(" ");if(typeof Intl.Segmenter<"u"){let s=new Intl.Segmenter(e,{granularity:t?"word":"grapheme"}).segment(n)[Symbol.iterator]();return Q(s)}return V(n,t)}function Q(n){return Array.from(n).reduce((e,t)=>t.segment===" "?[...e,{id:`space-${t.index}`,string:"\xA0"}]:e.find(s=>s.string===t.segment)?[...e,{id:`${t.segment}-${t.index}`,string:t.segment}]:[...e,{id:t.segment,string:t.segment}],[])}function J(n,e,t){let i=n.find(s=>s.string===e);n.push(i?{id:`${e}-${t}`,string:e}:{id:e,string:e});}function V(n,e){let t=e?n.split(" "):n.split(""),i=[];return t.forEach((s,r)=>{e&&r>0&&i.push({id:`space-${r}`,string:"\xA0"}),J(i,s,r);}),i}var x="torph-root",M="torph-item",f="torph-id",d="torph-exiting",b="torph-debug";function w(n){let e=Array.from(n.children),t={};return e.forEach((i,s)=>{if(i.hasAttribute(d))return;let r=i.getAttribute(f)||`child-${s}`;t[r]={x:i.offsetLeft,y:i.offsetTop};}),t}function v(n,e,t){let i=n[t],s=e[t];return !i||!s?{dx:0,dy:0}:{dx:i.x-s.x,dy:i.y-s.y}}function L(n,e,t,i="backward-first"){let[s,r]=i==="backward-first"?["backward","forward"]:["forward","backward"],o=a=>{if(a==="backward"){for(let u=n-1;u>=0;u--)if(t.has(e[u]))return e[u]}else for(let u=n+1;u<e.length;u++)if(t.has(e[u]))return e[u];return null};return o(s)??o(r)}function C(n,e,t,i){let s=new Set(t.filter((o,a)=>i.has(o)&&!e.has(n[a]))),r=new Map;for(let o=0;o<n.length;o++){let a=n[o];e.has(a)&&r.set(a,L(o,t,s,"forward-first"));}return r}function N(n,e){return Math.min(n*e,150)}function I(n){let e=getComputedStyle(n).transform;if(!e||e==="none")return {tx:0,ty:0};let t=e.match(/matrix\(([^)]+)\)/);if(!t)return {tx:0,ty:0};let i=t[1].split(",").map(Number);return {tx:i[4]||0,ty:i[5]||0}}function z(n){let{tx:e,ty:t}=I(n),i=Number(getComputedStyle(n).opacity)||1;return n.getAnimations().forEach(s=>s.cancel()),{tx:e,ty:t,opacity:i}}function k(n,e){let{dx:t,dy:i,duration:s,ease:r,scale:o}=e;n.animate({transform:o?`translate(${t}px, ${i}px) scale(0.95)`:`translate(${t}px, ${i}px)`,offset:1},{duration:s,easing:r,fill:"both"});let a=n.animate({opacity:0,offset:1},{duration:N(s,.25),easing:"linear",fill:"both"});a.onfinish=()=>n.remove();}function P(n,e){let{deltaX:t,deltaY:i,isNew:s,duration:r,ease:o}=e,a=z(n),u=t+a.tx,p=i+a.ty;n.animate({transform:`translate(${u}px, ${p}px) scale(${s?.95:1})`,offset:0},{duration:r,easing:o,fill:"both"});let l=s&&a.opacity>=1?0:a.opacity;l<1&&n.animate([{opacity:l},{opacity:1}],{duration:N(r,s?.5:.25),easing:"linear",fill:"both"});}var T=null;function F(n,e,t,i,s){if(T&&(T(),T=null),e===0||t===0)return;n.style.width="auto",n.style.height="auto",n.offsetWidth;let r=n.offsetWidth,o=n.offsetHeight;n.style.width=`${e}px`,n.style.height=`${t}px`,n.offsetWidth,n.style.width=`${r}px`,n.style.height=`${o}px`;function a(){n.removeEventListener("transitionend",u),clearTimeout(p),T=null,n.style.width="auto",n.style.height="auto",s?.();}function u(l){l.target===n&&(l.propertyName!=="width"&&l.propertyName!=="height"||a());}n.addEventListener("transitionend",u);let p=setTimeout(a,i+50);T=()=>{n.removeEventListener("transitionend",u),clearTimeout(p),T=null;};}function X(n){let e=n.map(t=>{let{tx:i,ty:s}=I(t),r=Number(getComputedStyle(t).opacity)||1;return t.getAnimations().forEach(o=>o.cancel()),{left:t.offsetLeft+i,top:t.offsetTop+s,width:t.offsetWidth,height:t.offsetHeight,opacity:r}});n.forEach((t,i)=>{let s=e[i];t.setAttribute(d,""),t.style.position="absolute",t.style.pointerEvents="none",t.style.left=`${s.left}px`,t.style.top=`${s.top}px`,t.style.width=`${s.width}px`,t.style.height=`${s.height}px`,t.style.opacity=String(s.opacity);});}function G(n,e,t,i){let s=new Map;e.forEach(r=>{let o=r.getAttribute(f);t.has(o)&&!r.hasAttribute(d)&&(s.set(o,r),r.remove());}),Array.from(n.childNodes).forEach(r=>{r.nodeType===Node.TEXT_NODE&&r.remove();}),i.forEach(r=>{let o=s.get(r.id);if(o)o.textContent=r.string,n.appendChild(o);else {let a=document.createElement("span");a.setAttribute(M,""),a.setAttribute(f,r.id),a.textContent=r.string,n.appendChild(a);}});}var Z=`
|
|
2
|
+
[${x}] {
|
|
3
3
|
display: inline-flex;
|
|
4
4
|
position: relative;
|
|
5
5
|
will-change: width, height;
|
|
@@ -7,19 +7,17 @@
|
|
|
7
7
|
white-space: nowrap;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
[
|
|
10
|
+
[${M}] {
|
|
11
11
|
display: inline-block;
|
|
12
12
|
will-change: opacity, transform;
|
|
13
13
|
transform: none;
|
|
14
14
|
opacity: 1;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
[
|
|
18
|
-
outline:2px solid magenta;
|
|
19
|
-
[
|
|
20
|
-
outline:2px solid cyan;
|
|
17
|
+
[${x}][${b}] {
|
|
18
|
+
outline: 2px solid magenta;
|
|
19
|
+
[${M}] {
|
|
20
|
+
outline: 2px solid cyan;
|
|
21
21
|
outline-offset: -4px;
|
|
22
22
|
}
|
|
23
|
-
}
|
|
24
|
-
`,document.head.appendChild(t),h.styleEl=t;}removeStyles(){h.styleEl&&(h.styleEl.remove(),h.styleEl=void 0);}blocks(t){return Array.from(t).reduce((o,i)=>i.segment===" "?[...o,{id:`space-${i.index}`,string:"\xA0"}]:o.find(l=>l.string===i.segment)?[...o,{id:`${i.segment}-${i.index}`,string:i.segment}]:[...o,{id:i.segment,string:i.segment}],[])}blocksFallback(t,s){let o=s?t.split(" "):t.split(""),i=[];return s?o.forEach((a,l)=>{l>0&&i.push({id:`space-${l}`,string:"\xA0"}),i.find(d=>d.string===a)?i.push({id:`${a}-${l}`,string:a}):i.push({id:a,string:a});}):o.forEach((a,l)=>{i.find(d=>d.string===a)?i.push({id:`${a}-${l}`,string:a}):i.push({id:a,string:a});}),i}log(...t){this.options.debug&&console.log("[TextMorph]",...t);}};function w(h){if(typeof h=="string")return h;if(typeof h=="number")return String(h);if(!h||typeof h=="boolean")return "";if(Array.isArray(h))return h.map(w).join("");throw c__default.default.isValidElement(h)?new Error("TextMorph only accepts text content. Found a React element \u2014 use strings, numbers, or expressions instead."):new Error(`TextMorph received an unsupported child of type "${typeof h}".`)}var R=({children:h,className:t,style:s,as:o=A,...i})=>{let{ref:a,update:l}=S(i),p=w(h),d=c__default.default.useRef({__html:p});return c__default.default.useEffect(()=>{l(p);},[p,l]),c__default.default.createElement(o,{ref:a,className:t,style:s,dangerouslySetInnerHTML:d.current})};function S(h){let t=c__default.default.useRef(null),s=c__default.default.useRef(null);c__default.default.useEffect(()=>(t.current&&(s.current=new b({element:t.current,...h})),()=>{s.current?.destroy();}),[]);let o=c__default.default.useCallback(i=>{s.current?.update(i);},[]);return {ref:t,update:o}}exports.TextMorph=R;exports.useTextMorph=S;//# sourceMappingURL=index.js.map
|
|
25
|
-
//# sourceMappingURL=index.js.map
|
|
23
|
+
}`,h=null,O=0;function U(){O++,!h&&(h=document.createElement("style"),h.dataset.torph="true",h.textContent=Z,document.head.appendChild(h));}function W(){O--,!(O>0||!h)&&(h.remove(),h=null);}function j(){if(typeof window>"u")return {prefersReducedMotion:false,destroy:()=>{}};let n=window.matchMedia("(prefers-reduced-motion: reduce)"),e={prefersReducedMotion:n.matches,destroy:i};function t(s){e.prefersReducedMotion=s.matches;}function i(){n.removeEventListener("change",t);}return n.addEventListener("change",t),e}var E=class n{instance=null;lastText="";configKey="";attach(e,t){this.instance?.destroy(),this.instance=new A({element:e,...t}),this.configKey=n.serializeConfig(t),this.lastText&&this.instance.update(this.lastText);}update(e){this.lastText=e,this.instance?.update(e);}needsRecreate(e){return n.serializeConfig(e)!==this.configKey}destroy(){this.instance?.destroy(),this.instance=null;}static serializeConfig(e){return JSON.stringify({ease:e.ease,duration:e.duration,locale:e.locale,scale:e.scale,debug:e.debug,disabled:e.disabled,respectReducedMotion:e.respectReducedMotion})}};var B="span",tt={debug:false,locale:"en",duration:400,scale:true,ease:"cubic-bezier(0.19, 1, 0.22, 1)",disabled:false,respectReducedMotion:true},A=class{element;options={};data;currentMeasures={};prevMeasures={};isInitialRender=true;reducedMotion=null;constructor(e){let{ease:t,...i}={...tt,...e},s,r;if(typeof t=="object"){let o=D(t);s=o.easing,r=o.duration;}else s=t,r=i.duration;this.options={...i,ease:s,duration:r},this.element=e.element,this.options.respectReducedMotion&&(this.reducedMotion=j()),this.isDisabled()||(this.element.setAttribute(x,""),this.element.style.transitionDuration=`${this.options.duration}ms`,this.element.style.transitionTimingFunction=this.options.ease,e.debug&&this.element.setAttribute(b,"")),this.data="",this.isDisabled()||U();}destroy(){this.reducedMotion?.destroy(),this.element.getAnimations().forEach(e=>e.cancel()),this.element.removeAttribute(x),this.element.removeAttribute(b),W();}isDisabled(){return !!(this.options.disabled||this.reducedMotion?.prefersReducedMotion)}update(e){if(e!==this.data){if(this.data=e,this.isDisabled()){typeof e=="string"&&(this.element.textContent=e);return}if(this.data instanceof HTMLElement)throw new Error("HTMLElement not yet supported");this.options.onAnimationStart&&!this.isInitialRender&&this.options.onAnimationStart(),this.createTextGroup(this.data,this.element);}}createTextGroup(e,t){let i=t.offsetWidth,s=t.offsetHeight,r=_(e,this.options.locale);this.prevMeasures=w(this.element);let o=Array.from(t.children),a=new Set(r.map(c=>c.id)),u=o.filter(c=>!a.has(c.getAttribute(f))&&!c.hasAttribute(d)),p=new Set(u),l=o.map(c=>c.getAttribute(f)),m=C(o,p,l,a);if(X(u),G(t,o,a,r),this.currentMeasures=w(this.element),this.updateStyles(r),u.forEach(c=>{if(this.isInitialRender){c.remove();return}let y=m.get(c),{dx:S,dy:R}=y?v(this.currentMeasures,this.prevMeasures,y):{dx:0,dy:0};k(c,{dx:S,dy:R,duration:this.options.duration,ease:this.options.ease,scale:this.options.scale});}),this.isInitialRender){this.isInitialRender=false,t.style.width="auto",t.style.height="auto";return}F(t,i,s,this.options.duration,this.options.onAnimationComplete);}updateStyles(e){if(this.isInitialRender)return;let t=Array.from(this.element.children),i=e.map(r=>r.id),s=new Set(i.filter(r=>this.prevMeasures[r]));t.forEach((r,o)=>{if(r.hasAttribute(d))return;let a=r.getAttribute(f)||`child-${o}`,u=!this.prevMeasures[a],p=u?L(e.findIndex(c=>c.id===a),i,s):a,{dx:l,dy:m}=p?v(this.prevMeasures,this.currentMeasures,p):{dx:0,dy:0};P(r,{deltaX:l,deltaY:m,isNew:u,duration:this.options.duration,ease:this.options.ease});});}};function K(n){if(typeof n=="string")return n;if(typeof n=="number")return String(n);if(!n||typeof n=="boolean")return "";if(Array.isArray(n))return n.map(K).join("");throw g__default.default.isValidElement(n)?new Error("TextMorph only accepts text content. Found a React element \u2014 use strings, numbers, or expressions instead."):new Error(`TextMorph received an unsupported child of type "${typeof n}".`)}var et=({children:n,className:e,style:t,as:i=B,...s})=>{let{ref:r,update:o}=q(s),a=K(n),u=g__default.default.useRef({__html:a});return g__default.default.useEffect(()=>{o(a);},[a,o]),g__default.default.createElement(i,{ref:r,className:e,style:t,dangerouslySetInnerHTML:u.current})};function q(n){let e=g__default.default.useRef(null),t=g__default.default.useRef(new E),i=E.serializeConfig(n);g__default.default.useEffect(()=>(e.current&&t.current.attach(e.current,n),()=>{t.current.destroy();}),[i]);let s=g__default.default.useCallback(r=>{t.current.update(r);},[]);return {ref:e,update:s}}exports.TextMorph=et;exports.useTextMorph=q;
|
package/dist/react/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
[
|
|
1
|
+
import g from'react';function H(n,e,t){if(t<1){let u=e*Math.sqrt(1-t*t);return 1-Math.exp(-t*e*n)*(Math.cos(u*n)+t*e/u*Math.sin(u*n))}let i=Math.sqrt(t*t-1),s=-e*(t+i),r=-e*(t-i),o=-s/(r-s);return 1-(1-o)*Math.exp(s*n)-o*Math.exp(r*n)}function Y(n,e,t){let r=0;for(let o=0;o<10;o+=.001)if(Math.abs(H(o,n,e)-1)>t)r=0;else if(r+=.001,r>.1)return Math.ceil((o-r+.001)*1e3);return Math.ceil(10*1e3)}var $=new Map;function D(n){let{stiffness:e=100,damping:t=10,mass:i=1,precision:s=.001}=n??{},r=`${e}:${t}:${i}:${s}`,o=$.get(r);if(o)return o;let a=Math.sqrt(e/i),u=t/(2*Math.sqrt(e*i)),p=Y(a,u,s),l=Math.min(100,Math.max(32,Math.round(p/15))),m=[];for(let y=0;y<l;y++){let S=y/(l-1)*(p/1e3),R=y===l-1?1:H(S,a,u);m.push(Math.round(R*1e4)/1e4+"");}for(;m.length>2&&m[m.length-2]==="1";)m.splice(m.length-2,1);let c={easing:`linear(${m.join(", ")})`,duration:p};return $.set(r,c),c}function _(n,e){let t=n.includes(" ");if(typeof Intl.Segmenter<"u"){let s=new Intl.Segmenter(e,{granularity:t?"word":"grapheme"}).segment(n)[Symbol.iterator]();return Q(s)}return V(n,t)}function Q(n){return Array.from(n).reduce((e,t)=>t.segment===" "?[...e,{id:`space-${t.index}`,string:"\xA0"}]:e.find(s=>s.string===t.segment)?[...e,{id:`${t.segment}-${t.index}`,string:t.segment}]:[...e,{id:t.segment,string:t.segment}],[])}function J(n,e,t){let i=n.find(s=>s.string===e);n.push(i?{id:`${e}-${t}`,string:e}:{id:e,string:e});}function V(n,e){let t=e?n.split(" "):n.split(""),i=[];return t.forEach((s,r)=>{e&&r>0&&i.push({id:`space-${r}`,string:"\xA0"}),J(i,s,r);}),i}var x="torph-root",M="torph-item",f="torph-id",d="torph-exiting",b="torph-debug";function w(n){let e=Array.from(n.children),t={};return e.forEach((i,s)=>{if(i.hasAttribute(d))return;let r=i.getAttribute(f)||`child-${s}`;t[r]={x:i.offsetLeft,y:i.offsetTop};}),t}function v(n,e,t){let i=n[t],s=e[t];return !i||!s?{dx:0,dy:0}:{dx:i.x-s.x,dy:i.y-s.y}}function L(n,e,t,i="backward-first"){let[s,r]=i==="backward-first"?["backward","forward"]:["forward","backward"],o=a=>{if(a==="backward"){for(let u=n-1;u>=0;u--)if(t.has(e[u]))return e[u]}else for(let u=n+1;u<e.length;u++)if(t.has(e[u]))return e[u];return null};return o(s)??o(r)}function C(n,e,t,i){let s=new Set(t.filter((o,a)=>i.has(o)&&!e.has(n[a]))),r=new Map;for(let o=0;o<n.length;o++){let a=n[o];e.has(a)&&r.set(a,L(o,t,s,"forward-first"));}return r}function N(n,e){return Math.min(n*e,150)}function I(n){let e=getComputedStyle(n).transform;if(!e||e==="none")return {tx:0,ty:0};let t=e.match(/matrix\(([^)]+)\)/);if(!t)return {tx:0,ty:0};let i=t[1].split(",").map(Number);return {tx:i[4]||0,ty:i[5]||0}}function z(n){let{tx:e,ty:t}=I(n),i=Number(getComputedStyle(n).opacity)||1;return n.getAnimations().forEach(s=>s.cancel()),{tx:e,ty:t,opacity:i}}function k(n,e){let{dx:t,dy:i,duration:s,ease:r,scale:o}=e;n.animate({transform:o?`translate(${t}px, ${i}px) scale(0.95)`:`translate(${t}px, ${i}px)`,offset:1},{duration:s,easing:r,fill:"both"});let a=n.animate({opacity:0,offset:1},{duration:N(s,.25),easing:"linear",fill:"both"});a.onfinish=()=>n.remove();}function P(n,e){let{deltaX:t,deltaY:i,isNew:s,duration:r,ease:o}=e,a=z(n),u=t+a.tx,p=i+a.ty;n.animate({transform:`translate(${u}px, ${p}px) scale(${s?.95:1})`,offset:0},{duration:r,easing:o,fill:"both"});let l=s&&a.opacity>=1?0:a.opacity;l<1&&n.animate([{opacity:l},{opacity:1}],{duration:N(r,s?.5:.25),easing:"linear",fill:"both"});}var T=null;function F(n,e,t,i,s){if(T&&(T(),T=null),e===0||t===0)return;n.style.width="auto",n.style.height="auto",n.offsetWidth;let r=n.offsetWidth,o=n.offsetHeight;n.style.width=`${e}px`,n.style.height=`${t}px`,n.offsetWidth,n.style.width=`${r}px`,n.style.height=`${o}px`;function a(){n.removeEventListener("transitionend",u),clearTimeout(p),T=null,n.style.width="auto",n.style.height="auto",s?.();}function u(l){l.target===n&&(l.propertyName!=="width"&&l.propertyName!=="height"||a());}n.addEventListener("transitionend",u);let p=setTimeout(a,i+50);T=()=>{n.removeEventListener("transitionend",u),clearTimeout(p),T=null;};}function X(n){let e=n.map(t=>{let{tx:i,ty:s}=I(t),r=Number(getComputedStyle(t).opacity)||1;return t.getAnimations().forEach(o=>o.cancel()),{left:t.offsetLeft+i,top:t.offsetTop+s,width:t.offsetWidth,height:t.offsetHeight,opacity:r}});n.forEach((t,i)=>{let s=e[i];t.setAttribute(d,""),t.style.position="absolute",t.style.pointerEvents="none",t.style.left=`${s.left}px`,t.style.top=`${s.top}px`,t.style.width=`${s.width}px`,t.style.height=`${s.height}px`,t.style.opacity=String(s.opacity);});}function G(n,e,t,i){let s=new Map;e.forEach(r=>{let o=r.getAttribute(f);t.has(o)&&!r.hasAttribute(d)&&(s.set(o,r),r.remove());}),Array.from(n.childNodes).forEach(r=>{r.nodeType===Node.TEXT_NODE&&r.remove();}),i.forEach(r=>{let o=s.get(r.id);if(o)o.textContent=r.string,n.appendChild(o);else {let a=document.createElement("span");a.setAttribute(M,""),a.setAttribute(f,r.id),a.textContent=r.string,n.appendChild(a);}});}var Z=`
|
|
2
|
+
[${x}] {
|
|
3
3
|
display: inline-flex;
|
|
4
4
|
position: relative;
|
|
5
5
|
will-change: width, height;
|
|
@@ -7,19 +7,17 @@ import c from'react';var A="span",$={debug:false,locale:"en",duration:400,scale:
|
|
|
7
7
|
white-space: nowrap;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
[
|
|
10
|
+
[${M}] {
|
|
11
11
|
display: inline-block;
|
|
12
12
|
will-change: opacity, transform;
|
|
13
13
|
transform: none;
|
|
14
14
|
opacity: 1;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
[
|
|
18
|
-
outline:2px solid magenta;
|
|
19
|
-
[
|
|
20
|
-
outline:2px solid cyan;
|
|
17
|
+
[${x}][${b}] {
|
|
18
|
+
outline: 2px solid magenta;
|
|
19
|
+
[${M}] {
|
|
20
|
+
outline: 2px solid cyan;
|
|
21
21
|
outline-offset: -4px;
|
|
22
22
|
}
|
|
23
|
-
}
|
|
24
|
-
`,document.head.appendChild(t),h.styleEl=t;}removeStyles(){h.styleEl&&(h.styleEl.remove(),h.styleEl=void 0);}blocks(t){return Array.from(t).reduce((o,i)=>i.segment===" "?[...o,{id:`space-${i.index}`,string:"\xA0"}]:o.find(l=>l.string===i.segment)?[...o,{id:`${i.segment}-${i.index}`,string:i.segment}]:[...o,{id:i.segment,string:i.segment}],[])}blocksFallback(t,s){let o=s?t.split(" "):t.split(""),i=[];return s?o.forEach((a,l)=>{l>0&&i.push({id:`space-${l}`,string:"\xA0"}),i.find(d=>d.string===a)?i.push({id:`${a}-${l}`,string:a}):i.push({id:a,string:a});}):o.forEach((a,l)=>{i.find(d=>d.string===a)?i.push({id:`${a}-${l}`,string:a}):i.push({id:a,string:a});}),i}log(...t){this.options.debug&&console.log("[TextMorph]",...t);}};function w(h){if(typeof h=="string")return h;if(typeof h=="number")return String(h);if(!h||typeof h=="boolean")return "";if(Array.isArray(h))return h.map(w).join("");throw c.isValidElement(h)?new Error("TextMorph only accepts text content. Found a React element \u2014 use strings, numbers, or expressions instead."):new Error(`TextMorph received an unsupported child of type "${typeof h}".`)}var R=({children:h,className:t,style:s,as:o=A,...i})=>{let{ref:a,update:l}=S(i),p=w(h),d=c.useRef({__html:p});return c.useEffect(()=>{l(p);},[p,l]),c.createElement(o,{ref:a,className:t,style:s,dangerouslySetInnerHTML:d.current})};function S(h){let t=c.useRef(null),s=c.useRef(null);c.useEffect(()=>(t.current&&(s.current=new b({element:t.current,...h})),()=>{s.current?.destroy();}),[]);let o=c.useCallback(i=>{s.current?.update(i);},[]);return {ref:t,update:o}}export{R as TextMorph,S as useTextMorph};//# sourceMappingURL=index.mjs.map
|
|
25
|
-
//# sourceMappingURL=index.mjs.map
|
|
23
|
+
}`,h=null,O=0;function U(){O++,!h&&(h=document.createElement("style"),h.dataset.torph="true",h.textContent=Z,document.head.appendChild(h));}function W(){O--,!(O>0||!h)&&(h.remove(),h=null);}function j(){if(typeof window>"u")return {prefersReducedMotion:false,destroy:()=>{}};let n=window.matchMedia("(prefers-reduced-motion: reduce)"),e={prefersReducedMotion:n.matches,destroy:i};function t(s){e.prefersReducedMotion=s.matches;}function i(){n.removeEventListener("change",t);}return n.addEventListener("change",t),e}var E=class n{instance=null;lastText="";configKey="";attach(e,t){this.instance?.destroy(),this.instance=new A({element:e,...t}),this.configKey=n.serializeConfig(t),this.lastText&&this.instance.update(this.lastText);}update(e){this.lastText=e,this.instance?.update(e);}needsRecreate(e){return n.serializeConfig(e)!==this.configKey}destroy(){this.instance?.destroy(),this.instance=null;}static serializeConfig(e){return JSON.stringify({ease:e.ease,duration:e.duration,locale:e.locale,scale:e.scale,debug:e.debug,disabled:e.disabled,respectReducedMotion:e.respectReducedMotion})}};var B="span",tt={debug:false,locale:"en",duration:400,scale:true,ease:"cubic-bezier(0.19, 1, 0.22, 1)",disabled:false,respectReducedMotion:true},A=class{element;options={};data;currentMeasures={};prevMeasures={};isInitialRender=true;reducedMotion=null;constructor(e){let{ease:t,...i}={...tt,...e},s,r;if(typeof t=="object"){let o=D(t);s=o.easing,r=o.duration;}else s=t,r=i.duration;this.options={...i,ease:s,duration:r},this.element=e.element,this.options.respectReducedMotion&&(this.reducedMotion=j()),this.isDisabled()||(this.element.setAttribute(x,""),this.element.style.transitionDuration=`${this.options.duration}ms`,this.element.style.transitionTimingFunction=this.options.ease,e.debug&&this.element.setAttribute(b,"")),this.data="",this.isDisabled()||U();}destroy(){this.reducedMotion?.destroy(),this.element.getAnimations().forEach(e=>e.cancel()),this.element.removeAttribute(x),this.element.removeAttribute(b),W();}isDisabled(){return !!(this.options.disabled||this.reducedMotion?.prefersReducedMotion)}update(e){if(e!==this.data){if(this.data=e,this.isDisabled()){typeof e=="string"&&(this.element.textContent=e);return}if(this.data instanceof HTMLElement)throw new Error("HTMLElement not yet supported");this.options.onAnimationStart&&!this.isInitialRender&&this.options.onAnimationStart(),this.createTextGroup(this.data,this.element);}}createTextGroup(e,t){let i=t.offsetWidth,s=t.offsetHeight,r=_(e,this.options.locale);this.prevMeasures=w(this.element);let o=Array.from(t.children),a=new Set(r.map(c=>c.id)),u=o.filter(c=>!a.has(c.getAttribute(f))&&!c.hasAttribute(d)),p=new Set(u),l=o.map(c=>c.getAttribute(f)),m=C(o,p,l,a);if(X(u),G(t,o,a,r),this.currentMeasures=w(this.element),this.updateStyles(r),u.forEach(c=>{if(this.isInitialRender){c.remove();return}let y=m.get(c),{dx:S,dy:R}=y?v(this.currentMeasures,this.prevMeasures,y):{dx:0,dy:0};k(c,{dx:S,dy:R,duration:this.options.duration,ease:this.options.ease,scale:this.options.scale});}),this.isInitialRender){this.isInitialRender=false,t.style.width="auto",t.style.height="auto";return}F(t,i,s,this.options.duration,this.options.onAnimationComplete);}updateStyles(e){if(this.isInitialRender)return;let t=Array.from(this.element.children),i=e.map(r=>r.id),s=new Set(i.filter(r=>this.prevMeasures[r]));t.forEach((r,o)=>{if(r.hasAttribute(d))return;let a=r.getAttribute(f)||`child-${o}`,u=!this.prevMeasures[a],p=u?L(e.findIndex(c=>c.id===a),i,s):a,{dx:l,dy:m}=p?v(this.prevMeasures,this.currentMeasures,p):{dx:0,dy:0};P(r,{deltaX:l,deltaY:m,isNew:u,duration:this.options.duration,ease:this.options.ease});});}};function K(n){if(typeof n=="string")return n;if(typeof n=="number")return String(n);if(!n||typeof n=="boolean")return "";if(Array.isArray(n))return n.map(K).join("");throw g.isValidElement(n)?new Error("TextMorph only accepts text content. Found a React element \u2014 use strings, numbers, or expressions instead."):new Error(`TextMorph received an unsupported child of type "${typeof n}".`)}var et=({children:n,className:e,style:t,as:i=B,...s})=>{let{ref:r,update:o}=q(s),a=K(n),u=g.useRef({__html:a});return g.useEffect(()=>{o(a);},[a,o]),g.createElement(i,{ref:r,className:e,style:t,dangerouslySetInnerHTML:u.current})};function q(n){let e=g.useRef(null),t=g.useRef(new E),i=E.serializeConfig(n);g.useEffect(()=>(e.current&&t.current.attach(e.current,n),()=>{t.current.destroy();}),[i]);let s=g.useCallback(r=>{t.current.update(r);},[]);return {ref:e,update:s}}export{et as TextMorph,q as useTextMorph};
|
package/dist/svelte/index.d.mts
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
interface SpringParams {
|
|
2
|
+
stiffness?: number;
|
|
3
|
+
damping?: number;
|
|
4
|
+
mass?: number;
|
|
5
|
+
precision?: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface TextMorphOptions {
|
|
9
|
+
debug?: boolean;
|
|
10
|
+
element: HTMLElement;
|
|
11
|
+
locale?: Intl.LocalesArgument;
|
|
12
|
+
scale?: boolean;
|
|
13
|
+
duration?: number;
|
|
14
|
+
ease?: string | SpringParams;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
respectReducedMotion?: boolean;
|
|
17
|
+
onAnimationStart?: () => void;
|
|
18
|
+
onAnimationComplete?: () => void;
|
|
19
|
+
}
|
|
2
20
|
|
|
3
21
|
interface TextMorphProps extends Omit<TextMorphOptions, "element"> {
|
|
4
22
|
text: string;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
interface SpringParams {
|
|
2
|
+
stiffness?: number;
|
|
3
|
+
damping?: number;
|
|
4
|
+
mass?: number;
|
|
5
|
+
precision?: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface TextMorphOptions {
|
|
9
|
+
debug?: boolean;
|
|
10
|
+
element: HTMLElement;
|
|
11
|
+
locale?: Intl.LocalesArgument;
|
|
12
|
+
scale?: boolean;
|
|
13
|
+
duration?: number;
|
|
14
|
+
ease?: string | SpringParams;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
respectReducedMotion?: boolean;
|
|
17
|
+
onAnimationStart?: () => void;
|
|
18
|
+
onAnimationComplete?: () => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface TextMorphProps extends Omit<TextMorphOptions, "element"> {
|
|
22
|
+
text: string;
|
|
23
|
+
class?: string;
|
|
24
|
+
style?: string;
|
|
25
|
+
as?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type { TextMorphProps };
|
package/dist/svelte/index.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
'use strict';require('svelte/internal/disclose-version');var e=require('svelte/internal/client'),
|
|
2
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
'use strict';require('svelte/internal/disclose-version');var e=require('svelte/internal/client'),textMorph=require('../lib/text-morph'),controller=require('../lib/text-morph/controller');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var e__namespace=/*#__PURE__*/_interopNamespace(e);function c(s,t){e__namespace.push(t,true);let p=e__namespace.prop(t,"locale",19,()=>textMorph.DEFAULT_TEXT_MORPH_OPTIONS.locale),u=e__namespace.prop(t,"duration",19,()=>textMorph.DEFAULT_TEXT_MORPH_OPTIONS.duration),m=e__namespace.prop(t,"ease",19,()=>textMorph.DEFAULT_TEXT_MORPH_OPTIONS.ease),f=e__namespace.prop(t,"scale",19,()=>textMorph.DEFAULT_TEXT_MORPH_OPTIONS.scale),g=e__namespace.prop(t,"debug",19,()=>textMorph.DEFAULT_TEXT_MORPH_OPTIONS.debug),$=e__namespace.prop(t,"disabled",19,()=>textMorph.DEFAULT_TEXT_MORPH_OPTIONS.disabled),b=e__namespace.prop(t,"respectReducedMotion",19,()=>textMorph.DEFAULT_TEXT_MORPH_OPTIONS.respectReducedMotion),A=e__namespace.prop(t,"onAnimationStart",19,()=>{}),M=e__namespace.prop(t,"onAnimationComplete",19,()=>{}),_=e__namespace.prop(t,"as",3,textMorph.DEFAULT_AS),h=e__namespace.rest_props(t,["$$slots","$$events","$$legacy","text","locale","duration","ease","scale","debug","disabled","respectReducedMotion","onAnimationStart","onAnimationComplete","as"]),a=e__namespace.state(void 0),n=new controller.MorphController,i=e__namespace.derived(()=>({locale:p(),duration:u(),ease:m(),debug:g(),scale:f(),disabled:$(),respectReducedMotion:b(),onAnimationStart:A(),onAnimationComplete:M()})),v=e__namespace.derived(()=>controller.MorphController.serializeConfig(e__namespace.get(i)));e__namespace.user_effect(()=>{if(e__namespace.get(v),e__namespace.get(a))return n.attach(e__namespace.get(a),e__namespace.get(i)),()=>{n.destroy();}}),e__namespace.user_effect(()=>{n.update(t.text);});var r=e__namespace.comment(),x=e__namespace.first_child(r);e__namespace.element(x,_,false,(d,C)=>{e__namespace.bind_this(d,T=>e__namespace.set(a,T,true),()=>e__namespace.get(a)),e__namespace.attribute_effect(d,()=>({...h}));}),e__namespace.append(s,r),e__namespace.pop();}exports.TextMorph=c;
|
package/dist/svelte/index.mjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
import'svelte/internal/disclose-version';import*as e from'svelte/internal/client';import {
|
|
2
|
-
//# sourceMappingURL=index.mjs.map
|
|
1
|
+
import'svelte/internal/disclose-version';import*as e from'svelte/internal/client';import {DEFAULT_TEXT_MORPH_OPTIONS,DEFAULT_AS}from'../lib/text-morph';import {MorphController}from'../lib/text-morph/controller';function c(s,t){e.push(t,true);let p=e.prop(t,"locale",19,()=>DEFAULT_TEXT_MORPH_OPTIONS.locale),u=e.prop(t,"duration",19,()=>DEFAULT_TEXT_MORPH_OPTIONS.duration),m=e.prop(t,"ease",19,()=>DEFAULT_TEXT_MORPH_OPTIONS.ease),f=e.prop(t,"scale",19,()=>DEFAULT_TEXT_MORPH_OPTIONS.scale),g=e.prop(t,"debug",19,()=>DEFAULT_TEXT_MORPH_OPTIONS.debug),$=e.prop(t,"disabled",19,()=>DEFAULT_TEXT_MORPH_OPTIONS.disabled),b=e.prop(t,"respectReducedMotion",19,()=>DEFAULT_TEXT_MORPH_OPTIONS.respectReducedMotion),A=e.prop(t,"onAnimationStart",19,()=>{}),M=e.prop(t,"onAnimationComplete",19,()=>{}),_=e.prop(t,"as",3,DEFAULT_AS),h=e.rest_props(t,["$$slots","$$events","$$legacy","text","locale","duration","ease","scale","debug","disabled","respectReducedMotion","onAnimationStart","onAnimationComplete","as"]),a=e.state(void 0),n=new MorphController,i=e.derived(()=>({locale:p(),duration:u(),ease:m(),debug:g(),scale:f(),disabled:$(),respectReducedMotion:b(),onAnimationStart:A(),onAnimationComplete:M()})),v=e.derived(()=>MorphController.serializeConfig(e.get(i)));e.user_effect(()=>{if(e.get(v),e.get(a))return n.attach(e.get(a),e.get(i)),()=>{n.destroy();}}),e.user_effect(()=>{n.update(t.text);});var r=e.comment(),x=e.first_child(r);e.element(x,_,false,(d,C)=>{e.bind_this(d,T=>e.set(a,T,true),()=>e.get(a)),e.attribute_effect(d,()=>({...h}));}),e.append(s,r),e.pop();}export{c as TextMorph};
|
package/dist/vue/index.d.mts
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
interface SpringParams {
|
|
2
|
+
stiffness?: number;
|
|
3
|
+
damping?: number;
|
|
4
|
+
mass?: number;
|
|
5
|
+
precision?: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface TextMorphOptions {
|
|
9
|
+
debug?: boolean;
|
|
10
|
+
element: HTMLElement;
|
|
11
|
+
locale?: Intl.LocalesArgument;
|
|
12
|
+
scale?: boolean;
|
|
13
|
+
duration?: number;
|
|
14
|
+
ease?: string | SpringParams;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
respectReducedMotion?: boolean;
|
|
17
|
+
onAnimationStart?: () => void;
|
|
18
|
+
onAnimationComplete?: () => void;
|
|
19
|
+
}
|
|
2
20
|
|
|
3
21
|
interface TextMorphProps extends Omit<TextMorphOptions, "element"> {
|
|
4
22
|
text: string;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
interface SpringParams {
|
|
2
|
+
stiffness?: number;
|
|
3
|
+
damping?: number;
|
|
4
|
+
mass?: number;
|
|
5
|
+
precision?: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface TextMorphOptions {
|
|
9
|
+
debug?: boolean;
|
|
10
|
+
element: HTMLElement;
|
|
11
|
+
locale?: Intl.LocalesArgument;
|
|
12
|
+
scale?: boolean;
|
|
13
|
+
duration?: number;
|
|
14
|
+
ease?: string | SpringParams;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
respectReducedMotion?: boolean;
|
|
17
|
+
onAnimationStart?: () => void;
|
|
18
|
+
onAnimationComplete?: () => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface TextMorphProps extends Omit<TextMorphOptions, "element"> {
|
|
22
|
+
text: string;
|
|
23
|
+
class?: string;
|
|
24
|
+
style?: Record<string, string | number>;
|
|
25
|
+
as?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type { TextMorphProps };
|
package/dist/vue/index.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
'use strict';var
|
|
2
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
'use strict';var TextMorphLC6RO5C5_vue=require('../TextMorph-LC6RO5C5.vue');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var TextMorphLC6RO5C5_vue__default=/*#__PURE__*/_interopDefault(TextMorphLC6RO5C5_vue);Object.defineProperty(exports,"TextMorph",{enumerable:true,get:function(){return TextMorphLC6RO5C5_vue__default.default}});
|
package/dist/vue/index.mjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export{default as TextMorph}from'../TextMorph-
|
|
2
|
-
//# sourceMappingURL=index.mjs.map
|
|
1
|
+
export{default as TextMorph}from'../TextMorph-LC6RO5C5.vue';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "torph",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "Dependency-free animated text component.",
|
|
5
5
|
"homepage": "https://torph.lochie.me",
|
|
6
6
|
"author": "Lochie Axon",
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
"url": "git+https://github.com/lochie/torph.git",
|
|
11
11
|
"directory": "packages/torph"
|
|
12
12
|
},
|
|
13
|
+
"main": "dist/index.js",
|
|
14
|
+
"module": "dist/index.mjs",
|
|
13
15
|
"types": "dist/index.d.ts",
|
|
14
16
|
"exports": {
|
|
15
17
|
".": {
|
|
@@ -23,12 +25,18 @@
|
|
|
23
25
|
"require": "./dist/react/index.js"
|
|
24
26
|
},
|
|
25
27
|
"./vue": {
|
|
26
|
-
"types":
|
|
28
|
+
"types": {
|
|
29
|
+
"import": "./dist/vue/index.d.mts",
|
|
30
|
+
"require": "./dist/vue/index.d.ts"
|
|
31
|
+
},
|
|
27
32
|
"import": "./dist/vue/index.mjs",
|
|
28
33
|
"require": "./dist/vue/index.js"
|
|
29
34
|
},
|
|
30
35
|
"./svelte": {
|
|
31
|
-
"types":
|
|
36
|
+
"types": {
|
|
37
|
+
"import": "./dist/svelte/index.d.mts",
|
|
38
|
+
"require": "./dist/svelte/index.d.ts"
|
|
39
|
+
},
|
|
32
40
|
"import": "./dist/svelte/index.mjs",
|
|
33
41
|
"require": "./dist/svelte/index.js"
|
|
34
42
|
}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/text-morph/index.ts"],"names":["DEFAULT_AS","DEFAULT_TEXT_MORPH_OPTIONS","TextMorph","_TextMorph","options","anim","event","value","element","oldWidth","oldHeight","byWord","blocks","iterator","oldChildren","newIds","b","exiting","child","exitingSet","exitingAnchorId","i","anchor","j","siblingId","exitPositions","a","pos","id","node","block","span","anchorId","dx","dy","anchorPrev","anchorCurr","animation","newWidth","newHeight","children","measures","index","key","persistentIds","prev","current","cx","cy","deltaX","deltaY","isNew","blockIndex","duration","delay","style","acc","string","x","segments","segment","args"],"mappings":"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","file":"index.js","sourcesContent":["import type { TextMorphOptions } from \"./types\";\n\nexport type { TextMorphOptions } from \"./types\";\n\nexport const DEFAULT_AS = \"span\";\nexport const DEFAULT_TEXT_MORPH_OPTIONS = {\n debug: false,\n locale: \"en\",\n duration: 400,\n scale: true,\n ease: \"cubic-bezier(0.19, 1, 0.22, 1)\",\n disabled: false,\n respectReducedMotion: true,\n} as const satisfies Omit<TextMorphOptions, \"element\">;\n\ntype Block = {\n id: string;\n string: string;\n};\ntype Measures = {\n [key: string]: { x: number; y: number };\n};\n\nexport class TextMorph {\n private element: HTMLElement;\n private options: Omit<TextMorphOptions, \"element\"> = {};\n\n private data: HTMLElement | string;\n\n private currentMeasures: Measures = {};\n private prevMeasures: Measures = {};\n private isInitialRender = true;\n private prefersReducedMotion = false;\n private mediaQuery?: MediaQueryList;\n\n static styleEl: HTMLStyleElement;\n\n constructor(options: TextMorphOptions) {\n this.options = {\n ...DEFAULT_TEXT_MORPH_OPTIONS,\n ...options,\n };\n\n this.element = options.element;\n\n // reduced motion detection\n if (typeof window !== \"undefined\" && this.options.respectReducedMotion) {\n this.mediaQuery = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n this.prefersReducedMotion = this.mediaQuery.matches;\n this.mediaQuery.addEventListener(\"change\", this.handleMediaQueryChange);\n }\n\n if (!this.isDisabled()) {\n this.element.setAttribute(\"torph-root\", \"\");\n this.element.style.transitionDuration = `${this.options.duration}ms`;\n this.element.style.transitionTimingFunction = this.options.ease!;\n\n if (options.debug) this.element.setAttribute(\"torph-debug\", \"\");\n }\n\n this.data = \"\";\n if (!this.isDisabled()) {\n this.addStyles();\n }\n }\n\n destroy() {\n if (this.mediaQuery) {\n this.mediaQuery.removeEventListener(\n \"change\",\n this.handleMediaQueryChange,\n );\n }\n this.element.getAnimations().forEach((anim) => anim.cancel());\n this.element.removeAttribute(\"torph-root\");\n this.element.removeAttribute(\"torph-debug\");\n this.removeStyles();\n }\n\n private handleMediaQueryChange = (event: MediaQueryListEvent) => {\n this.prefersReducedMotion = event.matches;\n };\n\n private isDisabled(): boolean {\n return Boolean(\n this.options.disabled ||\n (this.options.respectReducedMotion && this.prefersReducedMotion),\n );\n }\n\n update(value: HTMLElement | string) {\n if (value === this.data) return;\n this.data = value;\n\n if (this.isDisabled()) {\n if (typeof value === \"string\") {\n this.element.textContent = value;\n }\n return;\n }\n\n if (this.data instanceof HTMLElement) {\n // TODO: handle HTMLElement case\n throw new Error(\"HTMLElement not yet supported\");\n } else {\n if (this.options.onAnimationStart && !this.isInitialRender) {\n this.options.onAnimationStart();\n }\n this.createTextGroup(this.data, this.element);\n }\n }\n\n private createTextGroup(value: string, element: HTMLElement) {\n const oldWidth = element.offsetWidth;\n const oldHeight = element.offsetHeight;\n\n const byWord = value.includes(\" \");\n let blocks: Block[];\n\n if (typeof Intl.Segmenter !== \"undefined\") {\n const segmenter = new Intl.Segmenter(this.options.locale, {\n granularity: byWord ? \"word\" : \"grapheme\",\n });\n const iterator = segmenter.segment(value)[Symbol.iterator]();\n blocks = this.blocks(iterator);\n } else {\n // Fallback for browsers without Intl.Segmenter\n blocks = this.blocksFallback(value, byWord);\n }\n\n this.prevMeasures = this.measure();\n const oldChildren = Array.from(element.children) as HTMLElement[];\n const newIds = new Set(blocks.map((b) => b.id));\n\n const exiting = oldChildren.filter(\n (child) =>\n !newIds.has(child.getAttribute(\"torph-id\") as string) &&\n !child.hasAttribute(\"torph-exiting\"),\n );\n\n // For each exiting char, find the nearest persistent neighbor in old order\n // so we can make it follow that neighbor's FLIP movement\n const exitingSet = new Set(exiting);\n const exitingAnchorId = new Map<HTMLElement, string | null>();\n for (let i = 0; i < oldChildren.length; i++) {\n const child = oldChildren[i]!;\n if (!exitingSet.has(child)) continue;\n\n // Look forward for nearest persistent char\n let anchor: string | null = null;\n for (let j = i + 1; j < oldChildren.length; j++) {\n const siblingId = oldChildren[j]!.getAttribute(\"torph-id\") as string;\n if (newIds.has(siblingId) && !exitingSet.has(oldChildren[j]!)) {\n anchor = siblingId;\n break;\n }\n }\n // If none forward, look backward\n if (!anchor) {\n for (let j = i - 1; j >= 0; j--) {\n const siblingId = oldChildren[j]!.getAttribute(\"torph-id\") as string;\n if (newIds.has(siblingId) && !exitingSet.has(oldChildren[j]!)) {\n anchor = siblingId;\n break;\n }\n }\n }\n exitingAnchorId.set(child, anchor);\n }\n\n // Two-pass: read all positions before modifying any element,\n // since setting position:absolute removes from flow and shifts siblings\n const exitPositions = exiting.map((child) => {\n child.getAnimations().forEach((a) => a.cancel());\n return {\n left: child.offsetLeft,\n top: child.offsetTop,\n width: child.offsetWidth,\n height: child.offsetHeight,\n };\n });\n exiting.forEach((child, i) => {\n const pos = exitPositions[i]!;\n child.setAttribute(\"torph-exiting\", \"\");\n child.style.position = \"absolute\";\n child.style.pointerEvents = \"none\";\n child.style.left = `${pos.left}px`;\n child.style.top = `${pos.top}px`;\n child.style.width = `${pos.width}px`;\n child.style.height = `${pos.height}px`;\n });\n\n oldChildren.forEach((child) => {\n const id = child.getAttribute(\"torph-id\") as string;\n if (newIds.has(id)) child.remove();\n });\n\n // Disabled-mode updates set plain text via textContent; remove that text node\n // before appending torph items so old content is not duplicated.\n Array.from(element.childNodes).forEach((node) => {\n if (node.nodeType === Node.TEXT_NODE) {\n node.remove();\n }\n });\n\n blocks.forEach((block) => {\n const span = document.createElement(\"span\");\n span.setAttribute(\"torph-item\", \"\");\n span.setAttribute(\"torph-id\", block.id);\n span.textContent = block.string;\n element.appendChild(span);\n });\n\n this.currentMeasures = this.measure();\n this.updateStyles(blocks);\n\n exiting.forEach((child) => {\n if (this.isInitialRender) {\n child.remove();\n return;\n }\n\n // Find the anchor neighbor's FLIP delta so we move in sync with it\n const anchorId = exitingAnchorId.get(child);\n let dx = 0;\n let dy = 0;\n\n if (\n anchorId &&\n this.prevMeasures[anchorId] &&\n this.currentMeasures[anchorId]\n ) {\n const anchorPrev = this.prevMeasures[anchorId]!;\n const anchorCurr = this.currentMeasures[anchorId]!;\n dx = anchorCurr.x - anchorPrev.x;\n dy = anchorCurr.y - anchorPrev.y;\n }\n\n child.animate(\n {\n transform: this.options.scale\n ? `translate(${dx}px, ${dy}px) scale(0.95)`\n : `translate(${dx}px, ${dy}px)`,\n offset: 1,\n },\n {\n duration: this.options.duration,\n easing: this.options.ease,\n fill: \"both\",\n },\n );\n const animation: Animation = child.animate(\n {\n opacity: 0,\n offset: 1,\n },\n {\n duration: this.options.duration! * 0.25,\n easing: \"linear\",\n fill: \"both\",\n },\n );\n animation.onfinish = () => child.remove();\n });\n\n if (this.isInitialRender) {\n this.isInitialRender = false;\n element.style.width = \"auto\";\n element.style.height = \"auto\";\n return;\n }\n\n if (oldWidth === 0 || oldHeight === 0) return;\n\n element.style.width = \"auto\";\n element.style.height = \"auto\";\n void element.offsetWidth; // force reflow\n\n const newWidth = element.offsetWidth;\n const newHeight = element.offsetHeight;\n\n element.style.width = `${oldWidth}px`;\n element.style.height = `${oldHeight}px`;\n void element.offsetWidth; // force reflow\n\n element.style.width = `${newWidth}px`;\n element.style.height = `${newHeight}px`;\n\n // TODO: move to `transitionend` event listener\n setTimeout(() => {\n element.style.width = \"auto\";\n element.style.height = \"auto\";\n if (this.options.onAnimationComplete) {\n this.options.onAnimationComplete();\n }\n }, this.options.duration);\n }\n\n private measure() {\n const children = Array.from(this.element.children) as HTMLElement[];\n const measures: Measures = {};\n\n children.forEach((child, index) => {\n if (child.hasAttribute(\"torph-exiting\")) return;\n const key = child.getAttribute(\"torph-id\") || `child-${index}`;\n measures[key] = {\n x: child.offsetLeft,\n y: child.offsetTop,\n };\n });\n\n return measures;\n }\n\n private updateStyles(blocks: Block[]) {\n if (this.isInitialRender) return;\n\n const children = Array.from(this.element.children) as HTMLElement[];\n\n const persistentIds = new Set(\n blocks.map((b) => b.id).filter((id) => this.prevMeasures[id]),\n );\n\n children.forEach((child, index) => {\n if (child.hasAttribute(\"torph-exiting\")) return;\n const key = child.getAttribute(\"torph-id\") || `child-${index}`;\n const prev = this.prevMeasures[key];\n const current = this.currentMeasures[key];\n\n const cx = current?.x || 0;\n const cy = current?.y || 0;\n\n let deltaX = prev ? prev.x - cx : 0;\n let deltaY = prev ? prev.y - cy : 0;\n const isNew = !prev;\n\n // For new chars, use the nearest persistent neighbor's FLIP delta\n // so all new chars get the same consistent offset\n if (isNew) {\n const blockIndex = blocks.findIndex((b) => b.id === key);\n let anchorId: string | null = null;\n\n for (let j = blockIndex - 1; j >= 0; j--) {\n if (persistentIds.has(blocks[j]!.id)) {\n anchorId = blocks[j]!.id;\n break;\n }\n }\n if (!anchorId) {\n for (let j = blockIndex + 1; j < blocks.length; j++) {\n if (persistentIds.has(blocks[j]!.id)) {\n anchorId = blocks[j]!.id;\n break;\n }\n }\n }\n\n if (anchorId) {\n const anchorPrev = this.prevMeasures[anchorId]!;\n const anchorCurr = this.currentMeasures[anchorId]!;\n deltaX = anchorPrev.x - anchorCurr.x;\n deltaY = anchorPrev.y - anchorCurr.y;\n }\n }\n\n child.getAnimations().forEach((a) => a.cancel());\n child.animate(\n {\n transform: `translate(${deltaX}px, ${deltaY}px) scale(${isNew ? 0.95 : 1})`,\n offset: 0,\n },\n {\n duration: this.options.duration,\n easing: this.options.ease,\n fill: \"both\",\n },\n );\n const duration = isNew ? this.options.duration! * 0.25 : 0;\n const delay = isNew ? this.options.duration! * 0.25 : 0;\n child.animate(\n {\n opacity: isNew ? 0 : 1,\n offset: 0,\n },\n {\n duration: duration,\n delay: delay,\n easing: \"linear\",\n fill: \"both\",\n },\n );\n });\n }\n\n private addStyles() {\n if (TextMorph.styleEl) return;\n\n const style = document.createElement(\"style\");\n style.dataset.torph = \"true\";\n style.innerHTML = `\n[torph-root] {\n display: inline-flex;\n position: relative;\n will-change: width, height;\n transition-property: width, height;\n white-space: nowrap;\n}\n\n[torph-item] {\n display: inline-block;\n will-change: opacity, transform;\n transform: none;\n opacity: 1;\n}\n\n[torph-root][torph-debug] {\n outline:2px solid magenta;\n [torph-item] {\n outline:2px solid cyan;\n outline-offset: -4px;\n }\n}\n `;\n document.head.appendChild(style);\n TextMorph.styleEl = style;\n }\n\n private removeStyles() {\n if (TextMorph.styleEl) {\n TextMorph.styleEl.remove();\n TextMorph.styleEl = undefined!;\n }\n }\n\n // utils\n\n private blocks(iterator: Intl.SegmentIterator<Intl.SegmentData>) {\n const uniqueStrings: Block[] = Array.from(iterator).reduce(\n (acc, string) => {\n if (string.segment === \" \") {\n return [...acc, { id: `space-${string.index}`, string: \"\\u00A0\" }];\n }\n\n const existingString = acc.find((x) => x.string === string.segment);\n if (existingString) {\n return [\n ...acc,\n { id: `${string.segment}-${string.index}`, string: string.segment },\n ];\n }\n\n return [\n ...acc,\n {\n id: string.segment,\n string: string.segment,\n },\n ];\n },\n [] as Block[],\n );\n\n return uniqueStrings;\n }\n\n private blocksFallback(value: string, byWord: boolean): Block[] {\n const segments = byWord ? value.split(\" \") : value.split(\"\");\n const blocks: Block[] = [];\n\n if (byWord) {\n segments.forEach((segment, index) => {\n if (index > 0) {\n blocks.push({ id: `space-${index}`, string: \"\\u00A0\" });\n }\n const existing = blocks.find((x) => x.string === segment);\n if (existing) {\n blocks.push({ id: `${segment}-${index}`, string: segment });\n } else {\n blocks.push({ id: segment, string: segment });\n }\n });\n } else {\n segments.forEach((segment, index) => {\n const existing = blocks.find((x) => x.string === segment);\n if (existing) {\n blocks.push({ id: `${segment}-${index}`, string: segment });\n } else {\n blocks.push({ id: segment, string: segment });\n }\n });\n }\n\n return blocks;\n }\n\n private log(...args: any[]) {\n if (this.options.debug) console.log(\"[TextMorph]\", ...args);\n }\n}\n"]}
|
package/dist/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/text-morph/index.ts"],"names":["DEFAULT_AS","DEFAULT_TEXT_MORPH_OPTIONS","TextMorph","_TextMorph","options","anim","event","value","element","oldWidth","oldHeight","byWord","blocks","iterator","oldChildren","newIds","b","exiting","child","exitingSet","exitingAnchorId","i","anchor","j","siblingId","exitPositions","a","pos","id","node","block","span","anchorId","dx","dy","anchorPrev","anchorCurr","animation","newWidth","newHeight","children","measures","index","key","persistentIds","prev","current","cx","cy","deltaX","deltaY","isNew","blockIndex","duration","delay","style","acc","string","x","segments","segment","args"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { TextMorphOptions } from \"./types\";\n\nexport type { TextMorphOptions } from \"./types\";\n\nexport const DEFAULT_AS = \"span\";\nexport const DEFAULT_TEXT_MORPH_OPTIONS = {\n debug: false,\n locale: \"en\",\n duration: 400,\n scale: true,\n ease: \"cubic-bezier(0.19, 1, 0.22, 1)\",\n disabled: false,\n respectReducedMotion: true,\n} as const satisfies Omit<TextMorphOptions, \"element\">;\n\ntype Block = {\n id: string;\n string: string;\n};\ntype Measures = {\n [key: string]: { x: number; y: number };\n};\n\nexport class TextMorph {\n private element: HTMLElement;\n private options: Omit<TextMorphOptions, \"element\"> = {};\n\n private data: HTMLElement | string;\n\n private currentMeasures: Measures = {};\n private prevMeasures: Measures = {};\n private isInitialRender = true;\n private prefersReducedMotion = false;\n private mediaQuery?: MediaQueryList;\n\n static styleEl: HTMLStyleElement;\n\n constructor(options: TextMorphOptions) {\n this.options = {\n ...DEFAULT_TEXT_MORPH_OPTIONS,\n ...options,\n };\n\n this.element = options.element;\n\n // reduced motion detection\n if (typeof window !== \"undefined\" && this.options.respectReducedMotion) {\n this.mediaQuery = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n this.prefersReducedMotion = this.mediaQuery.matches;\n this.mediaQuery.addEventListener(\"change\", this.handleMediaQueryChange);\n }\n\n if (!this.isDisabled()) {\n this.element.setAttribute(\"torph-root\", \"\");\n this.element.style.transitionDuration = `${this.options.duration}ms`;\n this.element.style.transitionTimingFunction = this.options.ease!;\n\n if (options.debug) this.element.setAttribute(\"torph-debug\", \"\");\n }\n\n this.data = \"\";\n if (!this.isDisabled()) {\n this.addStyles();\n }\n }\n\n destroy() {\n if (this.mediaQuery) {\n this.mediaQuery.removeEventListener(\n \"change\",\n this.handleMediaQueryChange,\n );\n }\n this.element.getAnimations().forEach((anim) => anim.cancel());\n this.element.removeAttribute(\"torph-root\");\n this.element.removeAttribute(\"torph-debug\");\n this.removeStyles();\n }\n\n private handleMediaQueryChange = (event: MediaQueryListEvent) => {\n this.prefersReducedMotion = event.matches;\n };\n\n private isDisabled(): boolean {\n return Boolean(\n this.options.disabled ||\n (this.options.respectReducedMotion && this.prefersReducedMotion),\n );\n }\n\n update(value: HTMLElement | string) {\n if (value === this.data) return;\n this.data = value;\n\n if (this.isDisabled()) {\n if (typeof value === \"string\") {\n this.element.textContent = value;\n }\n return;\n }\n\n if (this.data instanceof HTMLElement) {\n // TODO: handle HTMLElement case\n throw new Error(\"HTMLElement not yet supported\");\n } else {\n if (this.options.onAnimationStart && !this.isInitialRender) {\n this.options.onAnimationStart();\n }\n this.createTextGroup(this.data, this.element);\n }\n }\n\n private createTextGroup(value: string, element: HTMLElement) {\n const oldWidth = element.offsetWidth;\n const oldHeight = element.offsetHeight;\n\n const byWord = value.includes(\" \");\n let blocks: Block[];\n\n if (typeof Intl.Segmenter !== \"undefined\") {\n const segmenter = new Intl.Segmenter(this.options.locale, {\n granularity: byWord ? \"word\" : \"grapheme\",\n });\n const iterator = segmenter.segment(value)[Symbol.iterator]();\n blocks = this.blocks(iterator);\n } else {\n // Fallback for browsers without Intl.Segmenter\n blocks = this.blocksFallback(value, byWord);\n }\n\n this.prevMeasures = this.measure();\n const oldChildren = Array.from(element.children) as HTMLElement[];\n const newIds = new Set(blocks.map((b) => b.id));\n\n const exiting = oldChildren.filter(\n (child) =>\n !newIds.has(child.getAttribute(\"torph-id\") as string) &&\n !child.hasAttribute(\"torph-exiting\"),\n );\n\n // For each exiting char, find the nearest persistent neighbor in old order\n // so we can make it follow that neighbor's FLIP movement\n const exitingSet = new Set(exiting);\n const exitingAnchorId = new Map<HTMLElement, string | null>();\n for (let i = 0; i < oldChildren.length; i++) {\n const child = oldChildren[i]!;\n if (!exitingSet.has(child)) continue;\n\n // Look forward for nearest persistent char\n let anchor: string | null = null;\n for (let j = i + 1; j < oldChildren.length; j++) {\n const siblingId = oldChildren[j]!.getAttribute(\"torph-id\") as string;\n if (newIds.has(siblingId) && !exitingSet.has(oldChildren[j]!)) {\n anchor = siblingId;\n break;\n }\n }\n // If none forward, look backward\n if (!anchor) {\n for (let j = i - 1; j >= 0; j--) {\n const siblingId = oldChildren[j]!.getAttribute(\"torph-id\") as string;\n if (newIds.has(siblingId) && !exitingSet.has(oldChildren[j]!)) {\n anchor = siblingId;\n break;\n }\n }\n }\n exitingAnchorId.set(child, anchor);\n }\n\n // Two-pass: read all positions before modifying any element,\n // since setting position:absolute removes from flow and shifts siblings\n const exitPositions = exiting.map((child) => {\n child.getAnimations().forEach((a) => a.cancel());\n return {\n left: child.offsetLeft,\n top: child.offsetTop,\n width: child.offsetWidth,\n height: child.offsetHeight,\n };\n });\n exiting.forEach((child, i) => {\n const pos = exitPositions[i]!;\n child.setAttribute(\"torph-exiting\", \"\");\n child.style.position = \"absolute\";\n child.style.pointerEvents = \"none\";\n child.style.left = `${pos.left}px`;\n child.style.top = `${pos.top}px`;\n child.style.width = `${pos.width}px`;\n child.style.height = `${pos.height}px`;\n });\n\n oldChildren.forEach((child) => {\n const id = child.getAttribute(\"torph-id\") as string;\n if (newIds.has(id)) child.remove();\n });\n\n // Disabled-mode updates set plain text via textContent; remove that text node\n // before appending torph items so old content is not duplicated.\n Array.from(element.childNodes).forEach((node) => {\n if (node.nodeType === Node.TEXT_NODE) {\n node.remove();\n }\n });\n\n blocks.forEach((block) => {\n const span = document.createElement(\"span\");\n span.setAttribute(\"torph-item\", \"\");\n span.setAttribute(\"torph-id\", block.id);\n span.textContent = block.string;\n element.appendChild(span);\n });\n\n this.currentMeasures = this.measure();\n this.updateStyles(blocks);\n\n exiting.forEach((child) => {\n if (this.isInitialRender) {\n child.remove();\n return;\n }\n\n // Find the anchor neighbor's FLIP delta so we move in sync with it\n const anchorId = exitingAnchorId.get(child);\n let dx = 0;\n let dy = 0;\n\n if (\n anchorId &&\n this.prevMeasures[anchorId] &&\n this.currentMeasures[anchorId]\n ) {\n const anchorPrev = this.prevMeasures[anchorId]!;\n const anchorCurr = this.currentMeasures[anchorId]!;\n dx = anchorCurr.x - anchorPrev.x;\n dy = anchorCurr.y - anchorPrev.y;\n }\n\n child.animate(\n {\n transform: this.options.scale\n ? `translate(${dx}px, ${dy}px) scale(0.95)`\n : `translate(${dx}px, ${dy}px)`,\n offset: 1,\n },\n {\n duration: this.options.duration,\n easing: this.options.ease,\n fill: \"both\",\n },\n );\n const animation: Animation = child.animate(\n {\n opacity: 0,\n offset: 1,\n },\n {\n duration: this.options.duration! * 0.25,\n easing: \"linear\",\n fill: \"both\",\n },\n );\n animation.onfinish = () => child.remove();\n });\n\n if (this.isInitialRender) {\n this.isInitialRender = false;\n element.style.width = \"auto\";\n element.style.height = \"auto\";\n return;\n }\n\n if (oldWidth === 0 || oldHeight === 0) return;\n\n element.style.width = \"auto\";\n element.style.height = \"auto\";\n void element.offsetWidth; // force reflow\n\n const newWidth = element.offsetWidth;\n const newHeight = element.offsetHeight;\n\n element.style.width = `${oldWidth}px`;\n element.style.height = `${oldHeight}px`;\n void element.offsetWidth; // force reflow\n\n element.style.width = `${newWidth}px`;\n element.style.height = `${newHeight}px`;\n\n // TODO: move to `transitionend` event listener\n setTimeout(() => {\n element.style.width = \"auto\";\n element.style.height = \"auto\";\n if (this.options.onAnimationComplete) {\n this.options.onAnimationComplete();\n }\n }, this.options.duration);\n }\n\n private measure() {\n const children = Array.from(this.element.children) as HTMLElement[];\n const measures: Measures = {};\n\n children.forEach((child, index) => {\n if (child.hasAttribute(\"torph-exiting\")) return;\n const key = child.getAttribute(\"torph-id\") || `child-${index}`;\n measures[key] = {\n x: child.offsetLeft,\n y: child.offsetTop,\n };\n });\n\n return measures;\n }\n\n private updateStyles(blocks: Block[]) {\n if (this.isInitialRender) return;\n\n const children = Array.from(this.element.children) as HTMLElement[];\n\n const persistentIds = new Set(\n blocks.map((b) => b.id).filter((id) => this.prevMeasures[id]),\n );\n\n children.forEach((child, index) => {\n if (child.hasAttribute(\"torph-exiting\")) return;\n const key = child.getAttribute(\"torph-id\") || `child-${index}`;\n const prev = this.prevMeasures[key];\n const current = this.currentMeasures[key];\n\n const cx = current?.x || 0;\n const cy = current?.y || 0;\n\n let deltaX = prev ? prev.x - cx : 0;\n let deltaY = prev ? prev.y - cy : 0;\n const isNew = !prev;\n\n // For new chars, use the nearest persistent neighbor's FLIP delta\n // so all new chars get the same consistent offset\n if (isNew) {\n const blockIndex = blocks.findIndex((b) => b.id === key);\n let anchorId: string | null = null;\n\n for (let j = blockIndex - 1; j >= 0; j--) {\n if (persistentIds.has(blocks[j]!.id)) {\n anchorId = blocks[j]!.id;\n break;\n }\n }\n if (!anchorId) {\n for (let j = blockIndex + 1; j < blocks.length; j++) {\n if (persistentIds.has(blocks[j]!.id)) {\n anchorId = blocks[j]!.id;\n break;\n }\n }\n }\n\n if (anchorId) {\n const anchorPrev = this.prevMeasures[anchorId]!;\n const anchorCurr = this.currentMeasures[anchorId]!;\n deltaX = anchorPrev.x - anchorCurr.x;\n deltaY = anchorPrev.y - anchorCurr.y;\n }\n }\n\n child.getAnimations().forEach((a) => a.cancel());\n child.animate(\n {\n transform: `translate(${deltaX}px, ${deltaY}px) scale(${isNew ? 0.95 : 1})`,\n offset: 0,\n },\n {\n duration: this.options.duration,\n easing: this.options.ease,\n fill: \"both\",\n },\n );\n const duration = isNew ? this.options.duration! * 0.25 : 0;\n const delay = isNew ? this.options.duration! * 0.25 : 0;\n child.animate(\n {\n opacity: isNew ? 0 : 1,\n offset: 0,\n },\n {\n duration: duration,\n delay: delay,\n easing: \"linear\",\n fill: \"both\",\n },\n );\n });\n }\n\n private addStyles() {\n if (TextMorph.styleEl) return;\n\n const style = document.createElement(\"style\");\n style.dataset.torph = \"true\";\n style.innerHTML = `\n[torph-root] {\n display: inline-flex;\n position: relative;\n will-change: width, height;\n transition-property: width, height;\n white-space: nowrap;\n}\n\n[torph-item] {\n display: inline-block;\n will-change: opacity, transform;\n transform: none;\n opacity: 1;\n}\n\n[torph-root][torph-debug] {\n outline:2px solid magenta;\n [torph-item] {\n outline:2px solid cyan;\n outline-offset: -4px;\n }\n}\n `;\n document.head.appendChild(style);\n TextMorph.styleEl = style;\n }\n\n private removeStyles() {\n if (TextMorph.styleEl) {\n TextMorph.styleEl.remove();\n TextMorph.styleEl = undefined!;\n }\n }\n\n // utils\n\n private blocks(iterator: Intl.SegmentIterator<Intl.SegmentData>) {\n const uniqueStrings: Block[] = Array.from(iterator).reduce(\n (acc, string) => {\n if (string.segment === \" \") {\n return [...acc, { id: `space-${string.index}`, string: \"\\u00A0\" }];\n }\n\n const existingString = acc.find((x) => x.string === string.segment);\n if (existingString) {\n return [\n ...acc,\n { id: `${string.segment}-${string.index}`, string: string.segment },\n ];\n }\n\n return [\n ...acc,\n {\n id: string.segment,\n string: string.segment,\n },\n ];\n },\n [] as Block[],\n );\n\n return uniqueStrings;\n }\n\n private blocksFallback(value: string, byWord: boolean): Block[] {\n const segments = byWord ? value.split(\" \") : value.split(\"\");\n const blocks: Block[] = [];\n\n if (byWord) {\n segments.forEach((segment, index) => {\n if (index > 0) {\n blocks.push({ id: `space-${index}`, string: \"\\u00A0\" });\n }\n const existing = blocks.find((x) => x.string === segment);\n if (existing) {\n blocks.push({ id: `${segment}-${index}`, string: segment });\n } else {\n blocks.push({ id: segment, string: segment });\n }\n });\n } else {\n segments.forEach((segment, index) => {\n const existing = blocks.find((x) => x.string === segment);\n if (existing) {\n blocks.push({ id: `${segment}-${index}`, string: segment });\n } else {\n blocks.push({ id: segment, string: segment });\n }\n });\n }\n\n return blocks;\n }\n\n private log(...args: any[]) {\n if (this.options.debug) console.log(\"[TextMorph]\", ...args);\n }\n}\n"]}
|
package/dist/react/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/text-morph/index.ts","../../src/react/TextMorph.tsx"],"names":["DEFAULT_AS","DEFAULT_TEXT_MORPH_OPTIONS","TextMorph","_TextMorph","options","anim","event","value","element","oldWidth","oldHeight","byWord","blocks","iterator","oldChildren","newIds","b","exiting","child","exitingSet","exitingAnchorId","i","anchor","j","siblingId","exitPositions","a","pos","id","node","block","span","anchorId","dx","dy","anchorPrev","anchorCurr","animation","newWidth","newHeight","children","measures","index","key","persistentIds","prev","current","cx","cy","deltaX","deltaY","isNew","blockIndex","duration","delay","style","acc","string","x","segments","segment","args","childrenToString","React","className","as","props","ref","update","useTextMorph","text","initialHTML","morphRef"],"mappings":"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","file":"index.js","sourcesContent":["import type { TextMorphOptions } from \"./types\";\n\nexport type { TextMorphOptions } from \"./types\";\n\nexport const DEFAULT_AS = \"span\";\nexport const DEFAULT_TEXT_MORPH_OPTIONS = {\n debug: false,\n locale: \"en\",\n duration: 400,\n scale: true,\n ease: \"cubic-bezier(0.19, 1, 0.22, 1)\",\n disabled: false,\n respectReducedMotion: true,\n} as const satisfies Omit<TextMorphOptions, \"element\">;\n\ntype Block = {\n id: string;\n string: string;\n};\ntype Measures = {\n [key: string]: { x: number; y: number };\n};\n\nexport class TextMorph {\n private element: HTMLElement;\n private options: Omit<TextMorphOptions, \"element\"> = {};\n\n private data: HTMLElement | string;\n\n private currentMeasures: Measures = {};\n private prevMeasures: Measures = {};\n private isInitialRender = true;\n private prefersReducedMotion = false;\n private mediaQuery?: MediaQueryList;\n\n static styleEl: HTMLStyleElement;\n\n constructor(options: TextMorphOptions) {\n this.options = {\n ...DEFAULT_TEXT_MORPH_OPTIONS,\n ...options,\n };\n\n this.element = options.element;\n\n // reduced motion detection\n if (typeof window !== \"undefined\" && this.options.respectReducedMotion) {\n this.mediaQuery = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n this.prefersReducedMotion = this.mediaQuery.matches;\n this.mediaQuery.addEventListener(\"change\", this.handleMediaQueryChange);\n }\n\n if (!this.isDisabled()) {\n this.element.setAttribute(\"torph-root\", \"\");\n this.element.style.transitionDuration = `${this.options.duration}ms`;\n this.element.style.transitionTimingFunction = this.options.ease!;\n\n if (options.debug) this.element.setAttribute(\"torph-debug\", \"\");\n }\n\n this.data = \"\";\n if (!this.isDisabled()) {\n this.addStyles();\n }\n }\n\n destroy() {\n if (this.mediaQuery) {\n this.mediaQuery.removeEventListener(\n \"change\",\n this.handleMediaQueryChange,\n );\n }\n this.element.getAnimations().forEach((anim) => anim.cancel());\n this.element.removeAttribute(\"torph-root\");\n this.element.removeAttribute(\"torph-debug\");\n this.removeStyles();\n }\n\n private handleMediaQueryChange = (event: MediaQueryListEvent) => {\n this.prefersReducedMotion = event.matches;\n };\n\n private isDisabled(): boolean {\n return Boolean(\n this.options.disabled ||\n (this.options.respectReducedMotion && this.prefersReducedMotion),\n );\n }\n\n update(value: HTMLElement | string) {\n if (value === this.data) return;\n this.data = value;\n\n if (this.isDisabled()) {\n if (typeof value === \"string\") {\n this.element.textContent = value;\n }\n return;\n }\n\n if (this.data instanceof HTMLElement) {\n // TODO: handle HTMLElement case\n throw new Error(\"HTMLElement not yet supported\");\n } else {\n if (this.options.onAnimationStart && !this.isInitialRender) {\n this.options.onAnimationStart();\n }\n this.createTextGroup(this.data, this.element);\n }\n }\n\n private createTextGroup(value: string, element: HTMLElement) {\n const oldWidth = element.offsetWidth;\n const oldHeight = element.offsetHeight;\n\n const byWord = value.includes(\" \");\n let blocks: Block[];\n\n if (typeof Intl.Segmenter !== \"undefined\") {\n const segmenter = new Intl.Segmenter(this.options.locale, {\n granularity: byWord ? \"word\" : \"grapheme\",\n });\n const iterator = segmenter.segment(value)[Symbol.iterator]();\n blocks = this.blocks(iterator);\n } else {\n // Fallback for browsers without Intl.Segmenter\n blocks = this.blocksFallback(value, byWord);\n }\n\n this.prevMeasures = this.measure();\n const oldChildren = Array.from(element.children) as HTMLElement[];\n const newIds = new Set(blocks.map((b) => b.id));\n\n const exiting = oldChildren.filter(\n (child) =>\n !newIds.has(child.getAttribute(\"torph-id\") as string) &&\n !child.hasAttribute(\"torph-exiting\"),\n );\n\n // For each exiting char, find the nearest persistent neighbor in old order\n // so we can make it follow that neighbor's FLIP movement\n const exitingSet = new Set(exiting);\n const exitingAnchorId = new Map<HTMLElement, string | null>();\n for (let i = 0; i < oldChildren.length; i++) {\n const child = oldChildren[i]!;\n if (!exitingSet.has(child)) continue;\n\n // Look forward for nearest persistent char\n let anchor: string | null = null;\n for (let j = i + 1; j < oldChildren.length; j++) {\n const siblingId = oldChildren[j]!.getAttribute(\"torph-id\") as string;\n if (newIds.has(siblingId) && !exitingSet.has(oldChildren[j]!)) {\n anchor = siblingId;\n break;\n }\n }\n // If none forward, look backward\n if (!anchor) {\n for (let j = i - 1; j >= 0; j--) {\n const siblingId = oldChildren[j]!.getAttribute(\"torph-id\") as string;\n if (newIds.has(siblingId) && !exitingSet.has(oldChildren[j]!)) {\n anchor = siblingId;\n break;\n }\n }\n }\n exitingAnchorId.set(child, anchor);\n }\n\n // Two-pass: read all positions before modifying any element,\n // since setting position:absolute removes from flow and shifts siblings\n const exitPositions = exiting.map((child) => {\n child.getAnimations().forEach((a) => a.cancel());\n return {\n left: child.offsetLeft,\n top: child.offsetTop,\n width: child.offsetWidth,\n height: child.offsetHeight,\n };\n });\n exiting.forEach((child, i) => {\n const pos = exitPositions[i]!;\n child.setAttribute(\"torph-exiting\", \"\");\n child.style.position = \"absolute\";\n child.style.pointerEvents = \"none\";\n child.style.left = `${pos.left}px`;\n child.style.top = `${pos.top}px`;\n child.style.width = `${pos.width}px`;\n child.style.height = `${pos.height}px`;\n });\n\n oldChildren.forEach((child) => {\n const id = child.getAttribute(\"torph-id\") as string;\n if (newIds.has(id)) child.remove();\n });\n\n // Disabled-mode updates set plain text via textContent; remove that text node\n // before appending torph items so old content is not duplicated.\n Array.from(element.childNodes).forEach((node) => {\n if (node.nodeType === Node.TEXT_NODE) {\n node.remove();\n }\n });\n\n blocks.forEach((block) => {\n const span = document.createElement(\"span\");\n span.setAttribute(\"torph-item\", \"\");\n span.setAttribute(\"torph-id\", block.id);\n span.textContent = block.string;\n element.appendChild(span);\n });\n\n this.currentMeasures = this.measure();\n this.updateStyles(blocks);\n\n exiting.forEach((child) => {\n if (this.isInitialRender) {\n child.remove();\n return;\n }\n\n // Find the anchor neighbor's FLIP delta so we move in sync with it\n const anchorId = exitingAnchorId.get(child);\n let dx = 0;\n let dy = 0;\n\n if (\n anchorId &&\n this.prevMeasures[anchorId] &&\n this.currentMeasures[anchorId]\n ) {\n const anchorPrev = this.prevMeasures[anchorId]!;\n const anchorCurr = this.currentMeasures[anchorId]!;\n dx = anchorCurr.x - anchorPrev.x;\n dy = anchorCurr.y - anchorPrev.y;\n }\n\n child.animate(\n {\n transform: this.options.scale\n ? `translate(${dx}px, ${dy}px) scale(0.95)`\n : `translate(${dx}px, ${dy}px)`,\n offset: 1,\n },\n {\n duration: this.options.duration,\n easing: this.options.ease,\n fill: \"both\",\n },\n );\n const animation: Animation = child.animate(\n {\n opacity: 0,\n offset: 1,\n },\n {\n duration: this.options.duration! * 0.25,\n easing: \"linear\",\n fill: \"both\",\n },\n );\n animation.onfinish = () => child.remove();\n });\n\n if (this.isInitialRender) {\n this.isInitialRender = false;\n element.style.width = \"auto\";\n element.style.height = \"auto\";\n return;\n }\n\n if (oldWidth === 0 || oldHeight === 0) return;\n\n element.style.width = \"auto\";\n element.style.height = \"auto\";\n void element.offsetWidth; // force reflow\n\n const newWidth = element.offsetWidth;\n const newHeight = element.offsetHeight;\n\n element.style.width = `${oldWidth}px`;\n element.style.height = `${oldHeight}px`;\n void element.offsetWidth; // force reflow\n\n element.style.width = `${newWidth}px`;\n element.style.height = `${newHeight}px`;\n\n // TODO: move to `transitionend` event listener\n setTimeout(() => {\n element.style.width = \"auto\";\n element.style.height = \"auto\";\n if (this.options.onAnimationComplete) {\n this.options.onAnimationComplete();\n }\n }, this.options.duration);\n }\n\n private measure() {\n const children = Array.from(this.element.children) as HTMLElement[];\n const measures: Measures = {};\n\n children.forEach((child, index) => {\n if (child.hasAttribute(\"torph-exiting\")) return;\n const key = child.getAttribute(\"torph-id\") || `child-${index}`;\n measures[key] = {\n x: child.offsetLeft,\n y: child.offsetTop,\n };\n });\n\n return measures;\n }\n\n private updateStyles(blocks: Block[]) {\n if (this.isInitialRender) return;\n\n const children = Array.from(this.element.children) as HTMLElement[];\n\n const persistentIds = new Set(\n blocks.map((b) => b.id).filter((id) => this.prevMeasures[id]),\n );\n\n children.forEach((child, index) => {\n if (child.hasAttribute(\"torph-exiting\")) return;\n const key = child.getAttribute(\"torph-id\") || `child-${index}`;\n const prev = this.prevMeasures[key];\n const current = this.currentMeasures[key];\n\n const cx = current?.x || 0;\n const cy = current?.y || 0;\n\n let deltaX = prev ? prev.x - cx : 0;\n let deltaY = prev ? prev.y - cy : 0;\n const isNew = !prev;\n\n // For new chars, use the nearest persistent neighbor's FLIP delta\n // so all new chars get the same consistent offset\n if (isNew) {\n const blockIndex = blocks.findIndex((b) => b.id === key);\n let anchorId: string | null = null;\n\n for (let j = blockIndex - 1; j >= 0; j--) {\n if (persistentIds.has(blocks[j]!.id)) {\n anchorId = blocks[j]!.id;\n break;\n }\n }\n if (!anchorId) {\n for (let j = blockIndex + 1; j < blocks.length; j++) {\n if (persistentIds.has(blocks[j]!.id)) {\n anchorId = blocks[j]!.id;\n break;\n }\n }\n }\n\n if (anchorId) {\n const anchorPrev = this.prevMeasures[anchorId]!;\n const anchorCurr = this.currentMeasures[anchorId]!;\n deltaX = anchorPrev.x - anchorCurr.x;\n deltaY = anchorPrev.y - anchorCurr.y;\n }\n }\n\n child.getAnimations().forEach((a) => a.cancel());\n child.animate(\n {\n transform: `translate(${deltaX}px, ${deltaY}px) scale(${isNew ? 0.95 : 1})`,\n offset: 0,\n },\n {\n duration: this.options.duration,\n easing: this.options.ease,\n fill: \"both\",\n },\n );\n const duration = isNew ? this.options.duration! * 0.25 : 0;\n const delay = isNew ? this.options.duration! * 0.25 : 0;\n child.animate(\n {\n opacity: isNew ? 0 : 1,\n offset: 0,\n },\n {\n duration: duration,\n delay: delay,\n easing: \"linear\",\n fill: \"both\",\n },\n );\n });\n }\n\n private addStyles() {\n if (TextMorph.styleEl) return;\n\n const style = document.createElement(\"style\");\n style.dataset.torph = \"true\";\n style.innerHTML = `\n[torph-root] {\n display: inline-flex;\n position: relative;\n will-change: width, height;\n transition-property: width, height;\n white-space: nowrap;\n}\n\n[torph-item] {\n display: inline-block;\n will-change: opacity, transform;\n transform: none;\n opacity: 1;\n}\n\n[torph-root][torph-debug] {\n outline:2px solid magenta;\n [torph-item] {\n outline:2px solid cyan;\n outline-offset: -4px;\n }\n}\n `;\n document.head.appendChild(style);\n TextMorph.styleEl = style;\n }\n\n private removeStyles() {\n if (TextMorph.styleEl) {\n TextMorph.styleEl.remove();\n TextMorph.styleEl = undefined!;\n }\n }\n\n // utils\n\n private blocks(iterator: Intl.SegmentIterator<Intl.SegmentData>) {\n const uniqueStrings: Block[] = Array.from(iterator).reduce(\n (acc, string) => {\n if (string.segment === \" \") {\n return [...acc, { id: `space-${string.index}`, string: \"\\u00A0\" }];\n }\n\n const existingString = acc.find((x) => x.string === string.segment);\n if (existingString) {\n return [\n ...acc,\n { id: `${string.segment}-${string.index}`, string: string.segment },\n ];\n }\n\n return [\n ...acc,\n {\n id: string.segment,\n string: string.segment,\n },\n ];\n },\n [] as Block[],\n );\n\n return uniqueStrings;\n }\n\n private blocksFallback(value: string, byWord: boolean): Block[] {\n const segments = byWord ? value.split(\" \") : value.split(\"\");\n const blocks: Block[] = [];\n\n if (byWord) {\n segments.forEach((segment, index) => {\n if (index > 0) {\n blocks.push({ id: `space-${index}`, string: \"\\u00A0\" });\n }\n const existing = blocks.find((x) => x.string === segment);\n if (existing) {\n blocks.push({ id: `${segment}-${index}`, string: segment });\n } else {\n blocks.push({ id: segment, string: segment });\n }\n });\n } else {\n segments.forEach((segment, index) => {\n const existing = blocks.find((x) => x.string === segment);\n if (existing) {\n blocks.push({ id: `${segment}-${index}`, string: segment });\n } else {\n blocks.push({ id: segment, string: segment });\n }\n });\n }\n\n return blocks;\n }\n\n private log(...args: any[]) {\n if (this.options.debug) console.log(\"[TextMorph]\", ...args);\n }\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { DEFAULT_AS, TextMorph as Morph } from \"../lib/text-morph\";\nimport type { TextMorphOptions } from \"../lib/text-morph/types\";\n\nexport type TextMorphProps = Omit<TextMorphOptions, \"element\"> & {\n children: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n as?: React.ElementType;\n};\n\nfunction childrenToString(node: React.ReactNode): string {\n if (typeof node === \"string\") return node;\n if (typeof node === \"number\") return String(node);\n if (!node || typeof node === \"boolean\") return \"\";\n if (Array.isArray(node)) return node.map(childrenToString).join(\"\");\n if (React.isValidElement(node)) {\n throw new Error(\n \"TextMorph only accepts text content. Found a React element — use strings, numbers, or expressions instead.\"\n );\n }\n throw new Error(\n `TextMorph received an unsupported child of type \"${typeof node}\".`\n );\n}\n\nexport const TextMorph = ({\n children,\n className,\n style,\n as = DEFAULT_AS,\n ...props\n}: TextMorphProps) => {\n const { ref, update } = useTextMorph(props);\n const text = childrenToString(children);\n const initialHTML = React.useRef({ __html: text });\n\n React.useEffect(() => {\n update(text);\n }, [text, update]);\n\n const Component = as;\n\n return (\n <Component\n ref={ref}\n className={className}\n style={style}\n dangerouslySetInnerHTML={initialHTML.current}\n />\n );\n};\n\nexport function useTextMorph(props: Omit<TextMorphOptions, \"element\">) {\n const ref = React.useRef<HTMLDivElement | null>(null);\n const morphRef = React.useRef<Morph | null>(null);\n\n React.useEffect(() => {\n if (ref.current) {\n morphRef.current = new Morph({ element: ref.current, ...props });\n }\n\n return () => {\n morphRef.current?.destroy();\n };\n }, []);\n\n const update = React.useCallback((text: string) => {\n morphRef.current?.update(text);\n }, []);\n\n return { ref, update };\n}\n"]}
|
package/dist/react/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/text-morph/index.ts","../../src/react/TextMorph.tsx"],"names":["DEFAULT_AS","DEFAULT_TEXT_MORPH_OPTIONS","TextMorph","_TextMorph","options","anim","event","value","element","oldWidth","oldHeight","byWord","blocks","iterator","oldChildren","newIds","b","exiting","child","exitingSet","exitingAnchorId","i","anchor","j","siblingId","exitPositions","a","pos","id","node","block","span","anchorId","dx","dy","anchorPrev","anchorCurr","animation","newWidth","newHeight","children","measures","index","key","persistentIds","prev","current","cx","cy","deltaX","deltaY","isNew","blockIndex","duration","delay","style","acc","string","x","segments","segment","args","childrenToString","React","className","as","props","ref","update","useTextMorph","text","initialHTML","morphRef"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { TextMorphOptions } from \"./types\";\n\nexport type { TextMorphOptions } from \"./types\";\n\nexport const DEFAULT_AS = \"span\";\nexport const DEFAULT_TEXT_MORPH_OPTIONS = {\n debug: false,\n locale: \"en\",\n duration: 400,\n scale: true,\n ease: \"cubic-bezier(0.19, 1, 0.22, 1)\",\n disabled: false,\n respectReducedMotion: true,\n} as const satisfies Omit<TextMorphOptions, \"element\">;\n\ntype Block = {\n id: string;\n string: string;\n};\ntype Measures = {\n [key: string]: { x: number; y: number };\n};\n\nexport class TextMorph {\n private element: HTMLElement;\n private options: Omit<TextMorphOptions, \"element\"> = {};\n\n private data: HTMLElement | string;\n\n private currentMeasures: Measures = {};\n private prevMeasures: Measures = {};\n private isInitialRender = true;\n private prefersReducedMotion = false;\n private mediaQuery?: MediaQueryList;\n\n static styleEl: HTMLStyleElement;\n\n constructor(options: TextMorphOptions) {\n this.options = {\n ...DEFAULT_TEXT_MORPH_OPTIONS,\n ...options,\n };\n\n this.element = options.element;\n\n // reduced motion detection\n if (typeof window !== \"undefined\" && this.options.respectReducedMotion) {\n this.mediaQuery = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n this.prefersReducedMotion = this.mediaQuery.matches;\n this.mediaQuery.addEventListener(\"change\", this.handleMediaQueryChange);\n }\n\n if (!this.isDisabled()) {\n this.element.setAttribute(\"torph-root\", \"\");\n this.element.style.transitionDuration = `${this.options.duration}ms`;\n this.element.style.transitionTimingFunction = this.options.ease!;\n\n if (options.debug) this.element.setAttribute(\"torph-debug\", \"\");\n }\n\n this.data = \"\";\n if (!this.isDisabled()) {\n this.addStyles();\n }\n }\n\n destroy() {\n if (this.mediaQuery) {\n this.mediaQuery.removeEventListener(\n \"change\",\n this.handleMediaQueryChange,\n );\n }\n this.element.getAnimations().forEach((anim) => anim.cancel());\n this.element.removeAttribute(\"torph-root\");\n this.element.removeAttribute(\"torph-debug\");\n this.removeStyles();\n }\n\n private handleMediaQueryChange = (event: MediaQueryListEvent) => {\n this.prefersReducedMotion = event.matches;\n };\n\n private isDisabled(): boolean {\n return Boolean(\n this.options.disabled ||\n (this.options.respectReducedMotion && this.prefersReducedMotion),\n );\n }\n\n update(value: HTMLElement | string) {\n if (value === this.data) return;\n this.data = value;\n\n if (this.isDisabled()) {\n if (typeof value === \"string\") {\n this.element.textContent = value;\n }\n return;\n }\n\n if (this.data instanceof HTMLElement) {\n // TODO: handle HTMLElement case\n throw new Error(\"HTMLElement not yet supported\");\n } else {\n if (this.options.onAnimationStart && !this.isInitialRender) {\n this.options.onAnimationStart();\n }\n this.createTextGroup(this.data, this.element);\n }\n }\n\n private createTextGroup(value: string, element: HTMLElement) {\n const oldWidth = element.offsetWidth;\n const oldHeight = element.offsetHeight;\n\n const byWord = value.includes(\" \");\n let blocks: Block[];\n\n if (typeof Intl.Segmenter !== \"undefined\") {\n const segmenter = new Intl.Segmenter(this.options.locale, {\n granularity: byWord ? \"word\" : \"grapheme\",\n });\n const iterator = segmenter.segment(value)[Symbol.iterator]();\n blocks = this.blocks(iterator);\n } else {\n // Fallback for browsers without Intl.Segmenter\n blocks = this.blocksFallback(value, byWord);\n }\n\n this.prevMeasures = this.measure();\n const oldChildren = Array.from(element.children) as HTMLElement[];\n const newIds = new Set(blocks.map((b) => b.id));\n\n const exiting = oldChildren.filter(\n (child) =>\n !newIds.has(child.getAttribute(\"torph-id\") as string) &&\n !child.hasAttribute(\"torph-exiting\"),\n );\n\n // For each exiting char, find the nearest persistent neighbor in old order\n // so we can make it follow that neighbor's FLIP movement\n const exitingSet = new Set(exiting);\n const exitingAnchorId = new Map<HTMLElement, string | null>();\n for (let i = 0; i < oldChildren.length; i++) {\n const child = oldChildren[i]!;\n if (!exitingSet.has(child)) continue;\n\n // Look forward for nearest persistent char\n let anchor: string | null = null;\n for (let j = i + 1; j < oldChildren.length; j++) {\n const siblingId = oldChildren[j]!.getAttribute(\"torph-id\") as string;\n if (newIds.has(siblingId) && !exitingSet.has(oldChildren[j]!)) {\n anchor = siblingId;\n break;\n }\n }\n // If none forward, look backward\n if (!anchor) {\n for (let j = i - 1; j >= 0; j--) {\n const siblingId = oldChildren[j]!.getAttribute(\"torph-id\") as string;\n if (newIds.has(siblingId) && !exitingSet.has(oldChildren[j]!)) {\n anchor = siblingId;\n break;\n }\n }\n }\n exitingAnchorId.set(child, anchor);\n }\n\n // Two-pass: read all positions before modifying any element,\n // since setting position:absolute removes from flow and shifts siblings\n const exitPositions = exiting.map((child) => {\n child.getAnimations().forEach((a) => a.cancel());\n return {\n left: child.offsetLeft,\n top: child.offsetTop,\n width: child.offsetWidth,\n height: child.offsetHeight,\n };\n });\n exiting.forEach((child, i) => {\n const pos = exitPositions[i]!;\n child.setAttribute(\"torph-exiting\", \"\");\n child.style.position = \"absolute\";\n child.style.pointerEvents = \"none\";\n child.style.left = `${pos.left}px`;\n child.style.top = `${pos.top}px`;\n child.style.width = `${pos.width}px`;\n child.style.height = `${pos.height}px`;\n });\n\n oldChildren.forEach((child) => {\n const id = child.getAttribute(\"torph-id\") as string;\n if (newIds.has(id)) child.remove();\n });\n\n // Disabled-mode updates set plain text via textContent; remove that text node\n // before appending torph items so old content is not duplicated.\n Array.from(element.childNodes).forEach((node) => {\n if (node.nodeType === Node.TEXT_NODE) {\n node.remove();\n }\n });\n\n blocks.forEach((block) => {\n const span = document.createElement(\"span\");\n span.setAttribute(\"torph-item\", \"\");\n span.setAttribute(\"torph-id\", block.id);\n span.textContent = block.string;\n element.appendChild(span);\n });\n\n this.currentMeasures = this.measure();\n this.updateStyles(blocks);\n\n exiting.forEach((child) => {\n if (this.isInitialRender) {\n child.remove();\n return;\n }\n\n // Find the anchor neighbor's FLIP delta so we move in sync with it\n const anchorId = exitingAnchorId.get(child);\n let dx = 0;\n let dy = 0;\n\n if (\n anchorId &&\n this.prevMeasures[anchorId] &&\n this.currentMeasures[anchorId]\n ) {\n const anchorPrev = this.prevMeasures[anchorId]!;\n const anchorCurr = this.currentMeasures[anchorId]!;\n dx = anchorCurr.x - anchorPrev.x;\n dy = anchorCurr.y - anchorPrev.y;\n }\n\n child.animate(\n {\n transform: this.options.scale\n ? `translate(${dx}px, ${dy}px) scale(0.95)`\n : `translate(${dx}px, ${dy}px)`,\n offset: 1,\n },\n {\n duration: this.options.duration,\n easing: this.options.ease,\n fill: \"both\",\n },\n );\n const animation: Animation = child.animate(\n {\n opacity: 0,\n offset: 1,\n },\n {\n duration: this.options.duration! * 0.25,\n easing: \"linear\",\n fill: \"both\",\n },\n );\n animation.onfinish = () => child.remove();\n });\n\n if (this.isInitialRender) {\n this.isInitialRender = false;\n element.style.width = \"auto\";\n element.style.height = \"auto\";\n return;\n }\n\n if (oldWidth === 0 || oldHeight === 0) return;\n\n element.style.width = \"auto\";\n element.style.height = \"auto\";\n void element.offsetWidth; // force reflow\n\n const newWidth = element.offsetWidth;\n const newHeight = element.offsetHeight;\n\n element.style.width = `${oldWidth}px`;\n element.style.height = `${oldHeight}px`;\n void element.offsetWidth; // force reflow\n\n element.style.width = `${newWidth}px`;\n element.style.height = `${newHeight}px`;\n\n // TODO: move to `transitionend` event listener\n setTimeout(() => {\n element.style.width = \"auto\";\n element.style.height = \"auto\";\n if (this.options.onAnimationComplete) {\n this.options.onAnimationComplete();\n }\n }, this.options.duration);\n }\n\n private measure() {\n const children = Array.from(this.element.children) as HTMLElement[];\n const measures: Measures = {};\n\n children.forEach((child, index) => {\n if (child.hasAttribute(\"torph-exiting\")) return;\n const key = child.getAttribute(\"torph-id\") || `child-${index}`;\n measures[key] = {\n x: child.offsetLeft,\n y: child.offsetTop,\n };\n });\n\n return measures;\n }\n\n private updateStyles(blocks: Block[]) {\n if (this.isInitialRender) return;\n\n const children = Array.from(this.element.children) as HTMLElement[];\n\n const persistentIds = new Set(\n blocks.map((b) => b.id).filter((id) => this.prevMeasures[id]),\n );\n\n children.forEach((child, index) => {\n if (child.hasAttribute(\"torph-exiting\")) return;\n const key = child.getAttribute(\"torph-id\") || `child-${index}`;\n const prev = this.prevMeasures[key];\n const current = this.currentMeasures[key];\n\n const cx = current?.x || 0;\n const cy = current?.y || 0;\n\n let deltaX = prev ? prev.x - cx : 0;\n let deltaY = prev ? prev.y - cy : 0;\n const isNew = !prev;\n\n // For new chars, use the nearest persistent neighbor's FLIP delta\n // so all new chars get the same consistent offset\n if (isNew) {\n const blockIndex = blocks.findIndex((b) => b.id === key);\n let anchorId: string | null = null;\n\n for (let j = blockIndex - 1; j >= 0; j--) {\n if (persistentIds.has(blocks[j]!.id)) {\n anchorId = blocks[j]!.id;\n break;\n }\n }\n if (!anchorId) {\n for (let j = blockIndex + 1; j < blocks.length; j++) {\n if (persistentIds.has(blocks[j]!.id)) {\n anchorId = blocks[j]!.id;\n break;\n }\n }\n }\n\n if (anchorId) {\n const anchorPrev = this.prevMeasures[anchorId]!;\n const anchorCurr = this.currentMeasures[anchorId]!;\n deltaX = anchorPrev.x - anchorCurr.x;\n deltaY = anchorPrev.y - anchorCurr.y;\n }\n }\n\n child.getAnimations().forEach((a) => a.cancel());\n child.animate(\n {\n transform: `translate(${deltaX}px, ${deltaY}px) scale(${isNew ? 0.95 : 1})`,\n offset: 0,\n },\n {\n duration: this.options.duration,\n easing: this.options.ease,\n fill: \"both\",\n },\n );\n const duration = isNew ? this.options.duration! * 0.25 : 0;\n const delay = isNew ? this.options.duration! * 0.25 : 0;\n child.animate(\n {\n opacity: isNew ? 0 : 1,\n offset: 0,\n },\n {\n duration: duration,\n delay: delay,\n easing: \"linear\",\n fill: \"both\",\n },\n );\n });\n }\n\n private addStyles() {\n if (TextMorph.styleEl) return;\n\n const style = document.createElement(\"style\");\n style.dataset.torph = \"true\";\n style.innerHTML = `\n[torph-root] {\n display: inline-flex;\n position: relative;\n will-change: width, height;\n transition-property: width, height;\n white-space: nowrap;\n}\n\n[torph-item] {\n display: inline-block;\n will-change: opacity, transform;\n transform: none;\n opacity: 1;\n}\n\n[torph-root][torph-debug] {\n outline:2px solid magenta;\n [torph-item] {\n outline:2px solid cyan;\n outline-offset: -4px;\n }\n}\n `;\n document.head.appendChild(style);\n TextMorph.styleEl = style;\n }\n\n private removeStyles() {\n if (TextMorph.styleEl) {\n TextMorph.styleEl.remove();\n TextMorph.styleEl = undefined!;\n }\n }\n\n // utils\n\n private blocks(iterator: Intl.SegmentIterator<Intl.SegmentData>) {\n const uniqueStrings: Block[] = Array.from(iterator).reduce(\n (acc, string) => {\n if (string.segment === \" \") {\n return [...acc, { id: `space-${string.index}`, string: \"\\u00A0\" }];\n }\n\n const existingString = acc.find((x) => x.string === string.segment);\n if (existingString) {\n return [\n ...acc,\n { id: `${string.segment}-${string.index}`, string: string.segment },\n ];\n }\n\n return [\n ...acc,\n {\n id: string.segment,\n string: string.segment,\n },\n ];\n },\n [] as Block[],\n );\n\n return uniqueStrings;\n }\n\n private blocksFallback(value: string, byWord: boolean): Block[] {\n const segments = byWord ? value.split(\" \") : value.split(\"\");\n const blocks: Block[] = [];\n\n if (byWord) {\n segments.forEach((segment, index) => {\n if (index > 0) {\n blocks.push({ id: `space-${index}`, string: \"\\u00A0\" });\n }\n const existing = blocks.find((x) => x.string === segment);\n if (existing) {\n blocks.push({ id: `${segment}-${index}`, string: segment });\n } else {\n blocks.push({ id: segment, string: segment });\n }\n });\n } else {\n segments.forEach((segment, index) => {\n const existing = blocks.find((x) => x.string === segment);\n if (existing) {\n blocks.push({ id: `${segment}-${index}`, string: segment });\n } else {\n blocks.push({ id: segment, string: segment });\n }\n });\n }\n\n return blocks;\n }\n\n private log(...args: any[]) {\n if (this.options.debug) console.log(\"[TextMorph]\", ...args);\n }\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { DEFAULT_AS, TextMorph as Morph } from \"../lib/text-morph\";\nimport type { TextMorphOptions } from \"../lib/text-morph/types\";\n\nexport type TextMorphProps = Omit<TextMorphOptions, \"element\"> & {\n children: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n as?: React.ElementType;\n};\n\nfunction childrenToString(node: React.ReactNode): string {\n if (typeof node === \"string\") return node;\n if (typeof node === \"number\") return String(node);\n if (!node || typeof node === \"boolean\") return \"\";\n if (Array.isArray(node)) return node.map(childrenToString).join(\"\");\n if (React.isValidElement(node)) {\n throw new Error(\n \"TextMorph only accepts text content. Found a React element — use strings, numbers, or expressions instead.\"\n );\n }\n throw new Error(\n `TextMorph received an unsupported child of type \"${typeof node}\".`\n );\n}\n\nexport const TextMorph = ({\n children,\n className,\n style,\n as = DEFAULT_AS,\n ...props\n}: TextMorphProps) => {\n const { ref, update } = useTextMorph(props);\n const text = childrenToString(children);\n const initialHTML = React.useRef({ __html: text });\n\n React.useEffect(() => {\n update(text);\n }, [text, update]);\n\n const Component = as;\n\n return (\n <Component\n ref={ref}\n className={className}\n style={style}\n dangerouslySetInnerHTML={initialHTML.current}\n />\n );\n};\n\nexport function useTextMorph(props: Omit<TextMorphOptions, \"element\">) {\n const ref = React.useRef<HTMLDivElement | null>(null);\n const morphRef = React.useRef<Morph | null>(null);\n\n React.useEffect(() => {\n if (ref.current) {\n morphRef.current = new Morph({ element: ref.current, ...props });\n }\n\n return () => {\n morphRef.current?.destroy();\n };\n }, []);\n\n const update = React.useCallback((text: string) => {\n morphRef.current?.update(text);\n }, []);\n\n return { ref, update };\n}\n"]}
|
package/dist/svelte/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/svelte/TextMorph.svelte"],"names":["TextMorph","$$anchor","$$props","e","locale","DEFAULT_TEXT_MORPH_OPTIONS","duration","ease","scale","debug","disabled","respectReducedMotion","onAnimationStart","onAnimationComplete","as","DEFAULT_AS","props","containerRef","morphInstance","onMount","Morph","fragment","node","$$element","$$value"],"mappings":"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","file":"index.js","sourcesContent":["import 'svelte/internal/disclose-version';\nimport * as $ from 'svelte/internal/client';\nimport { onMount } from \"svelte\";\nimport { DEFAULT_AS, DEFAULT_TEXT_MORPH_OPTIONS, TextMorph as Morph } from \"../lib/text-morph\";\n\nexport default function TextMorph($$anchor, $$props) {\n\t$.push($$props, true);\n\n\tlet locale = $.prop($$props, 'locale', 19, () => DEFAULT_TEXT_MORPH_OPTIONS.locale),\n\t\tduration = $.prop($$props, 'duration', 19, () => DEFAULT_TEXT_MORPH_OPTIONS.duration),\n\t\tease = $.prop($$props, 'ease', 19, () => DEFAULT_TEXT_MORPH_OPTIONS.ease),\n\t\tscale = $.prop($$props, 'scale', 19, () => DEFAULT_TEXT_MORPH_OPTIONS.scale),\n\t\tdebug = $.prop($$props, 'debug', 19, () => DEFAULT_TEXT_MORPH_OPTIONS.debug),\n\t\tdisabled = $.prop($$props, 'disabled', 19, () => DEFAULT_TEXT_MORPH_OPTIONS.disabled),\n\t\trespectReducedMotion = $.prop($$props, 'respectReducedMotion', 19, () => DEFAULT_TEXT_MORPH_OPTIONS.respectReducedMotion),\n\t\tonAnimationStart = $.prop($$props, 'onAnimationStart', 19, () => void 0),\n\t\tonAnimationComplete = $.prop($$props, 'onAnimationComplete', 19, () => void 0),\n\t\tas = $.prop($$props, 'as', 3, DEFAULT_AS),\n\t\tprops = $.rest_props($$props, [\n\t\t\t'$$slots',\n\t\t\t'$$events',\n\t\t\t'$$legacy',\n\t\t\t'text',\n\t\t\t'locale',\n\t\t\t'duration',\n\t\t\t'ease',\n\t\t\t'scale',\n\t\t\t'debug',\n\t\t\t'disabled',\n\t\t\t'respectReducedMotion',\n\t\t\t'onAnimationStart',\n\t\t\t'onAnimationComplete',\n\t\t\t'as'\n\t\t]);\n\n\tlet containerRef = $.state(void 0);\n\tlet morphInstance = $.state(null);\n\n\tonMount(() => {\n\t\tif ($.get(containerRef)) {\n\t\t\t$.set(\n\t\t\t\tmorphInstance,\n\t\t\t\tnew Morph({\n\t\t\t\t\telement: $.get(containerRef),\n\t\t\t\t\tlocale: locale(),\n\t\t\t\t\tduration: duration(),\n\t\t\t\t\tease: ease(),\n\t\t\t\t\tdebug: debug(),\n\t\t\t\t\tscale: scale(),\n\t\t\t\t\tdisabled: disabled(),\n\t\t\t\t\trespectReducedMotion: respectReducedMotion(),\n\t\t\t\t\tonAnimationStart: onAnimationStart(),\n\t\t\t\t\tonAnimationComplete: onAnimationComplete()\n\t\t\t\t}),\n\t\t\t\ttrue\n\t\t\t);\n\n\t\t\t$.get(morphInstance).update($$props.text);\n\t\t}\n\n\t\treturn () => {\n\t\t\t$.get(morphInstance)?.destroy();\n\t\t};\n\t});\n\n\t$.user_effect(() => {\n\t\tif ($.get(morphInstance)) {\n\t\t\t$.get(morphInstance).update($$props.text);\n\t\t}\n\t});\n\n\tvar fragment = $.comment();\n\tvar node = $.first_child(fragment);\n\n\t$.element(node, as, false, ($$element, $$anchor) => {\n\t\t$.bind_this($$element, ($$value) => $.set(containerRef, $$value, true), () => $.get(containerRef));\n\t\t$.attribute_effect($$element, () => ({ ...props }));\n\t});\n\n\t$.append($$anchor, fragment);\n\t$.pop();\n}"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/svelte/TextMorph.svelte"],"names":["TextMorph","$$anchor","$$props","locale","DEFAULT_TEXT_MORPH_OPTIONS","duration","ease","scale","debug","disabled","respectReducedMotion","onAnimationStart","onAnimationComplete","as","DEFAULT_AS","props","containerRef","morphInstance","onMount","Morph","fragment","node","$$element","$$value"],"mappings":"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","file":"index.mjs","sourcesContent":["import 'svelte/internal/disclose-version';\nimport * as $ from 'svelte/internal/client';\nimport { onMount } from \"svelte\";\nimport { DEFAULT_AS, DEFAULT_TEXT_MORPH_OPTIONS, TextMorph as Morph } from \"../lib/text-morph\";\n\nexport default function TextMorph($$anchor, $$props) {\n\t$.push($$props, true);\n\n\tlet locale = $.prop($$props, 'locale', 19, () => DEFAULT_TEXT_MORPH_OPTIONS.locale),\n\t\tduration = $.prop($$props, 'duration', 19, () => DEFAULT_TEXT_MORPH_OPTIONS.duration),\n\t\tease = $.prop($$props, 'ease', 19, () => DEFAULT_TEXT_MORPH_OPTIONS.ease),\n\t\tscale = $.prop($$props, 'scale', 19, () => DEFAULT_TEXT_MORPH_OPTIONS.scale),\n\t\tdebug = $.prop($$props, 'debug', 19, () => DEFAULT_TEXT_MORPH_OPTIONS.debug),\n\t\tdisabled = $.prop($$props, 'disabled', 19, () => DEFAULT_TEXT_MORPH_OPTIONS.disabled),\n\t\trespectReducedMotion = $.prop($$props, 'respectReducedMotion', 19, () => DEFAULT_TEXT_MORPH_OPTIONS.respectReducedMotion),\n\t\tonAnimationStart = $.prop($$props, 'onAnimationStart', 19, () => void 0),\n\t\tonAnimationComplete = $.prop($$props, 'onAnimationComplete', 19, () => void 0),\n\t\tas = $.prop($$props, 'as', 3, DEFAULT_AS),\n\t\tprops = $.rest_props($$props, [\n\t\t\t'$$slots',\n\t\t\t'$$events',\n\t\t\t'$$legacy',\n\t\t\t'text',\n\t\t\t'locale',\n\t\t\t'duration',\n\t\t\t'ease',\n\t\t\t'scale',\n\t\t\t'debug',\n\t\t\t'disabled',\n\t\t\t'respectReducedMotion',\n\t\t\t'onAnimationStart',\n\t\t\t'onAnimationComplete',\n\t\t\t'as'\n\t\t]);\n\n\tlet containerRef = $.state(void 0);\n\tlet morphInstance = $.state(null);\n\n\tonMount(() => {\n\t\tif ($.get(containerRef)) {\n\t\t\t$.set(\n\t\t\t\tmorphInstance,\n\t\t\t\tnew Morph({\n\t\t\t\t\telement: $.get(containerRef),\n\t\t\t\t\tlocale: locale(),\n\t\t\t\t\tduration: duration(),\n\t\t\t\t\tease: ease(),\n\t\t\t\t\tdebug: debug(),\n\t\t\t\t\tscale: scale(),\n\t\t\t\t\tdisabled: disabled(),\n\t\t\t\t\trespectReducedMotion: respectReducedMotion(),\n\t\t\t\t\tonAnimationStart: onAnimationStart(),\n\t\t\t\t\tonAnimationComplete: onAnimationComplete()\n\t\t\t\t}),\n\t\t\t\ttrue\n\t\t\t);\n\n\t\t\t$.get(morphInstance).update($$props.text);\n\t\t}\n\n\t\treturn () => {\n\t\t\t$.get(morphInstance)?.destroy();\n\t\t};\n\t});\n\n\t$.user_effect(() => {\n\t\tif ($.get(morphInstance)) {\n\t\t\t$.get(morphInstance).update($$props.text);\n\t\t}\n\t});\n\n\tvar fragment = $.comment();\n\tvar node = $.first_child(fragment);\n\n\t$.element(node, as, false, ($$element, $$anchor) => {\n\t\t$.bind_this($$element, ($$value) => $.set(containerRef, $$value, true), () => $.get(containerRef));\n\t\t$.attribute_effect($$element, () => ({ ...props }));\n\t});\n\n\t$.append($$anchor, fragment);\n\t$.pop();\n}"]}
|
package/dist/vue/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js","sourcesContent":[]}
|
package/dist/vue/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.mjs","sourcesContent":[]}
|