torph 0.0.3 → 0.0.5

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 CHANGED
@@ -17,16 +17,19 @@ yarn add torph
17
17
  ### React
18
18
 
19
19
  ```tsx
20
- import { TextMorph } from 'torph/react';
20
+ import { TextMorph } from "torph/react";
21
21
 
22
22
  function App() {
23
- const [text, setText] = useState('Hello World');
23
+ const [text, setText] = useState("Hello World");
24
24
 
25
25
  return (
26
26
  <TextMorph
27
27
  duration={400}
28
28
  ease="cubic-bezier(0.19, 1, 0.22, 1)"
29
29
  locale="en"
30
+ onAnimationComplete={() => console.log("Animation done!")}
31
+ className="my-text"
32
+ as="h1"
30
33
  >
31
34
  {text}
32
35
  </TextMorph>
@@ -37,7 +40,7 @@ function App() {
37
40
  #### React Hook
38
41
 
39
42
  ```tsx
40
- import { useTextMorph } from 'torph/react';
43
+ import { useTextMorph } from "torph/react";
41
44
 
42
45
  function CustomComponent() {
43
46
  const { ref, update } = useTextMorph({
@@ -46,7 +49,7 @@ function CustomComponent() {
46
49
  });
47
50
 
48
51
  useEffect(() => {
49
- update('Hello World');
52
+ update("Hello World");
50
53
  }, []);
51
54
 
52
55
  return <div ref={ref} />;
@@ -57,10 +60,14 @@ function CustomComponent() {
57
60
 
58
61
  ```vue
59
62
  <script setup>
60
- import { ref } from 'vue';
61
- import { TextMorph } from 'torph/vue';
63
+ import { ref } from "vue";
64
+ import { TextMorph } from "torph/vue";
62
65
 
63
- const text = ref('Hello World');
66
+ const text = ref("Hello World");
67
+
68
+ const handleComplete = () => {
69
+ console.log("Animation done!");
70
+ };
64
71
  </script>
65
72
 
66
73
  <template>
@@ -69,6 +76,9 @@ const text = ref('Hello World');
69
76
  :duration="400"
70
77
  ease="cubic-bezier(0.19, 1, 0.22, 1)"
71
78
  locale="en"
79
+ :onAnimationComplete="handleComplete"
80
+ class="my-text"
81
+ as="h1"
72
82
  />
73
83
  </template>
74
84
  ```
@@ -78,8 +88,12 @@ const text = ref('Hello World');
78
88
  ```svelte
79
89
  <script>
80
90
  import { TextMorph } from 'torph/svelte';
81
-
91
+
82
92
  let text = 'Hello World';
93
+
94
+ const handleComplete = () => {
95
+ console.log('Animation done!');
96
+ };
83
97
  </script>
84
98
 
85
99
  <TextMorph
@@ -87,22 +101,27 @@ const text = ref('Hello World');
87
101
  duration={400}
88
102
  ease="cubic-bezier(0.19, 1, 0.22, 1)"
89
103
  locale="en"
104
+ onAnimationComplete={handleComplete}
105
+ class="my-text"
106
+ as="h1"
90
107
  />
91
108
  ```
92
109
 
93
110
  ### Vanilla JS
94
111
 
95
112
  ```js
96
- import { TextMorph } from 'torph';
113
+ import { TextMorph } from "torph";
97
114
 
98
115
  const morph = new TextMorph({
99
- element: document.getElementById('morph'),
116
+ element: document.getElementById("morph"),
100
117
  duration: 400,
101
- ease: 'cubic-bezier(0.19, 1, 0.22, 1)',
102
- locale: 'en',
118
+ ease: "cubic-bezier(0.19, 1, 0.22, 1)",
119
+ locale: "en",
120
+ onAnimationStart: () => console.log("Starting..."),
121
+ onAnimationComplete: () => console.log("Done!"),
103
122
  });
104
123
 
105
- morph.update('Hello World');
124
+ morph.update("Hello World");
106
125
  ```
107
126
 
108
127
  ## API
@@ -116,6 +135,13 @@ All components accept the following props/options:
116
135
  - `ease?: string` - CSS easing function (default: "cubic-bezier(0.19, 1, 0.22, 1)")
117
136
  - `locale?: Intl.LocalesArgument` - Locale for text segmentation (default: "en")
118
137
  - `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)
140
+ - `onAnimationStart?: () => void` - Callback fired when animation begins
141
+ - `onAnimationComplete?: () => void` - Callback fired when animation completes
142
+ - `className?: string` - CSS class name (React/Vue: `class`)
143
+ - `style?: object | string` - Inline styles
144
+ - `as?: string` - HTML element type (default: "div")
119
145
 
120
146
  ## Found this useful?
121
147
 
@@ -0,0 +1,54 @@
1
+ <template>
2
+ <component
3
+ :is="as"
4
+ ref="containerRef"
5
+ :class="props.class"
6
+ :style="props.style"
7
+ ></component>
8
+ </template>
9
+
10
+ <script setup lang="ts">
11
+ import { ref, onMounted, onUnmounted, watch } from "vue";
12
+ import { TextMorph as Morph } from "../lib/text-morph";
13
+ import type { TextMorphProps } from "./types";
14
+
15
+ const props = withDefaults(defineProps<TextMorphProps>(), {
16
+ locale: "en",
17
+ duration: 400,
18
+ ease: "cubic-bezier(0.19, 1, 0.22, 1)",
19
+ disabled: false,
20
+ respectReducedMotion: true,
21
+ as: "div",
22
+ });
23
+
24
+ const containerRef = ref<HTMLElement | null>(null);
25
+ let morphInstance: Morph | null = null;
26
+
27
+ onMounted(() => {
28
+ if (containerRef.value) {
29
+ morphInstance = new Morph({
30
+ element: containerRef.value,
31
+ locale: props.locale,
32
+ duration: props.duration,
33
+ ease: props.ease,
34
+ debug: props.debug,
35
+ disabled: props.disabled,
36
+ respectReducedMotion: props.respectReducedMotion,
37
+ onAnimationStart: props.onAnimationStart,
38
+ onAnimationComplete: props.onAnimationComplete,
39
+ });
40
+ morphInstance.update(props.text);
41
+ }
42
+ });
43
+
44
+ onUnmounted(() => {
45
+ morphInstance?.destroy();
46
+ });
47
+
48
+ watch(
49
+ () => props.text,
50
+ (newText) => {
51
+ morphInstance?.update(newText);
52
+ },
53
+ );
54
+ </script>
@@ -0,0 +1,26 @@
1
+ "use client";
2
+ var E=class f{element;options={};data;currentMeasures={};prevMeasures={};isInitialRender=!0;prefersReducedMotion=!1;mediaQuery;static styleEl;constructor(t){if(this.options={locale:"en",duration:400,scale:!0,ease:"cubic-bezier(0.19, 1, 0.22, 1)",respectReducedMotion:!0,...t},this.element=t.element,typeof window<"u"&&this.options.respectReducedMotion){this.mediaQuery=window.matchMedia("(prefers-reduced-motion: reduce)"),this.prefersReducedMotion=this.mediaQuery.matches;let s=o=>{this.prefersReducedMotion=o.matches};this.mediaQuery.addEventListener("change",s)}this.isDisabled()||(this.element.setAttribute("torph-root",""),this.element.style.transitionDuration=`${this.options.duration}ms`,this.element.style.transitionTimingFunction=this.options.ease,t.debug&&this.element.setAttribute("torph-debug","")),this.data=this.element.innerHTML,this.isDisabled()||this.addStyles()}destroy(){this.mediaQuery&&this.mediaQuery.removeEventListener("change",this.handleMediaQueryChange),this.element.getAnimations().forEach(t=>t.cancel()),this.element.removeAttribute("torph-root"),this.element.removeAttribute("torph-debug"),this.removeStyles()}handleMediaQueryChange=t=>{this.prefersReducedMotion=t.matches};isDisabled(){return!!(this.options.disabled||this.options.respectReducedMotion&&this.prefersReducedMotion)}update(t){if(t!==this.data){if(this.data=t,this.isDisabled()){typeof t=="string"&&(this.element.textContent=t);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(t,s){let o=s.offsetWidth,i=s.offsetHeight,a=t.includes(" "),h;if(typeof Intl.Segmenter<"u"){let r=new Intl.Segmenter(this.options.locale,{granularity:a?"word":"grapheme"}).segment(t)[Symbol.iterator]();h=this.blocks(r)}else h=this.blocksFallback(t,a);this.prevMeasures=this.measure();let l=Array.from(s.children),d=new Set(h.map(e=>e.id)),g=l.filter(e=>!d.has(e.getAttribute("torph-id"))&&!e.hasAttribute("torph-exiting")),y=new Set(g),m=new Map;for(let e=0;e<l.length;e++){let r=l[e];if(!y.has(r))continue;let p=null;for(let n=e+1;n<l.length;n++){let u=l[n].getAttribute("torph-id");if(d.has(u)&&!y.has(l[n])){p=u;break}}if(!p)for(let n=e-1;n>=0;n--){let u=l[n].getAttribute("torph-id");if(d.has(u)&&!y.has(l[n])){p=u;break}}m.set(r,p)}let x=s.getBoundingClientRect();if(g.forEach(e=>{let r=e.getBoundingClientRect();e.setAttribute("torph-exiting",""),e.style.position="absolute",e.style.pointerEvents="none",e.style.left=`${r.left-x.left}px`,e.style.top=`${r.top-x.top}px`,e.style.width=`${r.width}px`,e.style.height=`${r.height}px`}),l.forEach(e=>{let r=e.getAttribute("torph-id");d.has(r)&&e.remove()}),h.forEach(e=>{let r=document.createElement("span");r.setAttribute("torph-item",""),r.setAttribute("torph-id",e.id),r.textContent=e.string,s.appendChild(r)}),this.currentMeasures=this.measure(),this.updateStyles(h),g.forEach(e=>{if(this.isInitialRender){e.remove();return}let r=m.get(e),p=0,n=0;if(r&&this.prevMeasures[r]&&this.currentMeasures[r]){let M=this.prevMeasures[r],v=this.currentMeasures[r];p=v.x-M.x,n=v.y-M.y}e.getAnimations().forEach(M=>M.cancel()),e.animate({transform:this.options.scale?`translate(${p}px, ${n}px) scale(0.95)`:`translate(${p}px, ${n}px)`,offset:1},{duration:this.options.duration,easing:this.options.ease,fill:"both"});let u=e.animate({opacity:0,offset:1},{duration:this.options.duration*.25,easing:"linear",fill:"both"});u.onfinish=()=>e.remove()}),this.isInitialRender){this.isInitialRender=!1,s.style.width="auto",s.style.height="auto";return}if(o===0||i===0)return;s.style.width="auto",s.style.height="auto",s.offsetWidth;let c=s.offsetWidth,b=s.offsetHeight;s.style.width=`${o}px`,s.style.height=`${i}px`,s.offsetWidth,s.style.width=`${c}px`,s.style.height=`${b}px`,setTimeout(()=>{s.style.width="auto",s.style.height="auto",this.options.onAnimationComplete&&this.options.onAnimationComplete()},this.options.duration)}measure(){let t=Array.from(this.element.children),s={};return t.forEach((o,i)=>{if(o.hasAttribute("torph-exiting"))return;let a=o.getAttribute("torph-id")||`child-${i}`;s[a]={x:o.offsetLeft,y:o.offsetTop}}),s}updateStyles(t){if(this.isInitialRender)return;let s=Array.from(this.element.children),o=new Set(t.map(i=>i.id).filter(i=>this.prevMeasures[i]));s.forEach((i,a)=>{if(i.hasAttribute("torph-exiting"))return;let h=i.getAttribute("torph-id")||`child-${a}`,l=this.prevMeasures[h],d=this.currentMeasures[h],g=d?.x||0,y=d?.y||0,m=l?l.x-g:0,x=l?l.y-y:0,c=!l;if(c){let r=t.findIndex(n=>n.id===h),p=null;for(let n=r-1;n>=0;n--)if(o.has(t[n].id)){p=t[n].id;break}if(!p){for(let n=r+1;n<t.length;n++)if(o.has(t[n].id)){p=t[n].id;break}}if(p){let n=this.prevMeasures[p],u=this.currentMeasures[p];m=n.x-u.x,x=n.y-u.y}}i.getAnimations().forEach(r=>r.cancel()),i.animate({transform:`translate(${m}px, ${x}px) scale(${c?.95:1})`,offset:0},{duration:this.options.duration,easing:this.options.ease,fill:"both"});let b=c?this.options.duration*.25:0,e=c?this.options.duration*.25:0;i.animate({opacity:c?0:1,offset:0},{duration:b,delay:e,easing:"linear",fill:"both"})})}addStyles(){if(f.styleEl)return;let t=document.createElement("style");t.dataset.torph="true",t.innerHTML=`
3
+ [torph-root] {
4
+ display: inline-flex;
5
+ position: relative;
6
+ will-change: width, height;
7
+ transition-property: width, height;
8
+ white-space: nowrap;
9
+ }
10
+
11
+ [torph-item] {
12
+ display: inline-block;
13
+ will-change: opacity, transform;
14
+ transform: none;
15
+ opacity: 1;
16
+ }
17
+
18
+ [torph-root][torph-debug] {
19
+ outline:2px solid magenta;
20
+ [torph-item] {
21
+ outline:2px solid cyan;
22
+ outline-offset: -4px;
23
+ }
24
+ }
25
+ `,document.head.appendChild(t),f.styleEl=t}removeStyles(){f.styleEl&&(f.styleEl.remove(),f.styleEl=void 0)}blocks(t){return Array.from(t).reduce((o,i)=>i.segment===" "?[...o,{id:`space-${i.index}`,string:"\xA0"}]:o.find(h=>h.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,h)=>{h>0&&i.push({id:`space-${h}`,string:"\xA0"}),i.find(d=>d.string===a)?i.push({id:`${a}-${h}`,string:a}):i.push({id:a,string:a})}):o.forEach((a,h)=>{i.find(d=>d.string===a)?i.push({id:`${a}-${h}`,string:a}):i.push({id:a,string:a})}),i}log(...t){this.options.debug&&console.log("[TextMorph]",...t)}};export{E as a};
26
+ //# sourceMappingURL=chunk-5MHVW5FX.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/text-morph/index.ts"],"sourcesContent":["import type { TextMorphOptions } from \"./types\";\n\nexport type { TextMorphOptions } from \"./types\";\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 locale: \"en\",\n duration: 400,\n scale: true,\n ease: \"cubic-bezier(0.19, 1, 0.22, 1)\",\n respectReducedMotion: true,\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\n const listener = (event: MediaQueryListEvent) => {\n this.prefersReducedMotion = event.matches;\n };\n\n this.mediaQuery.addEventListener(\"change\", listener);\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 = this.element.innerHTML;\n\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 const parentRect = element.getBoundingClientRect();\n exiting.forEach((child) => {\n const rect = child.getBoundingClientRect();\n child.setAttribute(\"torph-exiting\", \"\");\n child.style.position = \"absolute\";\n child.style.pointerEvents = \"none\";\n child.style.left = `${rect.left - parentRect.left}px`;\n child.style.top = `${rect.top - parentRect.top}px`;\n child.style.width = `${rect.width}px`;\n child.style.height = `${rect.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 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.getAnimations().forEach((a) => a.cancel());\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"],"mappings":"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","names":["TextMorph","_TextMorph","options","listener","event","anim","value","element","oldWidth","oldHeight","byWord","blocks","iterator","oldChildren","newIds","b","exiting","child","exitingSet","exitingAnchorId","i","anchor","j","siblingId","parentRect","rect","id","block","span","anchorId","dx","dy","anchorPrev","anchorCurr","a","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"]}
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
- import { T as TextMorphOptions } from './types-CsvRfPun.mjs';
1
+ import { T as TextMorphOptions } from './types-CnPojgn6.mjs';
2
2
 
3
- var version = "0.0.3";
3
+ var version = "0.0.5";
4
4
 
5
5
  declare class TextMorph {
6
6
  private element;
@@ -9,9 +9,13 @@ declare class TextMorph {
9
9
  private currentMeasures;
10
10
  private prevMeasures;
11
11
  private isInitialRender;
12
+ private prefersReducedMotion;
13
+ private mediaQuery?;
12
14
  static styleEl: HTMLStyleElement;
13
15
  constructor(options: TextMorphOptions);
14
16
  destroy(): void;
17
+ private handleMediaQueryChange;
18
+ private isDisabled;
15
19
  update(value: HTMLElement | string): void;
16
20
  private createTextGroup;
17
21
  private measure;
@@ -19,7 +23,7 @@ declare class TextMorph {
19
23
  private addStyles;
20
24
  private removeStyles;
21
25
  private blocks;
22
- private getUnscaledBoundingClientRect;
26
+ private blocksFallback;
23
27
  private log;
24
28
  }
25
29
 
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { T as TextMorphOptions } from './types-CsvRfPun.js';
1
+ import { T as TextMorphOptions } from './types-CnPojgn6.js';
2
2
 
3
- var version = "0.0.3";
3
+ var version = "0.0.5";
4
4
 
5
5
  declare class TextMorph {
6
6
  private element;
@@ -9,9 +9,13 @@ declare class TextMorph {
9
9
  private currentMeasures;
10
10
  private prevMeasures;
11
11
  private isInitialRender;
12
+ private prefersReducedMotion;
13
+ private mediaQuery?;
12
14
  static styleEl: HTMLStyleElement;
13
15
  constructor(options: TextMorphOptions);
14
16
  destroy(): void;
17
+ private handleMediaQueryChange;
18
+ private isDisabled;
15
19
  update(value: HTMLElement | string): void;
16
20
  private createTextGroup;
17
21
  private measure;
@@ -19,7 +23,7 @@ declare class TextMorph {
19
23
  private addStyles;
20
24
  private removeStyles;
21
25
  private blocks;
22
- private getUnscaledBoundingClientRect;
26
+ private blocksFallback;
23
27
  private log;
24
28
  }
25
29
 
package/dist/index.js CHANGED
@@ -1,10 +1,11 @@
1
1
  "use client";
2
- "use strict";var M=Object.defineProperty;var L=Object.getOwnPropertyDescriptor;var R=Object.getOwnPropertyNames;var k=Object.prototype.hasOwnProperty;var C=(o,e)=>{for(var t in e)M(o,t,{get:e[t],enumerable:!0})},j=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of R(e))!k.call(o,i)&&i!==t&&M(o,i,{get:()=>e[i],enumerable:!(n=L(e,i))||n.enumerable});return o};var I=o=>j(M({},"__esModule",{value:!0}),o);var O={};C(O,{TextMorph:()=>x,version:()=>w});module.exports=I(O);var w="0.0.3";var x=class o{element;options={};data;currentMeasures={};prevMeasures={};isInitialRender=!0;static styleEl;constructor(e){this.options={locale:"en",duration:400,ease:"cubic-bezier(0.19, 1, 0.22, 1)",...e},this.element=e.element,this.element.setAttribute("torph-root",""),this.element.style.transitionDuration=`${this.options.duration}ms`,this.element.style.transitionTimingFunction=this.options.ease,e.debug&&this.element.setAttribute("torph-debug",""),this.data=this.element.innerHTML,this.addStyles()}destroy(){this.element.getAnimations().forEach(e=>e.cancel()),this.element.removeAttribute("torph-root"),this.element.removeAttribute("torph-debug"),this.removeStyles()}update(e){if(e!==this.data){if(this.data=e,this.data instanceof HTMLElement)throw new Error("HTMLElement not yet supported");this.createTextGroup(this.data,this.element)}}createTextGroup(e,t){let n=t.offsetWidth,i=t.offsetHeight,r=e.includes(" "),g=new Intl.Segmenter(this.options.locale,{granularity:r?"word":"grapheme"}).segment(e)[Symbol.iterator](),m=this.blocks(g);this.prevMeasures=this.measure();let h=Array.from(t.children),d=new Set(m.map(s=>s.id)),p=h.filter(s=>!d.has(s.getAttribute("torph-id"))&&!s.hasAttribute("torph-exiting")),u=this.getUnscaledBoundingClientRect(t);if(p.forEach(s=>{let a=this.getUnscaledBoundingClientRect(s);s.setAttribute("torph-exiting",""),s.style.position="absolute",s.style.pointerEvents="none",s.style.left=`${a.left-u.left}px`,s.style.top=`${a.top-u.top}px`,s.style.width=`${a.width}px`,s.style.height=`${a.height}px`}),h.forEach(s=>{let a=s.getAttribute("torph-id");d.has(a)&&s.remove()}),m.forEach(s=>{let a=document.createElement("span");a.setAttribute("torph-item",""),a.setAttribute("torph-id",s.id),a.textContent=s.string,t.appendChild(a)}),this.currentMeasures=this.measure(),this.updateStyles(),p.forEach(s=>{if(this.isInitialRender){s.remove();return}let a=s.getAttribute("torph-id"),v=this.prevMeasures[a],E=Array.from(t.children).find(b=>{let S=b.getBoundingClientRect(),$=s.getBoundingClientRect();return Math.abs(S.left-$.left)<40}),y=E?this.currentMeasures[E.getAttribute("torph-id")]:v,A=(y?y.x-(v?.x||0):0)*.5,T=(y?y.y-(v?.y||0):0)*.5;s.getAnimations().forEach(b=>b.cancel());let H=s.animate({transform:`translate(${A}px, ${T}px) scale(0.95)`,opacity:0,offset:1},{duration:this.options.duration,easing:this.options.ease,fill:"both"});H.onfinish=()=>s.remove()}),this.isInitialRender){this.isInitialRender=!1,t.style.width="auto",t.style.height="auto";return}if(n===0||i===0)return;t.style.width="auto",t.style.height="auto",t.offsetWidth;let c=t.offsetWidth,f=t.offsetHeight;t.style.width=`${n}px`,t.style.height=`${i}px`,t.offsetWidth,t.style.width=`${c}px`,t.style.height=`${f}px`,setTimeout(()=>{t.style.width="auto",t.style.height="auto"},this.options.duration)}measure(){let e=Array.from(this.element.children),t={};return e.forEach((n,i)=>{if(n.hasAttribute("torph-exiting"))return;let r=n.getAttribute("torph-id")||`child-${i}`;t[r]={x:n.offsetLeft,y:n.offsetTop}}),t}updateStyles(){if(this.isInitialRender)return;Array.from(this.element.children).forEach((t,n)=>{if(t.hasAttribute("torph-exiting"))return;let i=t.getAttribute("torph-id")||`child-${n}`,r=this.prevMeasures[i],l=this.currentMeasures[i],g=l?.x||0,m=l?.y||0,h=r?r?.x-g:0,d=r?r?.y-m:0,p=!r;t.getAnimations().forEach(u=>u.cancel()),t.animate({transform:`translate(${h}px, ${d}px) scale(${p?.95:1})`,opacity:p?0:1,offset:0},{duration:this.options.duration,easing:this.options.ease,delay:p?this.options.duration*.2:0,fill:"both"})})}addStyles(){if(o.styleEl)return;let e=document.createElement("style");e.dataset.torph="true",e.innerHTML=`
2
+ "use strict";var E=Object.defineProperty;var $=Object.getOwnPropertyDescriptor;var T=Object.getOwnPropertyNames;var S=Object.prototype.hasOwnProperty;var I=(d,t)=>{for(var i in t)E(d,i,{get:t[i],enumerable:!0})},k=(d,t,i,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let e of T(t))!S.call(d,e)&&e!==i&&E(d,e,{get:()=>t[e],enumerable:!(o=$(t,e))||o.enumerable});return d};var L=d=>k(E({},"__esModule",{value:!0}),d);var R={};I(R,{TextMorph:()=>b,version:()=>w});module.exports=L(R);var w="0.0.5";var b=class d{element;options={};data;currentMeasures={};prevMeasures={};isInitialRender=!0;prefersReducedMotion=!1;mediaQuery;static styleEl;constructor(t){if(this.options={locale:"en",duration:400,scale:!0,ease:"cubic-bezier(0.19, 1, 0.22, 1)",respectReducedMotion:!0,...t},this.element=t.element,typeof window<"u"&&this.options.respectReducedMotion){this.mediaQuery=window.matchMedia("(prefers-reduced-motion: reduce)"),this.prefersReducedMotion=this.mediaQuery.matches;let i=o=>{this.prefersReducedMotion=o.matches};this.mediaQuery.addEventListener("change",i)}this.isDisabled()||(this.element.setAttribute("torph-root",""),this.element.style.transitionDuration=`${this.options.duration}ms`,this.element.style.transitionTimingFunction=this.options.ease,t.debug&&this.element.setAttribute("torph-debug","")),this.data=this.element.innerHTML,this.isDisabled()||this.addStyles()}destroy(){this.mediaQuery&&this.mediaQuery.removeEventListener("change",this.handleMediaQueryChange),this.element.getAnimations().forEach(t=>t.cancel()),this.element.removeAttribute("torph-root"),this.element.removeAttribute("torph-debug"),this.removeStyles()}handleMediaQueryChange=t=>{this.prefersReducedMotion=t.matches};isDisabled(){return!!(this.options.disabled||this.options.respectReducedMotion&&this.prefersReducedMotion)}update(t){if(t!==this.data){if(this.data=t,this.isDisabled()){typeof t=="string"&&(this.element.textContent=t);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(t,i){let o=i.offsetWidth,e=i.offsetHeight,a=t.includes(" "),p;if(typeof Intl.Segmenter<"u"){let r=new Intl.Segmenter(this.options.locale,{granularity:a?"word":"grapheme"}).segment(t)[Symbol.iterator]();p=this.blocks(r)}else p=this.blocksFallback(t,a);this.prevMeasures=this.measure();let l=Array.from(i.children),u=new Set(p.map(s=>s.id)),g=l.filter(s=>!u.has(s.getAttribute("torph-id"))&&!s.hasAttribute("torph-exiting")),m=new Set(g),y=new Map;for(let s=0;s<l.length;s++){let r=l[s];if(!m.has(r))continue;let h=null;for(let n=s+1;n<l.length;n++){let c=l[n].getAttribute("torph-id");if(u.has(c)&&!m.has(l[n])){h=c;break}}if(!h)for(let n=s-1;n>=0;n--){let c=l[n].getAttribute("torph-id");if(u.has(c)&&!m.has(l[n])){h=c;break}}y.set(r,h)}let x=i.getBoundingClientRect();if(g.forEach(s=>{let r=s.getBoundingClientRect();s.setAttribute("torph-exiting",""),s.style.position="absolute",s.style.pointerEvents="none",s.style.left=`${r.left-x.left}px`,s.style.top=`${r.top-x.top}px`,s.style.width=`${r.width}px`,s.style.height=`${r.height}px`}),l.forEach(s=>{let r=s.getAttribute("torph-id");u.has(r)&&s.remove()}),p.forEach(s=>{let r=document.createElement("span");r.setAttribute("torph-item",""),r.setAttribute("torph-id",s.id),r.textContent=s.string,i.appendChild(r)}),this.currentMeasures=this.measure(),this.updateStyles(p),g.forEach(s=>{if(this.isInitialRender){s.remove();return}let r=y.get(s),h=0,n=0;if(r&&this.prevMeasures[r]&&this.currentMeasures[r]){let v=this.prevMeasures[r],A=this.currentMeasures[r];h=A.x-v.x,n=A.y-v.y}s.getAnimations().forEach(v=>v.cancel()),s.animate({transform:this.options.scale?`translate(${h}px, ${n}px) scale(0.95)`:`translate(${h}px, ${n}px)`,offset:1},{duration:this.options.duration,easing:this.options.ease,fill:"both"});let c=s.animate({opacity:0,offset:1},{duration:this.options.duration*.25,easing:"linear",fill:"both"});c.onfinish=()=>s.remove()}),this.isInitialRender){this.isInitialRender=!1,i.style.width="auto",i.style.height="auto";return}if(o===0||e===0)return;i.style.width="auto",i.style.height="auto",i.offsetWidth;let f=i.offsetWidth,M=i.offsetHeight;i.style.width=`${o}px`,i.style.height=`${e}px`,i.offsetWidth,i.style.width=`${f}px`,i.style.height=`${M}px`,setTimeout(()=>{i.style.width="auto",i.style.height="auto",this.options.onAnimationComplete&&this.options.onAnimationComplete()},this.options.duration)}measure(){let t=Array.from(this.element.children),i={};return t.forEach((o,e)=>{if(o.hasAttribute("torph-exiting"))return;let a=o.getAttribute("torph-id")||`child-${e}`;i[a]={x:o.offsetLeft,y:o.offsetTop}}),i}updateStyles(t){if(this.isInitialRender)return;let i=Array.from(this.element.children),o=new Set(t.map(e=>e.id).filter(e=>this.prevMeasures[e]));i.forEach((e,a)=>{if(e.hasAttribute("torph-exiting"))return;let p=e.getAttribute("torph-id")||`child-${a}`,l=this.prevMeasures[p],u=this.currentMeasures[p],g=u?.x||0,m=u?.y||0,y=l?l.x-g:0,x=l?l.y-m:0,f=!l;if(f){let r=t.findIndex(n=>n.id===p),h=null;for(let n=r-1;n>=0;n--)if(o.has(t[n].id)){h=t[n].id;break}if(!h){for(let n=r+1;n<t.length;n++)if(o.has(t[n].id)){h=t[n].id;break}}if(h){let n=this.prevMeasures[h],c=this.currentMeasures[h];y=n.x-c.x,x=n.y-c.y}}e.getAnimations().forEach(r=>r.cancel()),e.animate({transform:`translate(${y}px, ${x}px) scale(${f?.95:1})`,offset:0},{duration:this.options.duration,easing:this.options.ease,fill:"both"});let M=f?this.options.duration*.25:0,s=f?this.options.duration*.25:0;e.animate({opacity:f?0:1,offset:0},{duration:M,delay:s,easing:"linear",fill:"both"})})}addStyles(){if(d.styleEl)return;let t=document.createElement("style");t.dataset.torph="true",t.innerHTML=`
3
3
  [torph-root] {
4
- display: inline-flex; /* TODO: remove for multi-line support */
4
+ display: inline-flex;
5
5
  position: relative;
6
6
  will-change: width, height;
7
7
  transition-property: width, height;
8
+ white-space: nowrap;
8
9
  }
9
10
 
10
11
  [torph-item] {
@@ -13,7 +14,7 @@
13
14
  transform: none;
14
15
  opacity: 1;
15
16
  }
16
-
17
+
17
18
  [torph-root][torph-debug] {
18
19
  outline:2px solid magenta;
19
20
  [torph-item] {
@@ -21,5 +22,5 @@
21
22
  outline-offset: -4px;
22
23
  }
23
24
  }
24
- `,document.head.appendChild(e),o.styleEl=e}removeStyles(){o.styleEl&&(o.styleEl.remove(),o.styleEl=void 0)}blocks(e){return Array.from(e).reduce((n,i)=>i.segment===" "?[...n,{id:`space-${i.index}`,string:"\xA0"}]:n.find(l=>l.string===i.segment)?[...n,{id:`${i.segment}-${i.index}`,string:i.segment}]:[...n,{id:i.segment,string:i.segment}],[])}getUnscaledBoundingClientRect(e){let t=e.getBoundingClientRect(),i=window.getComputedStyle(e).transform,r=1,l=1,g=/matrix\(([^)]+)\)/,m=i.match(g);if(m){let c=m[1]?.split(",").map(Number);c&&c?.length>=4&&(r=c[0],l=c[3])}else{let c=i.match(/scaleX\(([^)]+)\)/),f=i.match(/scaleY\(([^)]+)\)/);c&&(r=parseFloat(c[1])),f&&(l=parseFloat(f[1]))}let h=t.width/r,d=t.height/l,p=t.x+(t.width-h)/2,u=t.y+(t.height-d)/2;return{x:p,y:u,width:h,height:d,top:u,right:p+h,bottom:u+d,left:p}}log(...e){this.options.debug&&console.log("[TextMorph]",...e)}};0&&(module.exports={TextMorph,version});
25
+ `,document.head.appendChild(t),d.styleEl=t}removeStyles(){d.styleEl&&(d.styleEl.remove(),d.styleEl=void 0)}blocks(t){return Array.from(t).reduce((o,e)=>e.segment===" "?[...o,{id:`space-${e.index}`,string:"\xA0"}]:o.find(p=>p.string===e.segment)?[...o,{id:`${e.segment}-${e.index}`,string:e.segment}]:[...o,{id:e.segment,string:e.segment}],[])}blocksFallback(t,i){let o=i?t.split(" "):t.split(""),e=[];return i?o.forEach((a,p)=>{p>0&&e.push({id:`space-${p}`,string:"\xA0"}),e.find(u=>u.string===a)?e.push({id:`${a}-${p}`,string:a}):e.push({id:a,string:a})}):o.forEach((a,p)=>{e.find(u=>u.string===a)?e.push({id:`${a}-${p}`,string:a}):e.push({id:a,string:a})}),e}log(...t){this.options.debug&&console.log("[TextMorph]",...t)}};0&&(module.exports={TextMorph,version});
25
26
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../package.json","../src/lib/text-morph/index.ts"],"sourcesContent":["export { version } from \"./../package.json\";\n\nexport { TextMorph } from \"./lib/text-morph\";\nexport type { TextMorphOptions } from \"./lib/text-morph/types\";\n","{\n \"name\": \"torph\",\n \"version\": \"0.0.3\",\n \"description\": \"Dependency-free animated text component.\",\n \"author\": \"Lochie Axon\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/lochie/torph.git\",\n \"directory\": \"packages/torph\"\n },\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.js\"\n },\n \"./react\": {\n \"types\": \"./dist/react/index.d.ts\",\n \"import\": \"./dist/react/index.mjs\",\n \"require\": \"./dist/react/index.js\"\n },\n \"./vue\": {\n \"types\": \"./dist/vue/index.d.ts\",\n \"import\": \"./dist/vue/index.mjs\",\n \"require\": \"./dist/vue/index.js\"\n },\n \"./svelte\": {\n \"types\": \"./dist/svelte/index.d.ts\",\n \"import\": \"./dist/svelte/index.mjs\",\n \"require\": \"./dist/svelte/index.js\"\n }\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"lint\": \"eslint -c .eslintrc.cjs ./src/**/*.{ts,tsx}\",\n \"lint:fix\": \"eslint --fix -c .eslintrc.cjs ./src/**/*.{ts,tsx}\",\n \"pre-commit\": \"lint-staged\"\n },\n \"keywords\": [\n \"react\",\n \"vue\",\n \"svelte\",\n \"text\",\n \"animation\",\n \"morph\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/lochie/torph/issues\"\n },\n \"files\": [\n \"dist/*\"\n ],\n \"peerDependencies\": {\n \"react\": \">=18\",\n \"react-dom\": \">=18\",\n \"vue\": \">=3\",\n \"svelte\": \">=4\"\n },\n \"peerDependenciesMeta\": {\n \"react\": {\n \"optional\": true\n },\n \"react-dom\": {\n \"optional\": true\n },\n \"vue\": {\n \"optional\": true\n },\n \"svelte\": {\n \"optional\": true\n }\n },\n \"devDependencies\": {\n \"@types/react\": \"^18.2.15\",\n \"@typescript-eslint/eslint-plugin\": \"^6.8.0\",\n \"@typescript-eslint/parser\": \"^6.8.0\",\n \"eslint\": \"^9.36.0\",\n \"eslint-config-airbnb\": \"^19.0.4\",\n \"eslint-config-airbnb-typescript\": \"^17.1.0\",\n \"eslint-config-prettier\": \"^9.0.0\",\n \"eslint-plugin-import\": \"^2.28.1\",\n \"eslint-plugin-jsx-a11y\": \"^6.7.1\",\n \"eslint-plugin-prettier\": \"^5.0.1\",\n \"eslint-plugin-react\": \"^7.33.2\",\n \"eslint-plugin-react-hooks\": \"^4.6.0\",\n \"prettier\": \"^3.0.3\",\n \"react\": \"^18.2.0\",\n \"react-dom\": \"^18.2.0\",\n \"svelte\": \"^4.0.0\",\n \"tsup\": \"^8.5.0\",\n \"typescript\": \"^5.9.3\",\n \"vue\": \"^3.3.0\"\n }\n}\n","import type { TextMorphOptions } from \"./types\";\n\nexport { TextMorphOptions } from \"./types\";\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\n static styleEl: HTMLStyleElement;\n\n constructor(options: TextMorphOptions) {\n this.options = {\n locale: \"en\",\n duration: 400,\n ease: \"cubic-bezier(0.19, 1, 0.22, 1)\",\n ...options,\n };\n\n this.element = options.element;\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 this.data = this.element.innerHTML;\n\n this.addStyles();\n }\n\n destroy() {\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 update(value: HTMLElement | string) {\n if (value === this.data) return;\n this.data = value;\n\n if (this.data instanceof HTMLElement) {\n // TODO: handle HTMLElement case\n throw new Error(\"HTMLElement not yet supported\");\n } else {\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 const segmenter = new Intl.Segmenter(this.options.locale, {\n granularity: byWord ? \"word\" : \"grapheme\",\n });\n const iterator = segmenter.segment(value)[Symbol.iterator]();\n const blocks = this.blocks(iterator);\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 const parentRect = this.getUnscaledBoundingClientRect(element);\n exiting.forEach((child) => {\n const rect = this.getUnscaledBoundingClientRect(child);\n child.setAttribute(\"torph-exiting\", \"\");\n child.style.position = \"absolute\";\n child.style.pointerEvents = \"none\";\n child.style.left = `${rect.left - parentRect.left}px`;\n child.style.top = `${rect.top - parentRect.top}px`;\n child.style.width = `${rect.width}px`;\n child.style.height = `${rect.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 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();\n\n exiting.forEach((child) => {\n if (this.isInitialRender) {\n child.remove();\n return;\n }\n\n const id = child.getAttribute(\"torph-id\")!;\n\n const prev = this.prevMeasures[id];\n\n const siblings = Array.from(element.children) as HTMLElement[];\n const nearest = siblings.find((s) => {\n const sRect = s.getBoundingClientRect();\n const cRect = child.getBoundingClientRect();\n return Math.abs(sRect.left - cRect.left) < 40;\n });\n\n const nextPos = nearest\n ? this.currentMeasures[nearest.getAttribute(\"torph-id\")!]\n : prev;\n\n const dx = (nextPos ? nextPos.x - (prev?.x || 0) : 0) * 0.5;\n const dy = (nextPos ? nextPos.y - (prev?.y || 0) : 0) * 0.5;\n\n child.getAnimations().forEach((a) => a.cancel());\n const animation: Animation = child.animate(\n {\n transform: `translate(${dx}px, ${dy}px) scale(0.95)`,\n opacity: 0,\n offset: 1,\n },\n {\n duration: this.options.duration,\n easing: this.options.ease,\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 }, 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() {\n if (this.isInitialRender) return;\n\n const children = Array.from(this.element.children) as HTMLElement[];\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 const deltaX = prev ? prev?.x - cx : 0;\n const deltaY = prev ? prev?.y - cy : 0;\n const isNew = !prev;\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 opacity: isNew ? 0 : 1,\n offset: 0,\n },\n {\n duration: this.options.duration,\n easing: this.options.ease,\n delay: isNew ? this.options.duration! * 0.2 : 0,\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; /* TODO: remove for multi-line support */\n position: relative;\n will-change: width, height;\n transition-property: width, height;\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 getUnscaledBoundingClientRect(element: HTMLElement) {\n const scaledRect = element.getBoundingClientRect();\n const computedStyle = window.getComputedStyle(element);\n const transform = computedStyle.transform;\n\n let scaleX = 1;\n let scaleY = 1;\n\n const matrixRegex = /matrix\\(([^)]+)\\)/;\n const match = transform.match(matrixRegex);\n\n if (match) {\n const values = match[1]?.split(\",\").map(Number);\n if (values && values?.length >= 4) {\n scaleX = values[0]!;\n scaleY = values[3]!;\n }\n } else {\n const scaleXMatch = transform.match(/scaleX\\(([^)]+)\\)/);\n const scaleYMatch = transform.match(/scaleY\\(([^)]+)\\)/);\n if (scaleXMatch) scaleX = parseFloat(scaleXMatch[1]!);\n if (scaleYMatch) scaleY = parseFloat(scaleYMatch[1]!);\n }\n\n const unscaledWidth = scaledRect.width / scaleX;\n const unscaledHeight = scaledRect.height / scaleY;\n\n const unscaledX = scaledRect.x + (scaledRect.width - unscaledWidth) / 2;\n const unscaledY = scaledRect.y + (scaledRect.height - unscaledHeight) / 2;\n\n return {\n x: unscaledX,\n y: unscaledY,\n width: unscaledWidth,\n height: unscaledHeight,\n top: unscaledY,\n right: unscaledX + unscaledWidth,\n bottom: unscaledY + unscaledHeight,\n left: unscaledX,\n };\n }\n\n private log(...args: any[]) {\n if (this.options.debug) console.log(\"[TextMorph]\", ...args);\n }\n}\n"],"mappings":"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","names":["src_exports","__export","TextMorph","version","__toCommonJS","version","TextMorph","_TextMorph","options","anim","value","element","oldWidth","oldHeight","byWord","iterator","blocks","oldChildren","newIds","b","exiting","child","parentRect","rect","id","block","span","prev","nearest","s","sRect","cRect","nextPos","dx","dy","a","animation","newWidth","newHeight","children","measures","index","key","current","cx","cy","deltaX","deltaY","isNew","style","acc","string","x","scaledRect","transform","scaleX","scaleY","matrixRegex","match","values","scaleXMatch","scaleYMatch","unscaledWidth","unscaledHeight","unscaledX","unscaledY","args"]}
1
+ {"version":3,"sources":["../src/index.ts","../package.json","../src/lib/text-morph/index.ts"],"sourcesContent":["export { version } from \"./../package.json\";\n\nexport { TextMorph } from \"./lib/text-morph\";\nexport type { TextMorphOptions } from \"./lib/text-morph/types\";\n","{\n \"name\": \"torph\",\n \"version\": \"0.0.5\",\n \"description\": \"Dependency-free animated text component.\",\n \"author\": \"Lochie Axon\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/lochie/torph.git\",\n \"directory\": \"packages/torph\"\n },\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.js\"\n },\n \"./react\": {\n \"types\": \"./dist/react/index.d.ts\",\n \"import\": \"./dist/react/index.mjs\",\n \"require\": \"./dist/react/index.js\"\n },\n \"./vue\": {\n \"types\": \"./dist/vue/index.d.ts\",\n \"import\": \"./dist/vue/index.mjs\",\n \"require\": \"./dist/vue/index.js\"\n },\n \"./svelte\": {\n \"types\": \"./dist/svelte/index.d.ts\",\n \"import\": \"./dist/svelte/index.mjs\",\n \"require\": \"./dist/svelte/index.js\"\n }\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"lint\": \"eslint -c .eslintrc.cjs ./src/**/*.{ts,tsx}\",\n \"lint:fix\": \"eslint --fix -c .eslintrc.cjs ./src/**/*.{ts,tsx}\",\n \"pre-commit\": \"lint-staged\"\n },\n \"keywords\": [\n \"react\",\n \"vue\",\n \"svelte\",\n \"text\",\n \"animation\",\n \"morph\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/lochie/torph/issues\"\n },\n \"files\": [\n \"dist/*\"\n ],\n \"peerDependencies\": {\n \"react\": \">=18\",\n \"react-dom\": \">=18\",\n \"vue\": \">=3\",\n \"svelte\": \">=4\"\n },\n \"peerDependenciesMeta\": {\n \"react\": {\n \"optional\": true\n },\n \"react-dom\": {\n \"optional\": true\n },\n \"vue\": {\n \"optional\": true\n },\n \"svelte\": {\n \"optional\": true\n }\n },\n \"devDependencies\": {\n \"@types/react\": \"^18.2.15\",\n \"@typescript-eslint/eslint-plugin\": \"^6.8.0\",\n \"@typescript-eslint/parser\": \"^6.8.0\",\n \"eslint\": \"^9.36.0\",\n \"eslint-config-airbnb\": \"^19.0.4\",\n \"eslint-config-airbnb-typescript\": \"^17.1.0\",\n \"eslint-config-prettier\": \"^9.0.0\",\n \"eslint-plugin-import\": \"^2.28.1\",\n \"eslint-plugin-jsx-a11y\": \"^6.7.1\",\n \"eslint-plugin-prettier\": \"^5.0.1\",\n \"eslint-plugin-react\": \"^7.33.2\",\n \"eslint-plugin-react-hooks\": \"^4.6.0\",\n \"prettier\": \"^3.0.3\",\n \"react\": \"^18.2.0\",\n \"react-dom\": \"^18.2.0\",\n \"svelte\": \"^4.0.0\",\n \"tsup\": \"^8.5.0\",\n \"typescript\": \"^5.9.3\",\n \"vue\": \"^3.3.0\"\n }\n}\n","import type { TextMorphOptions } from \"./types\";\n\nexport type { TextMorphOptions } from \"./types\";\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 locale: \"en\",\n duration: 400,\n scale: true,\n ease: \"cubic-bezier(0.19, 1, 0.22, 1)\",\n respectReducedMotion: true,\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\n const listener = (event: MediaQueryListEvent) => {\n this.prefersReducedMotion = event.matches;\n };\n\n this.mediaQuery.addEventListener(\"change\", listener);\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 = this.element.innerHTML;\n\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 const parentRect = element.getBoundingClientRect();\n exiting.forEach((child) => {\n const rect = child.getBoundingClientRect();\n child.setAttribute(\"torph-exiting\", \"\");\n child.style.position = \"absolute\";\n child.style.pointerEvents = \"none\";\n child.style.left = `${rect.left - parentRect.left}px`;\n child.style.top = `${rect.top - parentRect.top}px`;\n child.style.width = `${rect.width}px`;\n child.style.height = `${rect.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 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.getAnimations().forEach((a) => a.cancel());\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"],"mappings":"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","names":["src_exports","__export","TextMorph","version","__toCommonJS","version","TextMorph","_TextMorph","options","listener","event","anim","value","element","oldWidth","oldHeight","byWord","blocks","iterator","oldChildren","newIds","b","exiting","child","exitingSet","exitingAnchorId","i","anchor","j","siblingId","parentRect","rect","id","block","span","anchorId","dx","dy","anchorPrev","anchorCurr","a","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"]}
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- import{a as e}from"./chunk-43OPPES3.mjs";var i="0.0.3";export{e as TextMorph,i as version};
2
+ import{a as e}from"./chunk-5MHVW5FX.mjs";var i="0.0.5";export{e as TextMorph,i as version};
3
3
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../package.json"],"sourcesContent":["{\n \"name\": \"torph\",\n \"version\": \"0.0.3\",\n \"description\": \"Dependency-free animated text component.\",\n \"author\": \"Lochie Axon\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/lochie/torph.git\",\n \"directory\": \"packages/torph\"\n },\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.js\"\n },\n \"./react\": {\n \"types\": \"./dist/react/index.d.ts\",\n \"import\": \"./dist/react/index.mjs\",\n \"require\": \"./dist/react/index.js\"\n },\n \"./vue\": {\n \"types\": \"./dist/vue/index.d.ts\",\n \"import\": \"./dist/vue/index.mjs\",\n \"require\": \"./dist/vue/index.js\"\n },\n \"./svelte\": {\n \"types\": \"./dist/svelte/index.d.ts\",\n \"import\": \"./dist/svelte/index.mjs\",\n \"require\": \"./dist/svelte/index.js\"\n }\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"lint\": \"eslint -c .eslintrc.cjs ./src/**/*.{ts,tsx}\",\n \"lint:fix\": \"eslint --fix -c .eslintrc.cjs ./src/**/*.{ts,tsx}\",\n \"pre-commit\": \"lint-staged\"\n },\n \"keywords\": [\n \"react\",\n \"vue\",\n \"svelte\",\n \"text\",\n \"animation\",\n \"morph\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/lochie/torph/issues\"\n },\n \"files\": [\n \"dist/*\"\n ],\n \"peerDependencies\": {\n \"react\": \">=18\",\n \"react-dom\": \">=18\",\n \"vue\": \">=3\",\n \"svelte\": \">=4\"\n },\n \"peerDependenciesMeta\": {\n \"react\": {\n \"optional\": true\n },\n \"react-dom\": {\n \"optional\": true\n },\n \"vue\": {\n \"optional\": true\n },\n \"svelte\": {\n \"optional\": true\n }\n },\n \"devDependencies\": {\n \"@types/react\": \"^18.2.15\",\n \"@typescript-eslint/eslint-plugin\": \"^6.8.0\",\n \"@typescript-eslint/parser\": \"^6.8.0\",\n \"eslint\": \"^9.36.0\",\n \"eslint-config-airbnb\": \"^19.0.4\",\n \"eslint-config-airbnb-typescript\": \"^17.1.0\",\n \"eslint-config-prettier\": \"^9.0.0\",\n \"eslint-plugin-import\": \"^2.28.1\",\n \"eslint-plugin-jsx-a11y\": \"^6.7.1\",\n \"eslint-plugin-prettier\": \"^5.0.1\",\n \"eslint-plugin-react\": \"^7.33.2\",\n \"eslint-plugin-react-hooks\": \"^4.6.0\",\n \"prettier\": \"^3.0.3\",\n \"react\": \"^18.2.0\",\n \"react-dom\": \"^18.2.0\",\n \"svelte\": \"^4.0.0\",\n \"tsup\": \"^8.5.0\",\n \"typescript\": \"^5.9.3\",\n \"vue\": \"^3.3.0\"\n }\n}\n"],"mappings":";yCAEE,IAAAA,EAAW","names":["version"]}
1
+ {"version":3,"sources":["../package.json"],"sourcesContent":["{\n \"name\": \"torph\",\n \"version\": \"0.0.5\",\n \"description\": \"Dependency-free animated text component.\",\n \"author\": \"Lochie Axon\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/lochie/torph.git\",\n \"directory\": \"packages/torph\"\n },\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.js\"\n },\n \"./react\": {\n \"types\": \"./dist/react/index.d.ts\",\n \"import\": \"./dist/react/index.mjs\",\n \"require\": \"./dist/react/index.js\"\n },\n \"./vue\": {\n \"types\": \"./dist/vue/index.d.ts\",\n \"import\": \"./dist/vue/index.mjs\",\n \"require\": \"./dist/vue/index.js\"\n },\n \"./svelte\": {\n \"types\": \"./dist/svelte/index.d.ts\",\n \"import\": \"./dist/svelte/index.mjs\",\n \"require\": \"./dist/svelte/index.js\"\n }\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"lint\": \"eslint -c .eslintrc.cjs ./src/**/*.{ts,tsx}\",\n \"lint:fix\": \"eslint --fix -c .eslintrc.cjs ./src/**/*.{ts,tsx}\",\n \"pre-commit\": \"lint-staged\"\n },\n \"keywords\": [\n \"react\",\n \"vue\",\n \"svelte\",\n \"text\",\n \"animation\",\n \"morph\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/lochie/torph/issues\"\n },\n \"files\": [\n \"dist/*\"\n ],\n \"peerDependencies\": {\n \"react\": \">=18\",\n \"react-dom\": \">=18\",\n \"vue\": \">=3\",\n \"svelte\": \">=4\"\n },\n \"peerDependenciesMeta\": {\n \"react\": {\n \"optional\": true\n },\n \"react-dom\": {\n \"optional\": true\n },\n \"vue\": {\n \"optional\": true\n },\n \"svelte\": {\n \"optional\": true\n }\n },\n \"devDependencies\": {\n \"@types/react\": \"^18.2.15\",\n \"@typescript-eslint/eslint-plugin\": \"^6.8.0\",\n \"@typescript-eslint/parser\": \"^6.8.0\",\n \"eslint\": \"^9.36.0\",\n \"eslint-config-airbnb\": \"^19.0.4\",\n \"eslint-config-airbnb-typescript\": \"^17.1.0\",\n \"eslint-config-prettier\": \"^9.0.0\",\n \"eslint-plugin-import\": \"^2.28.1\",\n \"eslint-plugin-jsx-a11y\": \"^6.7.1\",\n \"eslint-plugin-prettier\": \"^5.0.1\",\n \"eslint-plugin-react\": \"^7.33.2\",\n \"eslint-plugin-react-hooks\": \"^4.6.0\",\n \"prettier\": \"^3.0.3\",\n \"react\": \"^18.2.0\",\n \"react-dom\": \"^18.2.0\",\n \"svelte\": \"^4.0.0\",\n \"tsup\": \"^8.5.0\",\n \"typescript\": \"^5.9.3\",\n \"vue\": \"^3.3.0\"\n }\n}\n"],"mappings":";yCAEE,IAAAA,EAAW","names":["version"]}
@@ -1,10 +1,13 @@
1
1
  import React from 'react';
2
- import { T as TextMorphOptions } from '../types-CsvRfPun.mjs';
2
+ import { T as TextMorphOptions } from '../types-CnPojgn6.mjs';
3
3
 
4
4
  type TextMorphProps = Omit<TextMorphOptions, "element"> & {
5
5
  children: string;
6
+ className?: string;
7
+ style?: React.CSSProperties;
8
+ as?: keyof JSX.IntrinsicElements;
6
9
  };
7
- declare const TextMorph: ({ children, ...props }: TextMorphProps) => React.JSX.Element;
10
+ declare const TextMorph: ({ children, className, style, as, ...props }: TextMorphProps) => React.JSX.Element;
8
11
  declare function useTextMorph(props: Omit<TextMorphOptions, "element">): {
9
12
  ref: React.MutableRefObject<HTMLDivElement | null>;
10
13
  update: (text: string) => void;
@@ -1,10 +1,13 @@
1
1
  import React from 'react';
2
- import { T as TextMorphOptions } from '../types-CsvRfPun.js';
2
+ import { T as TextMorphOptions } from '../types-CnPojgn6.js';
3
3
 
4
4
  type TextMorphProps = Omit<TextMorphOptions, "element"> & {
5
5
  children: string;
6
+ className?: string;
7
+ style?: React.CSSProperties;
8
+ as?: keyof JSX.IntrinsicElements;
6
9
  };
7
- declare const TextMorph: ({ children, ...props }: TextMorphProps) => React.JSX.Element;
10
+ declare const TextMorph: ({ children, className, style, as, ...props }: TextMorphProps) => React.JSX.Element;
8
11
  declare function useTextMorph(props: Omit<TextMorphOptions, "element">): {
9
12
  ref: React.MutableRefObject<HTMLDivElement | null>;
10
13
  update: (text: string) => void;
@@ -1,10 +1,11 @@
1
1
  "use client";
2
- "use strict";var C=Object.create;var M=Object.defineProperty;var I=Object.getOwnPropertyDescriptor;var k=Object.getOwnPropertyNames;var B=Object.getPrototypeOf,W=Object.prototype.hasOwnProperty;var X=(r,e)=>{for(var t in e)M(r,t,{get:e[t],enumerable:!0})},A=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of k(e))!W.call(r,s)&&s!==t&&M(r,s,{get:()=>e[s],enumerable:!(n=I(e,s))||n.enumerable});return r};var Y=(r,e,t)=>(t=r!=null?C(B(r)):{},A(e||!r||!r.__esModule?M(t,"default",{value:r,enumerable:!0}):t,r)),D=r=>A(M({},"__esModule",{value:!0}),r);var P={};X(P,{TextMorph:()=>H,useTextMorph:()=>E});module.exports=D(P);var f=Y(require("react"));var b=class r{element;options={};data;currentMeasures={};prevMeasures={};isInitialRender=!0;static styleEl;constructor(e){this.options={locale:"en",duration:400,ease:"cubic-bezier(0.19, 1, 0.22, 1)",...e},this.element=e.element,this.element.setAttribute("torph-root",""),this.element.style.transitionDuration=`${this.options.duration}ms`,this.element.style.transitionTimingFunction=this.options.ease,e.debug&&this.element.setAttribute("torph-debug",""),this.data=this.element.innerHTML,this.addStyles()}destroy(){this.element.getAnimations().forEach(e=>e.cancel()),this.element.removeAttribute("torph-root"),this.element.removeAttribute("torph-debug"),this.removeStyles()}update(e){if(e!==this.data){if(this.data=e,this.data instanceof HTMLElement)throw new Error("HTMLElement not yet supported");this.createTextGroup(this.data,this.element)}}createTextGroup(e,t){let n=t.offsetWidth,s=t.offsetHeight,o=e.includes(" "),g=new Intl.Segmenter(this.options.locale,{granularity:o?"word":"grapheme"}).segment(e)[Symbol.iterator](),m=this.blocks(g);this.prevMeasures=this.measure();let c=Array.from(t.children),u=new Set(m.map(i=>i.id)),p=c.filter(i=>!u.has(i.getAttribute("torph-id"))&&!i.hasAttribute("torph-exiting")),d=this.getUnscaledBoundingClientRect(t);if(p.forEach(i=>{let a=this.getUnscaledBoundingClientRect(i);i.setAttribute("torph-exiting",""),i.style.position="absolute",i.style.pointerEvents="none",i.style.left=`${a.left-d.left}px`,i.style.top=`${a.top-d.top}px`,i.style.width=`${a.width}px`,i.style.height=`${a.height}px`}),c.forEach(i=>{let a=i.getAttribute("torph-id");u.has(a)&&i.remove()}),m.forEach(i=>{let a=document.createElement("span");a.setAttribute("torph-item",""),a.setAttribute("torph-id",i.id),a.textContent=i.string,t.appendChild(a)}),this.currentMeasures=this.measure(),this.updateStyles(),p.forEach(i=>{if(this.isInitialRender){i.remove();return}let a=i.getAttribute("torph-id"),T=this.prevMeasures[a],w=Array.from(t.children).find(v=>{let L=v.getBoundingClientRect(),O=i.getBoundingClientRect();return Math.abs(L.left-O.left)<40}),x=w?this.currentMeasures[w.getAttribute("torph-id")]:T,R=(x?x.x-(T?.x||0):0)*.5,S=(x?x.y-(T?.y||0):0)*.5;i.getAnimations().forEach(v=>v.cancel());let $=i.animate({transform:`translate(${R}px, ${S}px) scale(0.95)`,opacity:0,offset:1},{duration:this.options.duration,easing:this.options.ease,fill:"both"});$.onfinish=()=>i.remove()}),this.isInitialRender){this.isInitialRender=!1,t.style.width="auto",t.style.height="auto";return}if(n===0||s===0)return;t.style.width="auto",t.style.height="auto",t.offsetWidth;let l=t.offsetWidth,y=t.offsetHeight;t.style.width=`${n}px`,t.style.height=`${s}px`,t.offsetWidth,t.style.width=`${l}px`,t.style.height=`${y}px`,setTimeout(()=>{t.style.width="auto",t.style.height="auto"},this.options.duration)}measure(){let e=Array.from(this.element.children),t={};return e.forEach((n,s)=>{if(n.hasAttribute("torph-exiting"))return;let o=n.getAttribute("torph-id")||`child-${s}`;t[o]={x:n.offsetLeft,y:n.offsetTop}}),t}updateStyles(){if(this.isInitialRender)return;Array.from(this.element.children).forEach((t,n)=>{if(t.hasAttribute("torph-exiting"))return;let s=t.getAttribute("torph-id")||`child-${n}`,o=this.prevMeasures[s],h=this.currentMeasures[s],g=h?.x||0,m=h?.y||0,c=o?o?.x-g:0,u=o?o?.y-m:0,p=!o;t.getAnimations().forEach(d=>d.cancel()),t.animate({transform:`translate(${c}px, ${u}px) scale(${p?.95:1})`,opacity:p?0:1,offset:0},{duration:this.options.duration,easing:this.options.ease,delay:p?this.options.duration*.2:0,fill:"both"})})}addStyles(){if(r.styleEl)return;let e=document.createElement("style");e.dataset.torph="true",e.innerHTML=`
2
+ "use strict";var I=Object.create;var v=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var L=Object.getOwnPropertyNames;var k=Object.getPrototypeOf,H=Object.prototype.hasOwnProperty;var C=(a,t)=>{for(var e in t)v(a,e,{get:t[e],enumerable:!0})},$=(a,t,e,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of L(t))!H.call(a,i)&&i!==e&&v(a,i,{get:()=>t[i],enumerable:!(o=R(t,i))||o.enumerable});return a};var Q=(a,t,e)=>(e=a!=null?I(k(a)):{},$(t||!a||!a.__esModule?v(e,"default",{value:a,enumerable:!0}):e,a)),B=a=>$(v({},"__esModule",{value:!0}),a);var O={};C(O,{TextMorph:()=>S,useTextMorph:()=>A});module.exports=B(O);var m=Q(require("react"));var E=class a{element;options={};data;currentMeasures={};prevMeasures={};isInitialRender=!0;prefersReducedMotion=!1;mediaQuery;static styleEl;constructor(t){if(this.options={locale:"en",duration:400,scale:!0,ease:"cubic-bezier(0.19, 1, 0.22, 1)",respectReducedMotion:!0,...t},this.element=t.element,typeof window<"u"&&this.options.respectReducedMotion){this.mediaQuery=window.matchMedia("(prefers-reduced-motion: reduce)"),this.prefersReducedMotion=this.mediaQuery.matches;let e=o=>{this.prefersReducedMotion=o.matches};this.mediaQuery.addEventListener("change",e)}this.isDisabled()||(this.element.setAttribute("torph-root",""),this.element.style.transitionDuration=`${this.options.duration}ms`,this.element.style.transitionTimingFunction=this.options.ease,t.debug&&this.element.setAttribute("torph-debug","")),this.data=this.element.innerHTML,this.isDisabled()||this.addStyles()}destroy(){this.mediaQuery&&this.mediaQuery.removeEventListener("change",this.handleMediaQueryChange),this.element.getAnimations().forEach(t=>t.cancel()),this.element.removeAttribute("torph-root"),this.element.removeAttribute("torph-debug"),this.removeStyles()}handleMediaQueryChange=t=>{this.prefersReducedMotion=t.matches};isDisabled(){return!!(this.options.disabled||this.options.respectReducedMotion&&this.prefersReducedMotion)}update(t){if(t!==this.data){if(this.data=t,this.isDisabled()){typeof t=="string"&&(this.element.textContent=t);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(t,e){let o=e.offsetWidth,i=e.offsetHeight,h=t.includes(" "),p;if(typeof Intl.Segmenter<"u"){let n=new Intl.Segmenter(this.options.locale,{granularity:h?"word":"grapheme"}).segment(t)[Symbol.iterator]();p=this.blocks(n)}else p=this.blocksFallback(t,h);this.prevMeasures=this.measure();let l=Array.from(e.children),d=new Set(p.map(s=>s.id)),g=l.filter(s=>!d.has(s.getAttribute("torph-id"))&&!s.hasAttribute("torph-exiting")),y=new Set(g),x=new Map;for(let s=0;s<l.length;s++){let n=l[s];if(!y.has(n))continue;let u=null;for(let r=s+1;r<l.length;r++){let c=l[r].getAttribute("torph-id");if(d.has(c)&&!y.has(l[r])){u=c;break}}if(!u)for(let r=s-1;r>=0;r--){let c=l[r].getAttribute("torph-id");if(d.has(c)&&!y.has(l[r])){u=c;break}}x.set(n,u)}let M=e.getBoundingClientRect();if(g.forEach(s=>{let n=s.getBoundingClientRect();s.setAttribute("torph-exiting",""),s.style.position="absolute",s.style.pointerEvents="none",s.style.left=`${n.left-M.left}px`,s.style.top=`${n.top-M.top}px`,s.style.width=`${n.width}px`,s.style.height=`${n.height}px`}),l.forEach(s=>{let n=s.getAttribute("torph-id");d.has(n)&&s.remove()}),p.forEach(s=>{let n=document.createElement("span");n.setAttribute("torph-item",""),n.setAttribute("torph-id",s.id),n.textContent=s.string,e.appendChild(n)}),this.currentMeasures=this.measure(),this.updateStyles(p),g.forEach(s=>{if(this.isInitialRender){s.remove();return}let n=x.get(s),u=0,r=0;if(n&&this.prevMeasures[n]&&this.currentMeasures[n]){let b=this.prevMeasures[n],w=this.currentMeasures[n];u=w.x-b.x,r=w.y-b.y}s.getAnimations().forEach(b=>b.cancel()),s.animate({transform:this.options.scale?`translate(${u}px, ${r}px) scale(0.95)`:`translate(${u}px, ${r}px)`,offset:1},{duration:this.options.duration,easing:this.options.ease,fill:"both"});let c=s.animate({opacity:0,offset:1},{duration:this.options.duration*.25,easing:"linear",fill:"both"});c.onfinish=()=>s.remove()}),this.isInitialRender){this.isInitialRender=!1,e.style.width="auto",e.style.height="auto";return}if(o===0||i===0)return;e.style.width="auto",e.style.height="auto",e.offsetWidth;let f=e.offsetWidth,T=e.offsetHeight;e.style.width=`${o}px`,e.style.height=`${i}px`,e.offsetWidth,e.style.width=`${f}px`,e.style.height=`${T}px`,setTimeout(()=>{e.style.width="auto",e.style.height="auto",this.options.onAnimationComplete&&this.options.onAnimationComplete()},this.options.duration)}measure(){let t=Array.from(this.element.children),e={};return t.forEach((o,i)=>{if(o.hasAttribute("torph-exiting"))return;let h=o.getAttribute("torph-id")||`child-${i}`;e[h]={x:o.offsetLeft,y:o.offsetTop}}),e}updateStyles(t){if(this.isInitialRender)return;let e=Array.from(this.element.children),o=new Set(t.map(i=>i.id).filter(i=>this.prevMeasures[i]));e.forEach((i,h)=>{if(i.hasAttribute("torph-exiting"))return;let p=i.getAttribute("torph-id")||`child-${h}`,l=this.prevMeasures[p],d=this.currentMeasures[p],g=d?.x||0,y=d?.y||0,x=l?l.x-g:0,M=l?l.y-y:0,f=!l;if(f){let n=t.findIndex(r=>r.id===p),u=null;for(let r=n-1;r>=0;r--)if(o.has(t[r].id)){u=t[r].id;break}if(!u){for(let r=n+1;r<t.length;r++)if(o.has(t[r].id)){u=t[r].id;break}}if(u){let r=this.prevMeasures[u],c=this.currentMeasures[u];x=r.x-c.x,M=r.y-c.y}}i.getAnimations().forEach(n=>n.cancel()),i.animate({transform:`translate(${x}px, ${M}px) scale(${f?.95:1})`,offset:0},{duration:this.options.duration,easing:this.options.ease,fill:"both"});let T=f?this.options.duration*.25:0,s=f?this.options.duration*.25:0;i.animate({opacity:f?0:1,offset:0},{duration:T,delay:s,easing:"linear",fill:"both"})})}addStyles(){if(a.styleEl)return;let t=document.createElement("style");t.dataset.torph="true",t.innerHTML=`
3
3
  [torph-root] {
4
- display: inline-flex; /* TODO: remove for multi-line support */
4
+ display: inline-flex;
5
5
  position: relative;
6
6
  will-change: width, height;
7
7
  transition-property: width, height;
8
+ white-space: nowrap;
8
9
  }
9
10
 
10
11
  [torph-item] {
@@ -13,7 +14,7 @@
13
14
  transform: none;
14
15
  opacity: 1;
15
16
  }
16
-
17
+
17
18
  [torph-root][torph-debug] {
18
19
  outline:2px solid magenta;
19
20
  [torph-item] {
@@ -21,5 +22,5 @@
21
22
  outline-offset: -4px;
22
23
  }
23
24
  }
24
- `,document.head.appendChild(e),r.styleEl=e}removeStyles(){r.styleEl&&(r.styleEl.remove(),r.styleEl=void 0)}blocks(e){return Array.from(e).reduce((n,s)=>s.segment===" "?[...n,{id:`space-${s.index}`,string:"\xA0"}]:n.find(h=>h.string===s.segment)?[...n,{id:`${s.segment}-${s.index}`,string:s.segment}]:[...n,{id:s.segment,string:s.segment}],[])}getUnscaledBoundingClientRect(e){let t=e.getBoundingClientRect(),s=window.getComputedStyle(e).transform,o=1,h=1,g=/matrix\(([^)]+)\)/,m=s.match(g);if(m){let l=m[1]?.split(",").map(Number);l&&l?.length>=4&&(o=l[0],h=l[3])}else{let l=s.match(/scaleX\(([^)]+)\)/),y=s.match(/scaleY\(([^)]+)\)/);l&&(o=parseFloat(l[1])),y&&(h=parseFloat(y[1]))}let c=t.width/o,u=t.height/h,p=t.x+(t.width-c)/2,d=t.y+(t.height-u)/2;return{x:p,y:d,width:c,height:u,top:d,right:p+c,bottom:d+u,left:p}}log(...e){this.options.debug&&console.log("[TextMorph]",...e)}};var H=({children:r,...e})=>{let{ref:t,update:n}=E(e);return f.default.useEffect(()=>{n(r)},[r,n]),f.default.createElement("div",{ref:t})};function E(r){let e=f.default.useRef(null),t=f.default.useRef(null);return f.default.useEffect(()=>(e.current&&(t.current=new b({element:e.current,...r})),()=>{t.current?.destroy()}),[]),{ref:e,update:s=>{t.current?.update(s)}}}0&&(module.exports={TextMorph,useTextMorph});
25
+ `,document.head.appendChild(t),a.styleEl=t}removeStyles(){a.styleEl&&(a.styleEl.remove(),a.styleEl=void 0)}blocks(t){return Array.from(t).reduce((o,i)=>i.segment===" "?[...o,{id:`space-${i.index}`,string:"\xA0"}]:o.find(p=>p.string===i.segment)?[...o,{id:`${i.segment}-${i.index}`,string:i.segment}]:[...o,{id:i.segment,string:i.segment}],[])}blocksFallback(t,e){let o=e?t.split(" "):t.split(""),i=[];return e?o.forEach((h,p)=>{p>0&&i.push({id:`space-${p}`,string:"\xA0"}),i.find(d=>d.string===h)?i.push({id:`${h}-${p}`,string:h}):i.push({id:h,string:h})}):o.forEach((h,p)=>{i.find(d=>d.string===h)?i.push({id:`${h}-${p}`,string:h}):i.push({id:h,string:h})}),i}log(...t){this.options.debug&&console.log("[TextMorph]",...t)}};var S=({children:a,className:t,style:e,as:o="div",...i})=>{let{ref:h,update:p}=A(i);return m.default.useEffect(()=>{p(a)},[a,p]),m.default.createElement(o,{ref:h,className:t,style:e})};function A(a){let t=m.default.useRef(null),e=m.default.useRef(null);return m.default.useEffect(()=>(t.current&&(e.current=new E({element:t.current,...a})),()=>{e.current?.destroy()}),[]),{ref:t,update:i=>{e.current?.update(i)}}}0&&(module.exports={TextMorph,useTextMorph});
25
26
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/react/index.ts","../../src/react/TextMorph.tsx","../../src/lib/text-morph/index.ts"],"sourcesContent":["export { TextMorph, useTextMorph } from \"./TextMorph\";\nexport type { TextMorphProps } from \"./TextMorph\";\n\n","\"use client\";\n\nimport React from \"react\";\nimport { TextMorph as Morph } from \"../lib/text-morph\";\nimport type { TextMorphOptions } from \"../lib/text-morph/types\";\n\nexport type TextMorphProps = Omit<TextMorphOptions, \"element\"> & {\n children: string; //React.ReactNode;\n};\n\nexport const TextMorph = ({ children, ...props }: TextMorphProps) => {\n const { ref, update } = useTextMorph(props);\n\n React.useEffect(() => {\n update(children);\n }, [children, update]);\n\n return <div ref={ref} />;\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 = (text: string) => {\n morphRef.current?.update(text);\n };\n\n return { ref, update };\n}\n","import type { TextMorphOptions } from \"./types\";\n\nexport { TextMorphOptions } from \"./types\";\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\n static styleEl: HTMLStyleElement;\n\n constructor(options: TextMorphOptions) {\n this.options = {\n locale: \"en\",\n duration: 400,\n ease: \"cubic-bezier(0.19, 1, 0.22, 1)\",\n ...options,\n };\n\n this.element = options.element;\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 this.data = this.element.innerHTML;\n\n this.addStyles();\n }\n\n destroy() {\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 update(value: HTMLElement | string) {\n if (value === this.data) return;\n this.data = value;\n\n if (this.data instanceof HTMLElement) {\n // TODO: handle HTMLElement case\n throw new Error(\"HTMLElement not yet supported\");\n } else {\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 const segmenter = new Intl.Segmenter(this.options.locale, {\n granularity: byWord ? \"word\" : \"grapheme\",\n });\n const iterator = segmenter.segment(value)[Symbol.iterator]();\n const blocks = this.blocks(iterator);\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 const parentRect = this.getUnscaledBoundingClientRect(element);\n exiting.forEach((child) => {\n const rect = this.getUnscaledBoundingClientRect(child);\n child.setAttribute(\"torph-exiting\", \"\");\n child.style.position = \"absolute\";\n child.style.pointerEvents = \"none\";\n child.style.left = `${rect.left - parentRect.left}px`;\n child.style.top = `${rect.top - parentRect.top}px`;\n child.style.width = `${rect.width}px`;\n child.style.height = `${rect.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 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();\n\n exiting.forEach((child) => {\n if (this.isInitialRender) {\n child.remove();\n return;\n }\n\n const id = child.getAttribute(\"torph-id\")!;\n\n const prev = this.prevMeasures[id];\n\n const siblings = Array.from(element.children) as HTMLElement[];\n const nearest = siblings.find((s) => {\n const sRect = s.getBoundingClientRect();\n const cRect = child.getBoundingClientRect();\n return Math.abs(sRect.left - cRect.left) < 40;\n });\n\n const nextPos = nearest\n ? this.currentMeasures[nearest.getAttribute(\"torph-id\")!]\n : prev;\n\n const dx = (nextPos ? nextPos.x - (prev?.x || 0) : 0) * 0.5;\n const dy = (nextPos ? nextPos.y - (prev?.y || 0) : 0) * 0.5;\n\n child.getAnimations().forEach((a) => a.cancel());\n const animation: Animation = child.animate(\n {\n transform: `translate(${dx}px, ${dy}px) scale(0.95)`,\n opacity: 0,\n offset: 1,\n },\n {\n duration: this.options.duration,\n easing: this.options.ease,\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 }, 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() {\n if (this.isInitialRender) return;\n\n const children = Array.from(this.element.children) as HTMLElement[];\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 const deltaX = prev ? prev?.x - cx : 0;\n const deltaY = prev ? prev?.y - cy : 0;\n const isNew = !prev;\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 opacity: isNew ? 0 : 1,\n offset: 0,\n },\n {\n duration: this.options.duration,\n easing: this.options.ease,\n delay: isNew ? this.options.duration! * 0.2 : 0,\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; /* TODO: remove for multi-line support */\n position: relative;\n will-change: width, height;\n transition-property: width, height;\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 getUnscaledBoundingClientRect(element: HTMLElement) {\n const scaledRect = element.getBoundingClientRect();\n const computedStyle = window.getComputedStyle(element);\n const transform = computedStyle.transform;\n\n let scaleX = 1;\n let scaleY = 1;\n\n const matrixRegex = /matrix\\(([^)]+)\\)/;\n const match = transform.match(matrixRegex);\n\n if (match) {\n const values = match[1]?.split(\",\").map(Number);\n if (values && values?.length >= 4) {\n scaleX = values[0]!;\n scaleY = values[3]!;\n }\n } else {\n const scaleXMatch = transform.match(/scaleX\\(([^)]+)\\)/);\n const scaleYMatch = transform.match(/scaleY\\(([^)]+)\\)/);\n if (scaleXMatch) scaleX = parseFloat(scaleXMatch[1]!);\n if (scaleYMatch) scaleY = parseFloat(scaleYMatch[1]!);\n }\n\n const unscaledWidth = scaledRect.width / scaleX;\n const unscaledHeight = scaledRect.height / scaleY;\n\n const unscaledX = scaledRect.x + (scaledRect.width - unscaledWidth) / 2;\n const unscaledY = scaledRect.y + (scaledRect.height - unscaledHeight) / 2;\n\n return {\n x: unscaledX,\n y: unscaledY,\n width: unscaledWidth,\n height: unscaledHeight,\n top: unscaledY,\n right: unscaledX + unscaledWidth,\n bottom: unscaledY + unscaledHeight,\n left: unscaledX,\n };\n }\n\n private log(...args: any[]) {\n if (this.options.debug) console.log(\"[TextMorph]\", ...args);\n }\n}\n"],"mappings":"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","names":["react_exports","__export","TextMorph","useTextMorph","__toCommonJS","import_react","TextMorph","_TextMorph","options","anim","value","element","oldWidth","oldHeight","byWord","iterator","blocks","oldChildren","newIds","b","exiting","child","parentRect","rect","id","block","span","prev","nearest","s","sRect","cRect","nextPos","dx","dy","a","animation","newWidth","newHeight","children","measures","index","key","current","cx","cy","deltaX","deltaY","isNew","style","acc","string","x","scaledRect","transform","scaleX","scaleY","matrixRegex","match","values","scaleXMatch","scaleYMatch","unscaledWidth","unscaledHeight","unscaledX","unscaledY","args","TextMorph","children","props","ref","update","useTextMorph","React","morphRef","text"]}
1
+ {"version":3,"sources":["../../src/react/index.ts","../../src/react/TextMorph.tsx","../../src/lib/text-morph/index.ts"],"sourcesContent":["export { TextMorph, useTextMorph } from \"./TextMorph\";\nexport type { TextMorphProps } from \"./TextMorph\";\n\n","\"use client\";\n\nimport React from \"react\";\nimport { TextMorph as Morph } from \"../lib/text-morph\";\nimport type { TextMorphOptions } from \"../lib/text-morph/types\";\n\nexport type TextMorphProps = Omit<TextMorphOptions, \"element\"> & {\n children: string; //React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n as?: keyof JSX.IntrinsicElements;\n};\n\nexport const TextMorph = ({\n children,\n className,\n style,\n as = \"div\",\n ...props\n}: TextMorphProps) => {\n const { ref, update } = useTextMorph(props);\n\n React.useEffect(() => {\n update(children);\n }, [children, update]);\n\n const Component = as as any;\n return <Component ref={ref} className={className} style={style} />;\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 = (text: string) => {\n morphRef.current?.update(text);\n };\n\n return { ref, update };\n}\n","import type { TextMorphOptions } from \"./types\";\n\nexport type { TextMorphOptions } from \"./types\";\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 locale: \"en\",\n duration: 400,\n scale: true,\n ease: \"cubic-bezier(0.19, 1, 0.22, 1)\",\n respectReducedMotion: true,\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\n const listener = (event: MediaQueryListEvent) => {\n this.prefersReducedMotion = event.matches;\n };\n\n this.mediaQuery.addEventListener(\"change\", listener);\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 = this.element.innerHTML;\n\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 const parentRect = element.getBoundingClientRect();\n exiting.forEach((child) => {\n const rect = child.getBoundingClientRect();\n child.setAttribute(\"torph-exiting\", \"\");\n child.style.position = \"absolute\";\n child.style.pointerEvents = \"none\";\n child.style.left = `${rect.left - parentRect.left}px`;\n child.style.top = `${rect.top - parentRect.top}px`;\n child.style.width = `${rect.width}px`;\n child.style.height = `${rect.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 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.getAnimations().forEach((a) => a.cancel());\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"],"mappings":"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","names":["react_exports","__export","TextMorph","useTextMorph","__toCommonJS","import_react","TextMorph","_TextMorph","options","listener","event","anim","value","element","oldWidth","oldHeight","byWord","blocks","iterator","oldChildren","newIds","b","exiting","child","exitingSet","exitingAnchorId","i","anchor","j","siblingId","parentRect","rect","id","block","span","anchorId","dx","dy","anchorPrev","anchorCurr","a","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","TextMorph","children","className","style","as","props","ref","update","useTextMorph","React","morphRef","text"]}
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- import{a as n}from"../chunk-43OPPES3.mjs";import r from"react";var x=({children:o,...e})=>{let{ref:t,update:p}=u(e);return r.useEffect(()=>{p(o)},[o,p]),r.createElement("div",{ref:t})};function u(o){let e=r.useRef(null),t=r.useRef(null);return r.useEffect(()=>(e.current&&(t.current=new n({element:e.current,...o})),()=>{t.current?.destroy()}),[]),{ref:e,update:s=>{t.current?.update(s)}}}export{x as TextMorph,u as useTextMorph};
2
+ import{a as u}from"../chunk-5MHVW5FX.mjs";import r from"react";var c=({children:o,className:e,style:t,as:n="div",...p})=>{let{ref:i,update:s}=m(p);return r.useEffect(()=>{s(o)},[o,s]),r.createElement(n,{ref:i,className:e,style:t})};function m(o){let e=r.useRef(null),t=r.useRef(null);return r.useEffect(()=>(e.current&&(t.current=new u({element:e.current,...o})),()=>{t.current?.destroy()}),[]),{ref:e,update:p=>{t.current?.update(p)}}}export{c as TextMorph,m as useTextMorph};
3
3
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/react/TextMorph.tsx"],"sourcesContent":["\"use client\";\n\nimport React from \"react\";\nimport { TextMorph as Morph } from \"../lib/text-morph\";\nimport type { TextMorphOptions } from \"../lib/text-morph/types\";\n\nexport type TextMorphProps = Omit<TextMorphOptions, \"element\"> & {\n children: string; //React.ReactNode;\n};\n\nexport const TextMorph = ({ children, ...props }: TextMorphProps) => {\n const { ref, update } = useTextMorph(props);\n\n React.useEffect(() => {\n update(children);\n }, [children, update]);\n\n return <div ref={ref} />;\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 = (text: string) => {\n morphRef.current?.update(text);\n };\n\n return { ref, update };\n}\n"],"mappings":";0CAEA,OAAOA,MAAW,QAQX,IAAMC,EAAY,CAAC,CAAE,SAAAC,EAAU,GAAGC,CAAM,IAAsB,CACnE,GAAM,CAAE,IAAAC,EAAK,OAAAC,CAAO,EAAIC,EAAaH,CAAK,EAE1C,OAAAI,EAAM,UAAU,IAAM,CACpBF,EAAOH,CAAQ,CACjB,EAAG,CAACA,EAAUG,CAAM,CAAC,EAEdE,EAAA,cAAC,OAAI,IAAKH,EAAK,CACxB,EAEO,SAASE,EAAaH,EAA0C,CACrE,IAAMC,EAAMG,EAAM,OAA8B,IAAI,EAC9CC,EAAWD,EAAM,OAAqB,IAAI,EAEhD,OAAAA,EAAM,UAAU,KACVH,EAAI,UACNI,EAAS,QAAU,IAAIP,EAAM,CAAE,QAASG,EAAI,QAAS,GAAGD,CAAM,CAAC,GAG1D,IAAM,CACXK,EAAS,SAAS,QAAQ,CAC5B,GACC,CAAC,CAAC,EAME,CAAE,IAAAJ,EAAK,OAJEK,GAAiB,CAC/BD,EAAS,SAAS,OAAOC,CAAI,CAC/B,CAEqB,CACvB","names":["React","TextMorph","children","props","ref","update","useTextMorph","React","morphRef","text"]}
1
+ {"version":3,"sources":["../../src/react/TextMorph.tsx"],"sourcesContent":["\"use client\";\n\nimport React from \"react\";\nimport { TextMorph as Morph } from \"../lib/text-morph\";\nimport type { TextMorphOptions } from \"../lib/text-morph/types\";\n\nexport type TextMorphProps = Omit<TextMorphOptions, \"element\"> & {\n children: string; //React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n as?: keyof JSX.IntrinsicElements;\n};\n\nexport const TextMorph = ({\n children,\n className,\n style,\n as = \"div\",\n ...props\n}: TextMorphProps) => {\n const { ref, update } = useTextMorph(props);\n\n React.useEffect(() => {\n update(children);\n }, [children, update]);\n\n const Component = as as any;\n return <Component ref={ref} className={className} style={style} />;\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 = (text: string) => {\n morphRef.current?.update(text);\n };\n\n return { ref, update };\n}\n"],"mappings":";0CAEA,OAAOA,MAAW,QAWX,IAAMC,EAAY,CAAC,CACxB,SAAAC,EACA,UAAAC,EACA,MAAAC,EACA,GAAAC,EAAK,MACL,GAAGC,CACL,IAAsB,CACpB,GAAM,CAAE,IAAAC,EAAK,OAAAC,CAAO,EAAIC,EAAaH,CAAK,EAE1C,OAAAI,EAAM,UAAU,IAAM,CACpBF,EAAON,CAAQ,CACjB,EAAG,CAACA,EAAUM,CAAM,CAAC,EAGdE,EAAA,cADWL,EACV,CAAU,IAAKE,EAAK,UAAWJ,EAAW,MAAOC,EAAO,CAClE,EAEO,SAASK,EAAaH,EAA0C,CACrE,IAAMC,EAAMG,EAAM,OAA8B,IAAI,EAC9CC,EAAWD,EAAM,OAAqB,IAAI,EAEhD,OAAAA,EAAM,UAAU,KACVH,EAAI,UACNI,EAAS,QAAU,IAAIV,EAAM,CAAE,QAASM,EAAI,QAAS,GAAGD,CAAM,CAAC,GAG1D,IAAM,CACXK,EAAS,SAAS,QAAQ,CAC5B,GACC,CAAC,CAAC,EAME,CAAE,IAAAJ,EAAK,OAJEK,GAAiB,CAC/BD,EAAS,SAAS,OAAOC,CAAI,CAC/B,CAEqB,CACvB","names":["React","TextMorph","children","className","style","as","props","ref","update","useTextMorph","React","morphRef","text"]}
@@ -0,0 +1,10 @@
1
+ import { TextMorphOptions } from '../../lib/text-morph/types';
2
+
3
+ interface TextMorphProps extends Omit<TextMorphOptions, "element"> {
4
+ text: string;
5
+ class?: string;
6
+ style?: string;
7
+ as?: string;
8
+ }
9
+
10
+ export type { TextMorphProps };
@@ -1,2 +1,2 @@
1
- "use strict";var s=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var _=Object.getOwnPropertyNames;var M=Object.prototype.hasOwnProperty;var T=(i,e)=>{for(var n in e)s(i,n,{get:e[n],enumerable:!0})},k=(i,e,n,u)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of _(e))!M.call(i,r)&&r!==n&&s(i,r,{get:()=>e[r],enumerable:!(u=y(e,r))||u.enumerable});return i};var q=i=>k(s({},"__esModule",{value:!0}),i);var C={};T(C,{TextMorph:()=>h});module.exports=q(C);var t=require("svelte/internal"),I=require("svelte/internal/disclose-version"),c=require("svelte"),x=require("../lib/text-morph");function w(i){let e;return{c(){e=(0,t.element)("div")},m(n,u){(0,t.insert)(n,e,u),i[7](e)},p:t.noop,i:t.noop,o:t.noop,d(n){n&&(0,t.detach)(e),i[7](null)}}}function z(i,e,n){let{text:u}=e,{locale:r="en"}=e,{duration:a=400}=e,{ease:d="cubic-bezier(0.19, 1, 0.22, 1)"}=e,{debug:m=!1}=e,l,f=null;(0,c.onMount)(()=>{l&&(n(6,f=new x.TextMorph({element:l,locale:r,duration:a,ease:d,debug:m})),f.update(u))}),(0,c.onDestroy)(()=>{f?.destroy()});function g(o){t.binding_callbacks[o?"unshift":"push"](()=>{l=o,n(0,l)})}return i.$$set=o=>{"text"in o&&n(1,u=o.text),"locale"in o&&n(2,r=o.locale),"duration"in o&&n(3,a=o.duration),"ease"in o&&n(4,d=o.ease),"debug"in o&&n(5,m=o.debug)},i.$$.update=()=>{i.$$.dirty&66&&f&&f.update(u)},[l,u,r,a,d,m,f,g]}var b=class extends t.SvelteComponent{constructor(e){super(),(0,t.init)(this,e,z,w,t.safe_not_equal,{text:1,locale:2,duration:3,ease:4,debug:5})}},h=b;0&&(module.exports={TextMorph});
1
+ "use strict";var g=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var q=Object.getOwnPropertyNames;var w=Object.prototype.hasOwnProperty;var z=(m,e)=>{for(var n in e)g(m,n,{get:e[n],enumerable:!0})},D=(m,e,n,l)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of q(e))!w.call(m,t)&&t!==n&&g(m,t,{get:()=>e[t],enumerable:!(l=k(e,t))||l.enumerable});return m};var I=m=>D(g({},"__esModule",{value:!0}),m);var B={};z(B,{TextMorph:()=>N});module.exports=I(B);var i=require("svelte/internal"),F=require("svelte/internal/disclose-version"),d=require("svelte"),S=require("../lib/text-morph");function h(m){let e,n=[{class:m[0]},{style:m[1]}],l={};for(let t=0;t<n.length;t+=1)l=(0,i.assign)(l,n[t]);return{c(){e=(0,i.element)(m[2]),(0,i.set_dynamic_element_data)(m[2])(e,l)},m(t,o){(0,i.insert)(t,e,o),m[14](e)},p(t,o){(0,i.set_dynamic_element_data)(t[2])(e,l=(0,i.get_spread_update)(n,[o&1&&{class:t[0]},o&2&&{style:t[1]}]))},d(t){t&&(0,i.detach)(e),m[14](null)}}}function P(m){let e=m[2],n,l=m[2]&&h(m);return{c(){l&&l.c(),n=(0,i.empty)()},m(t,o){l&&l.m(t,o),(0,i.insert)(t,n,o)},p(t,[o]){t[2]?e?(0,i.safe_not_equal)(e,t[2])?(l.d(1),l=h(t),e=t[2],l.c(),l.m(n.parentNode,n)):l.p(t,o):(l=h(t),e=t[2],l.c(),l.m(n.parentNode,n)):e&&(l.d(1),l=null,e=t[2])},i:i.noop,o:i.noop,d(t){t&&(0,i.detach)(n),l&&l.d(t)}}}function j(m,e,n){let{text:l}=e,{locale:t="en"}=e,{duration:o=400}=e,{ease:u="cubic-bezier(0.19, 1, 0.22, 1)"}=e,{debug:c=!1}=e,{disabled:_=!1}=e,{respectReducedMotion:r=!0}=e,{onAnimationStart:b=void 0}=e,{onAnimationComplete:y=void 0}=e,{class:M=""}=e,{style:C=""}=e,{as:R="div"}=e,s,f=null;(0,d.onMount)(()=>{s&&(n(13,f=new S.TextMorph({element:s,locale:t,duration:o,ease:u,debug:c,disabled:_,respectReducedMotion:r,onAnimationStart:b,onAnimationComplete:y})),f.update(l))}),(0,d.onDestroy)(()=>{f?.destroy()});function T(a){i.binding_callbacks[a?"unshift":"push"](()=>{s=a,n(3,s)})}return m.$$set=a=>{"text"in a&&n(4,l=a.text),"locale"in a&&n(5,t=a.locale),"duration"in a&&n(6,o=a.duration),"ease"in a&&n(7,u=a.ease),"debug"in a&&n(8,c=a.debug),"disabled"in a&&n(9,_=a.disabled),"respectReducedMotion"in a&&n(10,r=a.respectReducedMotion),"onAnimationStart"in a&&n(11,b=a.onAnimationStart),"onAnimationComplete"in a&&n(12,y=a.onAnimationComplete),"class"in a&&n(0,M=a.class),"style"in a&&n(1,C=a.style),"as"in a&&n(2,R=a.as)},m.$$.update=()=>{m.$$.dirty&8208&&f&&f.update(l)},[M,C,R,s,l,t,o,u,c,_,r,b,y,f,T]}var A=class extends i.SvelteComponent{constructor(e){super(),(0,i.init)(this,e,j,P,i.safe_not_equal,{text:4,locale:5,duration:6,ease:7,debug:8,disabled:9,respectReducedMotion:10,onAnimationStart:11,onAnimationComplete:12,class:0,style:1,as:2})}},N=A;0&&(module.exports={TextMorph});
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/svelte/index.ts","../../src/svelte/TextMorph.svelte"],"sourcesContent":["export { default as TextMorph } from \"./TextMorph.svelte\";\nexport type { TextMorphProps } from \"./types\";\n\n","/* src/svelte/TextMorph.svelte generated by Svelte v4.2.20 */\nimport {\n\tSvelteComponent,\n\tbinding_callbacks,\n\tdetach,\n\telement,\n\tinit,\n\tinsert,\n\tnoop,\n\tsafe_not_equal\n} from \"svelte/internal\";\n\nimport \"svelte/internal/disclose-version\";\nimport { onMount, onDestroy } from \"svelte\";\nimport { TextMorph as Morph } from \"../lib/text-morph\";\n\nfunction create_fragment(ctx) {\n\tlet div;\n\n\treturn {\n\t\tc() {\n\t\t\tdiv = element(\"div\");\n\t\t},\n\t\tm(target, anchor) {\n\t\t\tinsert(target, div, anchor);\n\t\t\t/*div_binding*/ ctx[7](div);\n\t\t},\n\t\tp: noop,\n\t\ti: noop,\n\t\to: noop,\n\t\td(detaching) {\n\t\t\tif (detaching) {\n\t\t\t\tdetach(div);\n\t\t\t}\n\n\t\t\t/*div_binding*/ ctx[7](null);\n\t\t}\n\t};\n}\n\nfunction instance($$self, $$props, $$invalidate) {\n\tlet { text } = $$props;\n\tlet { locale = \"en\" } = $$props;\n\tlet { duration = 400 } = $$props;\n\tlet { ease = \"cubic-bezier(0.19, 1, 0.22, 1)\" } = $$props;\n\tlet { debug = false } = $$props;\n\tlet containerRef;\n\tlet morphInstance = null;\n\n\tonMount(() => {\n\t\tif (containerRef) {\n\t\t\t$$invalidate(6, morphInstance = new Morph({\n\t\t\t\t\telement: containerRef,\n\t\t\t\t\tlocale,\n\t\t\t\t\tduration,\n\t\t\t\t\tease,\n\t\t\t\t\tdebug\n\t\t\t\t}));\n\n\t\t\tmorphInstance.update(text);\n\t\t}\n\t});\n\n\tonDestroy(() => {\n\t\tmorphInstance?.destroy();\n\t});\n\n\tfunction div_binding($$value) {\n\t\tbinding_callbacks[$$value ? 'unshift' : 'push'](() => {\n\t\t\tcontainerRef = $$value;\n\t\t\t$$invalidate(0, containerRef);\n\t\t});\n\t}\n\n\t$$self.$$set = $$props => {\n\t\tif ('text' in $$props) $$invalidate(1, text = $$props.text);\n\t\tif ('locale' in $$props) $$invalidate(2, locale = $$props.locale);\n\t\tif ('duration' in $$props) $$invalidate(3, duration = $$props.duration);\n\t\tif ('ease' in $$props) $$invalidate(4, ease = $$props.ease);\n\t\tif ('debug' in $$props) $$invalidate(5, debug = $$props.debug);\n\t};\n\n\t$$self.$$.update = () => {\n\t\tif ($$self.$$.dirty & /*morphInstance, text*/ 66) {\n\t\t\t$: if (morphInstance) {\n\t\t\t\tmorphInstance.update(text);\n\t\t\t}\n\t\t}\n\t};\n\n\treturn [containerRef, text, locale, duration, ease, debug, morphInstance, div_binding];\n}\n\nclass TextMorph extends SvelteComponent {\n\tconstructor(options) {\n\t\tsuper();\n\n\t\tinit(this, options, instance, create_fragment, safe_not_equal, {\n\t\t\ttext: 1,\n\t\t\tlocale: 2,\n\t\t\tduration: 3,\n\t\t\tease: 4,\n\t\t\tdebug: 5\n\t\t});\n\t}\n}\n\nexport default TextMorph;"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,eAAAE,IAAA,eAAAC,EAAAH,GCCA,IAAAI,EASO,2BAEPC,EAAO,4CACPC,EAAmC,kBACnCC,EAAmC,6BAEnC,SAASC,EAAgBC,EAAK,CAC7B,IAAIC,EAEJ,MAAO,CACN,GAAI,CACHA,KAAM,WAAQ,KAAK,CACpB,EACA,EAAEC,EAAQC,EAAQ,IACjB,UAAOD,EAAQD,EAAKE,CAAM,EACVH,EAAI,CAAC,EAAEC,CAAG,CAC3B,EACA,EAAG,OACH,EAAG,OACH,EAAG,OACH,EAAEG,EAAW,CACRA,MACH,UAAOH,CAAG,EAGKD,EAAI,CAAC,EAAE,IAAI,CAC5B,CACD,CACD,CAEA,SAASK,EAASC,EAAQC,EAASC,EAAc,CAChD,GAAI,CAAE,KAAAC,CAAK,EAAIF,EACX,CAAE,OAAAG,EAAS,IAAK,EAAIH,EACpB,CAAE,SAAAI,EAAW,GAAI,EAAIJ,EACrB,CAAE,KAAAK,EAAO,gCAAiC,EAAIL,EAC9C,CAAE,MAAAM,EAAQ,EAAM,EAAIN,EACpBO,EACAC,EAAgB,QAEpB,WAAQ,IAAM,CACTD,IACHN,EAAa,EAAGO,EAAgB,IAAI,EAAAC,UAAM,CACxC,QAASF,EACT,OAAAJ,EACA,SAAAC,EACA,KAAAC,EACA,MAAAC,CACD,CAAC,CAAC,EAEHE,EAAc,OAAON,CAAI,EAE3B,CAAC,KAED,aAAU,IAAM,CACfM,GAAe,QAAQ,CACxB,CAAC,EAED,SAASE,EAAYC,EAAS,CAC7B,oBAAkBA,EAAU,UAAY,MAAM,EAAE,IAAM,CACrDJ,EAAeI,EACfV,EAAa,EAAGM,CAAY,CAC7B,CAAC,CACF,CAEA,OAAAR,EAAO,MAAQC,GAAW,CACrB,SAAUA,GAASC,EAAa,EAAGC,EAAOF,EAAQ,IAAI,EACtD,WAAYA,GAASC,EAAa,EAAGE,EAASH,EAAQ,MAAM,EAC5D,aAAcA,GAASC,EAAa,EAAGG,EAAWJ,EAAQ,QAAQ,EAClE,SAAUA,GAASC,EAAa,EAAGI,EAAOL,EAAQ,IAAI,EACtD,UAAWA,GAASC,EAAa,EAAGK,EAAQN,EAAQ,KAAK,CAC9D,EAEAD,EAAO,GAAG,OAAS,IAAM,CACpBA,EAAO,GAAG,MAAgC,IACtCS,GACNA,EAAc,OAAON,CAAI,CAG5B,EAEO,CAACK,EAAcL,EAAMC,EAAQC,EAAUC,EAAMC,EAAOE,EAAeE,CAAW,CACtF,CAEA,IAAME,EAAN,cAAwB,iBAAgB,CACvC,YAAYC,EAAS,CACpB,MAAM,KAEN,QAAK,KAAMA,EAASf,EAAUN,EAAiB,iBAAgB,CAC9D,KAAM,EACN,OAAQ,EACR,SAAU,EACV,KAAM,EACN,MAAO,CACR,CAAC,CACF,CACD,EAEOsB,EAAQF","names":["svelte_exports","__export","TextMorph_default","__toCommonJS","import_internal","import_disclose_version","import_svelte","import_text_morph","create_fragment","ctx","div","target","anchor","detaching","instance","$$self","$$props","$$invalidate","text","locale","duration","ease","debug","containerRef","morphInstance","Morph","div_binding","$$value","TextMorph","options","TextMorph_default"]}
1
+ {"version":3,"sources":["../../src/svelte/index.ts","../../src/svelte/TextMorph.svelte"],"sourcesContent":["export { default as TextMorph } from \"./TextMorph.svelte\";\nexport type { TextMorphProps } from \"./types\";\n\n","/* src/svelte/TextMorph.svelte generated by Svelte v4.2.20 */\nimport {\n\tSvelteComponent,\n\tassign,\n\tbinding_callbacks,\n\tdetach,\n\telement,\n\tempty,\n\tget_spread_update,\n\tinit,\n\tinsert,\n\tnoop,\n\tsafe_not_equal,\n\tset_dynamic_element_data\n} from \"svelte/internal\";\n\nimport \"svelte/internal/disclose-version\";\nimport { onMount, onDestroy } from \"svelte\";\nimport { TextMorph as Morph } from \"../lib/text-morph\";\n\nfunction create_dynamic_element(ctx) {\n\tlet svelte_element;\n\tlet svelte_element_levels = [{ class: /*className*/ ctx[0] }, { style: /*style*/ ctx[1] }];\n\tlet svelte_element_data = {};\n\n\tfor (let i = 0; i < svelte_element_levels.length; i += 1) {\n\t\tsvelte_element_data = assign(svelte_element_data, svelte_element_levels[i]);\n\t}\n\n\treturn {\n\t\tc() {\n\t\t\tsvelte_element = element(/*as*/ ctx[2]);\n\t\t\tset_dynamic_element_data(/*as*/ ctx[2])(svelte_element, svelte_element_data);\n\t\t},\n\t\tm(target, anchor) {\n\t\t\tinsert(target, svelte_element, anchor);\n\t\t\t/*svelte_element_binding*/ ctx[14](svelte_element);\n\t\t},\n\t\tp(ctx, dirty) {\n\t\t\tset_dynamic_element_data(/*as*/ ctx[2])(svelte_element, svelte_element_data = get_spread_update(svelte_element_levels, [\n\t\t\t\tdirty & /*className*/ 1 && { class: /*className*/ ctx[0] },\n\t\t\t\tdirty & /*style*/ 2 && { style: /*style*/ ctx[1] }\n\t\t\t]));\n\t\t},\n\t\td(detaching) {\n\t\t\tif (detaching) {\n\t\t\t\tdetach(svelte_element);\n\t\t\t}\n\n\t\t\t/*svelte_element_binding*/ ctx[14](null);\n\t\t}\n\t};\n}\n\nfunction create_fragment(ctx) {\n\tlet previous_tag = /*as*/ ctx[2];\n\tlet svelte_element_anchor;\n\tlet svelte_element = /*as*/ ctx[2] && create_dynamic_element(ctx);\n\n\treturn {\n\t\tc() {\n\t\t\tif (svelte_element) svelte_element.c();\n\t\t\tsvelte_element_anchor = empty();\n\t\t},\n\t\tm(target, anchor) {\n\t\t\tif (svelte_element) svelte_element.m(target, anchor);\n\t\t\tinsert(target, svelte_element_anchor, anchor);\n\t\t},\n\t\tp(ctx, [dirty]) {\n\t\t\tif (/*as*/ ctx[2]) {\n\t\t\t\tif (!previous_tag) {\n\t\t\t\t\tsvelte_element = create_dynamic_element(ctx);\n\t\t\t\t\tprevious_tag = /*as*/ ctx[2];\n\t\t\t\t\tsvelte_element.c();\n\t\t\t\t\tsvelte_element.m(svelte_element_anchor.parentNode, svelte_element_anchor);\n\t\t\t\t} else if (safe_not_equal(previous_tag, /*as*/ ctx[2])) {\n\t\t\t\t\tsvelte_element.d(1);\n\t\t\t\t\tsvelte_element = create_dynamic_element(ctx);\n\t\t\t\t\tprevious_tag = /*as*/ ctx[2];\n\t\t\t\t\tsvelte_element.c();\n\t\t\t\t\tsvelte_element.m(svelte_element_anchor.parentNode, svelte_element_anchor);\n\t\t\t\t} else {\n\t\t\t\t\tsvelte_element.p(ctx, dirty);\n\t\t\t\t}\n\t\t\t} else if (previous_tag) {\n\t\t\t\tsvelte_element.d(1);\n\t\t\t\tsvelte_element = null;\n\t\t\t\tprevious_tag = /*as*/ ctx[2];\n\t\t\t}\n\t\t},\n\t\ti: noop,\n\t\to: noop,\n\t\td(detaching) {\n\t\t\tif (detaching) {\n\t\t\t\tdetach(svelte_element_anchor);\n\t\t\t}\n\n\t\t\tif (svelte_element) svelte_element.d(detaching);\n\t\t}\n\t};\n}\n\nfunction instance($$self, $$props, $$invalidate) {\n\tlet { text } = $$props;\n\tlet { locale = \"en\" } = $$props;\n\tlet { duration = 400 } = $$props;\n\tlet { ease = \"cubic-bezier(0.19, 1, 0.22, 1)\" } = $$props;\n\tlet { debug = false } = $$props;\n\tlet { disabled = false } = $$props;\n\tlet { respectReducedMotion = true } = $$props;\n\tlet { onAnimationStart = void 0 } = $$props;\n\tlet { onAnimationComplete = void 0 } = $$props;\n\tlet { class: className = \"\" } = $$props;\n\tlet { style = \"\" } = $$props;\n\tlet { as = \"div\" } = $$props;\n\tlet containerRef;\n\tlet morphInstance = null;\n\n\tonMount(() => {\n\t\tif (containerRef) {\n\t\t\t$$invalidate(13, morphInstance = new Morph({\n\t\t\t\t\telement: containerRef,\n\t\t\t\t\tlocale,\n\t\t\t\t\tduration,\n\t\t\t\t\tease,\n\t\t\t\t\tdebug,\n\t\t\t\t\tdisabled,\n\t\t\t\t\trespectReducedMotion,\n\t\t\t\t\tonAnimationStart,\n\t\t\t\t\tonAnimationComplete\n\t\t\t\t}));\n\n\t\t\tmorphInstance.update(text);\n\t\t}\n\t});\n\n\tonDestroy(() => {\n\t\tmorphInstance?.destroy();\n\t});\n\n\tfunction svelte_element_binding($$value) {\n\t\tbinding_callbacks[$$value ? 'unshift' : 'push'](() => {\n\t\t\tcontainerRef = $$value;\n\t\t\t$$invalidate(3, containerRef);\n\t\t});\n\t}\n\n\t$$self.$$set = $$props => {\n\t\tif ('text' in $$props) $$invalidate(4, text = $$props.text);\n\t\tif ('locale' in $$props) $$invalidate(5, locale = $$props.locale);\n\t\tif ('duration' in $$props) $$invalidate(6, duration = $$props.duration);\n\t\tif ('ease' in $$props) $$invalidate(7, ease = $$props.ease);\n\t\tif ('debug' in $$props) $$invalidate(8, debug = $$props.debug);\n\t\tif ('disabled' in $$props) $$invalidate(9, disabled = $$props.disabled);\n\t\tif ('respectReducedMotion' in $$props) $$invalidate(10, respectReducedMotion = $$props.respectReducedMotion);\n\t\tif ('onAnimationStart' in $$props) $$invalidate(11, onAnimationStart = $$props.onAnimationStart);\n\t\tif ('onAnimationComplete' in $$props) $$invalidate(12, onAnimationComplete = $$props.onAnimationComplete);\n\t\tif ('class' in $$props) $$invalidate(0, className = $$props.class);\n\t\tif ('style' in $$props) $$invalidate(1, style = $$props.style);\n\t\tif ('as' in $$props) $$invalidate(2, as = $$props.as);\n\t};\n\n\t$$self.$$.update = () => {\n\t\tif ($$self.$$.dirty & /*morphInstance, text*/ 8208) {\n\t\t\t$: if (morphInstance) {\n\t\t\t\tmorphInstance.update(text);\n\t\t\t}\n\t\t}\n\t};\n\n\treturn [\n\t\tclassName,\n\t\tstyle,\n\t\tas,\n\t\tcontainerRef,\n\t\ttext,\n\t\tlocale,\n\t\tduration,\n\t\tease,\n\t\tdebug,\n\t\tdisabled,\n\t\trespectReducedMotion,\n\t\tonAnimationStart,\n\t\tonAnimationComplete,\n\t\tmorphInstance,\n\t\tsvelte_element_binding\n\t];\n}\n\nclass TextMorph extends SvelteComponent {\n\tconstructor(options) {\n\t\tsuper();\n\n\t\tinit(this, options, instance, create_fragment, safe_not_equal, {\n\t\t\ttext: 4,\n\t\t\tlocale: 5,\n\t\t\tduration: 6,\n\t\t\tease: 7,\n\t\t\tdebug: 8,\n\t\t\tdisabled: 9,\n\t\t\trespectReducedMotion: 10,\n\t\t\tonAnimationStart: 11,\n\t\t\tonAnimationComplete: 12,\n\t\t\tclass: 0,\n\t\t\tstyle: 1,\n\t\t\tas: 2\n\t\t});\n\t}\n}\n\nexport default TextMorph;"],"mappings":"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","names":["svelte_exports","__export","TextMorph_default","__toCommonJS","import_internal","import_disclose_version","import_svelte","import_text_morph","create_dynamic_element","ctx","svelte_element","svelte_element_levels","svelte_element_data","i","target","anchor","dirty","detaching","create_fragment","previous_tag","svelte_element_anchor","instance","$$self","$$props","$$invalidate","text","locale","duration","ease","debug","disabled","respectReducedMotion","onAnimationStart","onAnimationComplete","className","style","as","containerRef","morphInstance","Morph","svelte_element_binding","$$value","TextMorph","options","TextMorph_default"]}
@@ -1,2 +1,2 @@
1
- import{SvelteComponent as b,binding_callbacks as x,detach as h,element as g,init as y,insert as _,noop as d,safe_not_equal as M}from"svelte/internal";import"svelte/internal/disclose-version";import{onMount as T,onDestroy as k}from"svelte";import{TextMorph as q}from"../lib/text-morph";function w(i){let t;return{c(){t=g("div")},m(n,o){_(n,t,o),i[7](t)},p:d,i:d,o:d,d(n){n&&h(t),i[7](null)}}}function z(i,t,n){let{text:o}=t,{locale:f="en"}=t,{duration:l=400}=t,{ease:c="cubic-bezier(0.19, 1, 0.22, 1)"}=t,{debug:a=!1}=t,r,u=null;T(()=>{r&&(n(6,u=new q({element:r,locale:f,duration:l,ease:c,debug:a})),u.update(o))}),k(()=>{u?.destroy()});function s(e){x[e?"unshift":"push"](()=>{r=e,n(0,r)})}return i.$$set=e=>{"text"in e&&n(1,o=e.text),"locale"in e&&n(2,f=e.locale),"duration"in e&&n(3,l=e.duration),"ease"in e&&n(4,c=e.ease),"debug"in e&&n(5,a=e.debug)},i.$$.update=()=>{i.$$.dirty&66&&u&&u.update(o)},[r,o,f,l,c,a,u,s]}var m=class extends b{constructor(t){super(),y(this,t,z,w,M,{text:1,locale:2,duration:3,ease:4,debug:5})}},C=m;export{C as TextMorph};
1
+ import{SvelteComponent as k,assign as q,binding_callbacks as w,detach as R,element as z,empty as D,get_spread_update as I,init as P,insert as S,noop as M,safe_not_equal as N,set_dynamic_element_data as C}from"svelte/internal";import"svelte/internal/disclose-version";import{onMount as j,onDestroy as B}from"svelte";import{TextMorph as E}from"../lib/text-morph";function b(a){let t,l=[{class:a[0]},{style:a[1]}],i={};for(let e=0;e<l.length;e+=1)i=q(i,l[e]);return{c(){t=z(a[2]),C(a[2])(t,i)},m(e,m){S(e,t,m),a[14](t)},p(e,m){C(e[2])(t,i=I(l,[m&1&&{class:e[0]},m&2&&{style:e[1]}]))},d(e){e&&R(t),a[14](null)}}}function F(a){let t=a[2],l,i=a[2]&&b(a);return{c(){i&&i.c(),l=D()},m(e,m){i&&i.m(e,m),S(e,l,m)},p(e,[m]){e[2]?t?N(t,e[2])?(i.d(1),i=b(e),t=e[2],i.c(),i.m(l.parentNode,l)):i.p(e,m):(i=b(e),t=e[2],i.c(),i.m(l.parentNode,l)):t&&(i.d(1),i=null,t=e[2])},i:M,o:M,d(e){e&&R(l),i&&i.d(e)}}}function G(a,t,l){let{text:i}=t,{locale:e="en"}=t,{duration:m=400}=t,{ease:s="cubic-bezier(0.19, 1, 0.22, 1)"}=t,{debug:d=!1}=t,{disabled:u=!1}=t,{respectReducedMotion:c=!0}=t,{onAnimationStart:_=void 0}=t,{onAnimationComplete:r=void 0}=t,{class:g=""}=t,{style:h=""}=t,{as:A="div"}=t,f,o=null;j(()=>{f&&(l(13,o=new E({element:f,locale:e,duration:m,ease:s,debug:d,disabled:u,respectReducedMotion:c,onAnimationStart:_,onAnimationComplete:r})),o.update(i))}),B(()=>{o?.destroy()});function T(n){w[n?"unshift":"push"](()=>{f=n,l(3,f)})}return a.$$set=n=>{"text"in n&&l(4,i=n.text),"locale"in n&&l(5,e=n.locale),"duration"in n&&l(6,m=n.duration),"ease"in n&&l(7,s=n.ease),"debug"in n&&l(8,d=n.debug),"disabled"in n&&l(9,u=n.disabled),"respectReducedMotion"in n&&l(10,c=n.respectReducedMotion),"onAnimationStart"in n&&l(11,_=n.onAnimationStart),"onAnimationComplete"in n&&l(12,r=n.onAnimationComplete),"class"in n&&l(0,g=n.class),"style"in n&&l(1,h=n.style),"as"in n&&l(2,A=n.as)},a.$$.update=()=>{a.$$.dirty&8208&&o&&o.update(i)},[g,h,A,f,i,e,m,s,d,u,c,_,r,o,T]}var y=class extends k{constructor(t){super(),P(this,t,G,F,N,{text:4,locale:5,duration:6,ease:7,debug:8,disabled:9,respectReducedMotion:10,onAnimationStart:11,onAnimationComplete:12,class:0,style:1,as:2})}},H=y;export{H as TextMorph};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/svelte/TextMorph.svelte"],"sourcesContent":["/* src/svelte/TextMorph.svelte generated by Svelte v4.2.20 */\nimport {\n\tSvelteComponent,\n\tbinding_callbacks,\n\tdetach,\n\telement,\n\tinit,\n\tinsert,\n\tnoop,\n\tsafe_not_equal\n} from \"svelte/internal\";\n\nimport \"svelte/internal/disclose-version\";\nimport { onMount, onDestroy } from \"svelte\";\nimport { TextMorph as Morph } from \"../lib/text-morph\";\n\nfunction create_fragment(ctx) {\n\tlet div;\n\n\treturn {\n\t\tc() {\n\t\t\tdiv = element(\"div\");\n\t\t},\n\t\tm(target, anchor) {\n\t\t\tinsert(target, div, anchor);\n\t\t\t/*div_binding*/ ctx[7](div);\n\t\t},\n\t\tp: noop,\n\t\ti: noop,\n\t\to: noop,\n\t\td(detaching) {\n\t\t\tif (detaching) {\n\t\t\t\tdetach(div);\n\t\t\t}\n\n\t\t\t/*div_binding*/ ctx[7](null);\n\t\t}\n\t};\n}\n\nfunction instance($$self, $$props, $$invalidate) {\n\tlet { text } = $$props;\n\tlet { locale = \"en\" } = $$props;\n\tlet { duration = 400 } = $$props;\n\tlet { ease = \"cubic-bezier(0.19, 1, 0.22, 1)\" } = $$props;\n\tlet { debug = false } = $$props;\n\tlet containerRef;\n\tlet morphInstance = null;\n\n\tonMount(() => {\n\t\tif (containerRef) {\n\t\t\t$$invalidate(6, morphInstance = new Morph({\n\t\t\t\t\telement: containerRef,\n\t\t\t\t\tlocale,\n\t\t\t\t\tduration,\n\t\t\t\t\tease,\n\t\t\t\t\tdebug\n\t\t\t\t}));\n\n\t\t\tmorphInstance.update(text);\n\t\t}\n\t});\n\n\tonDestroy(() => {\n\t\tmorphInstance?.destroy();\n\t});\n\n\tfunction div_binding($$value) {\n\t\tbinding_callbacks[$$value ? 'unshift' : 'push'](() => {\n\t\t\tcontainerRef = $$value;\n\t\t\t$$invalidate(0, containerRef);\n\t\t});\n\t}\n\n\t$$self.$$set = $$props => {\n\t\tif ('text' in $$props) $$invalidate(1, text = $$props.text);\n\t\tif ('locale' in $$props) $$invalidate(2, locale = $$props.locale);\n\t\tif ('duration' in $$props) $$invalidate(3, duration = $$props.duration);\n\t\tif ('ease' in $$props) $$invalidate(4, ease = $$props.ease);\n\t\tif ('debug' in $$props) $$invalidate(5, debug = $$props.debug);\n\t};\n\n\t$$self.$$.update = () => {\n\t\tif ($$self.$$.dirty & /*morphInstance, text*/ 66) {\n\t\t\t$: if (morphInstance) {\n\t\t\t\tmorphInstance.update(text);\n\t\t\t}\n\t\t}\n\t};\n\n\treturn [containerRef, text, locale, duration, ease, debug, morphInstance, div_binding];\n}\n\nclass TextMorph extends SvelteComponent {\n\tconstructor(options) {\n\t\tsuper();\n\n\t\tinit(this, options, instance, create_fragment, safe_not_equal, {\n\t\t\ttext: 1,\n\t\t\tlocale: 2,\n\t\t\tduration: 3,\n\t\t\tease: 4,\n\t\t\tdebug: 5\n\t\t});\n\t}\n}\n\nexport default TextMorph;"],"mappings":"AACA,OACC,mBAAAA,EACA,qBAAAC,EACA,UAAAC,EACA,WAAAC,EACA,QAAAC,EACA,UAAAC,EACA,QAAAC,EACA,kBAAAC,MACM,kBAEP,MAAO,mCACP,OAAS,WAAAC,EAAS,aAAAC,MAAiB,SACnC,OAAS,aAAaC,MAAa,oBAEnC,SAASC,EAAgBC,EAAK,CAC7B,IAAIC,EAEJ,MAAO,CACN,GAAI,CACHA,EAAMV,EAAQ,KAAK,CACpB,EACA,EAAEW,EAAQC,EAAQ,CACjBV,EAAOS,EAAQD,EAAKE,CAAM,EACVH,EAAI,CAAC,EAAEC,CAAG,CAC3B,EACA,EAAGP,EACH,EAAGA,EACH,EAAGA,EACH,EAAEU,EAAW,CACRA,GACHd,EAAOW,CAAG,EAGKD,EAAI,CAAC,EAAE,IAAI,CAC5B,CACD,CACD,CAEA,SAASK,EAASC,EAAQC,EAASC,EAAc,CAChD,GAAI,CAAE,KAAAC,CAAK,EAAIF,EACX,CAAE,OAAAG,EAAS,IAAK,EAAIH,EACpB,CAAE,SAAAI,EAAW,GAAI,EAAIJ,EACrB,CAAE,KAAAK,EAAO,gCAAiC,EAAIL,EAC9C,CAAE,MAAAM,EAAQ,EAAM,EAAIN,EACpBO,EACAC,EAAgB,KAEpBnB,EAAQ,IAAM,CACTkB,IACHN,EAAa,EAAGO,EAAgB,IAAIjB,EAAM,CACxC,QAASgB,EACT,OAAAJ,EACA,SAAAC,EACA,KAAAC,EACA,MAAAC,CACD,CAAC,CAAC,EAEHE,EAAc,OAAON,CAAI,EAE3B,CAAC,EAEDZ,EAAU,IAAM,CACfkB,GAAe,QAAQ,CACxB,CAAC,EAED,SAASC,EAAYC,EAAS,CAC7B5B,EAAkB4B,EAAU,UAAY,MAAM,EAAE,IAAM,CACrDH,EAAeG,EACfT,EAAa,EAAGM,CAAY,CAC7B,CAAC,CACF,CAEA,OAAAR,EAAO,MAAQC,GAAW,CACrB,SAAUA,GAASC,EAAa,EAAGC,EAAOF,EAAQ,IAAI,EACtD,WAAYA,GAASC,EAAa,EAAGE,EAASH,EAAQ,MAAM,EAC5D,aAAcA,GAASC,EAAa,EAAGG,EAAWJ,EAAQ,QAAQ,EAClE,SAAUA,GAASC,EAAa,EAAGI,EAAOL,EAAQ,IAAI,EACtD,UAAWA,GAASC,EAAa,EAAGK,EAAQN,EAAQ,KAAK,CAC9D,EAEAD,EAAO,GAAG,OAAS,IAAM,CACpBA,EAAO,GAAG,MAAgC,IACtCS,GACNA,EAAc,OAAON,CAAI,CAG5B,EAEO,CAACK,EAAcL,EAAMC,EAAQC,EAAUC,EAAMC,EAAOE,EAAeC,CAAW,CACtF,CAEA,IAAME,EAAN,cAAwB9B,CAAgB,CACvC,YAAY+B,EAAS,CACpB,MAAM,EAEN3B,EAAK,KAAM2B,EAASd,EAAUN,EAAiBJ,EAAgB,CAC9D,KAAM,EACN,OAAQ,EACR,SAAU,EACV,KAAM,EACN,MAAO,CACR,CAAC,CACF,CACD,EAEOyB,EAAQF","names":["SvelteComponent","binding_callbacks","detach","element","init","insert","noop","safe_not_equal","onMount","onDestroy","Morph","create_fragment","ctx","div","target","anchor","detaching","instance","$$self","$$props","$$invalidate","text","locale","duration","ease","debug","containerRef","morphInstance","div_binding","$$value","TextMorph","options","TextMorph_default"]}
1
+ {"version":3,"sources":["../../src/svelte/TextMorph.svelte"],"sourcesContent":["/* src/svelte/TextMorph.svelte generated by Svelte v4.2.20 */\nimport {\n\tSvelteComponent,\n\tassign,\n\tbinding_callbacks,\n\tdetach,\n\telement,\n\tempty,\n\tget_spread_update,\n\tinit,\n\tinsert,\n\tnoop,\n\tsafe_not_equal,\n\tset_dynamic_element_data\n} from \"svelte/internal\";\n\nimport \"svelte/internal/disclose-version\";\nimport { onMount, onDestroy } from \"svelte\";\nimport { TextMorph as Morph } from \"../lib/text-morph\";\n\nfunction create_dynamic_element(ctx) {\n\tlet svelte_element;\n\tlet svelte_element_levels = [{ class: /*className*/ ctx[0] }, { style: /*style*/ ctx[1] }];\n\tlet svelte_element_data = {};\n\n\tfor (let i = 0; i < svelte_element_levels.length; i += 1) {\n\t\tsvelte_element_data = assign(svelte_element_data, svelte_element_levels[i]);\n\t}\n\n\treturn {\n\t\tc() {\n\t\t\tsvelte_element = element(/*as*/ ctx[2]);\n\t\t\tset_dynamic_element_data(/*as*/ ctx[2])(svelte_element, svelte_element_data);\n\t\t},\n\t\tm(target, anchor) {\n\t\t\tinsert(target, svelte_element, anchor);\n\t\t\t/*svelte_element_binding*/ ctx[14](svelte_element);\n\t\t},\n\t\tp(ctx, dirty) {\n\t\t\tset_dynamic_element_data(/*as*/ ctx[2])(svelte_element, svelte_element_data = get_spread_update(svelte_element_levels, [\n\t\t\t\tdirty & /*className*/ 1 && { class: /*className*/ ctx[0] },\n\t\t\t\tdirty & /*style*/ 2 && { style: /*style*/ ctx[1] }\n\t\t\t]));\n\t\t},\n\t\td(detaching) {\n\t\t\tif (detaching) {\n\t\t\t\tdetach(svelte_element);\n\t\t\t}\n\n\t\t\t/*svelte_element_binding*/ ctx[14](null);\n\t\t}\n\t};\n}\n\nfunction create_fragment(ctx) {\n\tlet previous_tag = /*as*/ ctx[2];\n\tlet svelte_element_anchor;\n\tlet svelte_element = /*as*/ ctx[2] && create_dynamic_element(ctx);\n\n\treturn {\n\t\tc() {\n\t\t\tif (svelte_element) svelte_element.c();\n\t\t\tsvelte_element_anchor = empty();\n\t\t},\n\t\tm(target, anchor) {\n\t\t\tif (svelte_element) svelte_element.m(target, anchor);\n\t\t\tinsert(target, svelte_element_anchor, anchor);\n\t\t},\n\t\tp(ctx, [dirty]) {\n\t\t\tif (/*as*/ ctx[2]) {\n\t\t\t\tif (!previous_tag) {\n\t\t\t\t\tsvelte_element = create_dynamic_element(ctx);\n\t\t\t\t\tprevious_tag = /*as*/ ctx[2];\n\t\t\t\t\tsvelte_element.c();\n\t\t\t\t\tsvelte_element.m(svelte_element_anchor.parentNode, svelte_element_anchor);\n\t\t\t\t} else if (safe_not_equal(previous_tag, /*as*/ ctx[2])) {\n\t\t\t\t\tsvelte_element.d(1);\n\t\t\t\t\tsvelte_element = create_dynamic_element(ctx);\n\t\t\t\t\tprevious_tag = /*as*/ ctx[2];\n\t\t\t\t\tsvelte_element.c();\n\t\t\t\t\tsvelte_element.m(svelte_element_anchor.parentNode, svelte_element_anchor);\n\t\t\t\t} else {\n\t\t\t\t\tsvelte_element.p(ctx, dirty);\n\t\t\t\t}\n\t\t\t} else if (previous_tag) {\n\t\t\t\tsvelte_element.d(1);\n\t\t\t\tsvelte_element = null;\n\t\t\t\tprevious_tag = /*as*/ ctx[2];\n\t\t\t}\n\t\t},\n\t\ti: noop,\n\t\to: noop,\n\t\td(detaching) {\n\t\t\tif (detaching) {\n\t\t\t\tdetach(svelte_element_anchor);\n\t\t\t}\n\n\t\t\tif (svelte_element) svelte_element.d(detaching);\n\t\t}\n\t};\n}\n\nfunction instance($$self, $$props, $$invalidate) {\n\tlet { text } = $$props;\n\tlet { locale = \"en\" } = $$props;\n\tlet { duration = 400 } = $$props;\n\tlet { ease = \"cubic-bezier(0.19, 1, 0.22, 1)\" } = $$props;\n\tlet { debug = false } = $$props;\n\tlet { disabled = false } = $$props;\n\tlet { respectReducedMotion = true } = $$props;\n\tlet { onAnimationStart = void 0 } = $$props;\n\tlet { onAnimationComplete = void 0 } = $$props;\n\tlet { class: className = \"\" } = $$props;\n\tlet { style = \"\" } = $$props;\n\tlet { as = \"div\" } = $$props;\n\tlet containerRef;\n\tlet morphInstance = null;\n\n\tonMount(() => {\n\t\tif (containerRef) {\n\t\t\t$$invalidate(13, morphInstance = new Morph({\n\t\t\t\t\telement: containerRef,\n\t\t\t\t\tlocale,\n\t\t\t\t\tduration,\n\t\t\t\t\tease,\n\t\t\t\t\tdebug,\n\t\t\t\t\tdisabled,\n\t\t\t\t\trespectReducedMotion,\n\t\t\t\t\tonAnimationStart,\n\t\t\t\t\tonAnimationComplete\n\t\t\t\t}));\n\n\t\t\tmorphInstance.update(text);\n\t\t}\n\t});\n\n\tonDestroy(() => {\n\t\tmorphInstance?.destroy();\n\t});\n\n\tfunction svelte_element_binding($$value) {\n\t\tbinding_callbacks[$$value ? 'unshift' : 'push'](() => {\n\t\t\tcontainerRef = $$value;\n\t\t\t$$invalidate(3, containerRef);\n\t\t});\n\t}\n\n\t$$self.$$set = $$props => {\n\t\tif ('text' in $$props) $$invalidate(4, text = $$props.text);\n\t\tif ('locale' in $$props) $$invalidate(5, locale = $$props.locale);\n\t\tif ('duration' in $$props) $$invalidate(6, duration = $$props.duration);\n\t\tif ('ease' in $$props) $$invalidate(7, ease = $$props.ease);\n\t\tif ('debug' in $$props) $$invalidate(8, debug = $$props.debug);\n\t\tif ('disabled' in $$props) $$invalidate(9, disabled = $$props.disabled);\n\t\tif ('respectReducedMotion' in $$props) $$invalidate(10, respectReducedMotion = $$props.respectReducedMotion);\n\t\tif ('onAnimationStart' in $$props) $$invalidate(11, onAnimationStart = $$props.onAnimationStart);\n\t\tif ('onAnimationComplete' in $$props) $$invalidate(12, onAnimationComplete = $$props.onAnimationComplete);\n\t\tif ('class' in $$props) $$invalidate(0, className = $$props.class);\n\t\tif ('style' in $$props) $$invalidate(1, style = $$props.style);\n\t\tif ('as' in $$props) $$invalidate(2, as = $$props.as);\n\t};\n\n\t$$self.$$.update = () => {\n\t\tif ($$self.$$.dirty & /*morphInstance, text*/ 8208) {\n\t\t\t$: if (morphInstance) {\n\t\t\t\tmorphInstance.update(text);\n\t\t\t}\n\t\t}\n\t};\n\n\treturn [\n\t\tclassName,\n\t\tstyle,\n\t\tas,\n\t\tcontainerRef,\n\t\ttext,\n\t\tlocale,\n\t\tduration,\n\t\tease,\n\t\tdebug,\n\t\tdisabled,\n\t\trespectReducedMotion,\n\t\tonAnimationStart,\n\t\tonAnimationComplete,\n\t\tmorphInstance,\n\t\tsvelte_element_binding\n\t];\n}\n\nclass TextMorph extends SvelteComponent {\n\tconstructor(options) {\n\t\tsuper();\n\n\t\tinit(this, options, instance, create_fragment, safe_not_equal, {\n\t\t\ttext: 4,\n\t\t\tlocale: 5,\n\t\t\tduration: 6,\n\t\t\tease: 7,\n\t\t\tdebug: 8,\n\t\t\tdisabled: 9,\n\t\t\trespectReducedMotion: 10,\n\t\t\tonAnimationStart: 11,\n\t\t\tonAnimationComplete: 12,\n\t\t\tclass: 0,\n\t\t\tstyle: 1,\n\t\t\tas: 2\n\t\t});\n\t}\n}\n\nexport default TextMorph;"],"mappings":"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","names":["SvelteComponent","assign","binding_callbacks","detach","element","empty","get_spread_update","init","insert","noop","safe_not_equal","set_dynamic_element_data","onMount","onDestroy","Morph","create_dynamic_element","ctx","svelte_element","svelte_element_levels","svelte_element_data","i","target","anchor","dirty","detaching","create_fragment","previous_tag","svelte_element_anchor","instance","$$self","$$props","$$invalidate","text","locale","duration","ease","debug","disabled","respectReducedMotion","onAnimationStart","onAnimationComplete","className","style","as","containerRef","morphInstance","svelte_element_binding","$$value","TextMorph","options","TextMorph_default"]}
@@ -2,8 +2,13 @@ interface TextMorphOptions {
2
2
  debug?: boolean;
3
3
  element: HTMLElement;
4
4
  locale?: Intl.LocalesArgument;
5
+ scale?: boolean;
5
6
  duration?: number;
6
7
  ease?: string;
8
+ disabled?: boolean;
9
+ respectReducedMotion?: boolean;
10
+ onAnimationStart?: () => void;
11
+ onAnimationComplete?: () => void;
7
12
  }
8
13
 
9
14
  export type { TextMorphOptions as T };
@@ -2,8 +2,13 @@ interface TextMorphOptions {
2
2
  debug?: boolean;
3
3
  element: HTMLElement;
4
4
  locale?: Intl.LocalesArgument;
5
+ scale?: boolean;
5
6
  duration?: number;
6
7
  ease?: string;
8
+ disabled?: boolean;
9
+ respectReducedMotion?: boolean;
10
+ onAnimationStart?: () => void;
11
+ onAnimationComplete?: () => void;
7
12
  }
8
13
 
9
14
  export type { TextMorphOptions as T };
package/dist/vue/index.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var a=Object.create;var t=Object.defineProperty;var h=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var y=Object.getPrototypeOf,M=Object.prototype.hasOwnProperty;var T=(e,o)=>{for(var p in o)t(e,p,{get:o[p],enumerable:!0})},f=(e,o,p,x)=>{if(o&&typeof o=="object"||typeof o=="function")for(let r of m(o))!M.call(e,r)&&r!==p&&t(e,r,{get:()=>o[r],enumerable:!(x=h(o,r))||x.enumerable});return e};var d=(e,o,p)=>(p=e!=null?a(y(e)):{},f(o||!e||!e.__esModule?t(p,"default",{value:e,enumerable:!0}):p,e)),l=e=>f(t({},"__esModule",{value:!0}),e);var u={};T(u,{TextMorph:()=>s.default});module.exports=l(u);var s=d(require("../TextMorph-TPUHANOZ.vue"));0&&(module.exports={TextMorph});
1
+ "use strict";var a=Object.create;var t=Object.defineProperty;var h=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var y=Object.getPrototypeOf,M=Object.prototype.hasOwnProperty;var T=(e,o)=>{for(var p in o)t(e,p,{get:o[p],enumerable:!0})},f=(e,o,p,x)=>{if(o&&typeof o=="object"||typeof o=="function")for(let r of m(o))!M.call(e,r)&&r!==p&&t(e,r,{get:()=>o[r],enumerable:!(x=h(o,r))||x.enumerable});return e};var d=(e,o,p)=>(p=e!=null?a(y(e)):{},f(o||!e||!e.__esModule?t(p,"default",{value:e,enumerable:!0}):p,e)),l=e=>f(t({},"__esModule",{value:!0}),e);var u={};T(u,{TextMorph:()=>s.default});module.exports=l(u);var s=d(require("../TextMorph-N26F7N56.vue"));0&&(module.exports={TextMorph});
2
2
  //# sourceMappingURL=index.js.map
@@ -1,2 +1,2 @@
1
- import{default as p}from"../TextMorph-TPUHANOZ.vue";export{p as TextMorph};
1
+ import{default as p}from"../TextMorph-N26F7N56.vue";export{p as TextMorph};
2
2
  //# sourceMappingURL=index.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "torph",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "Dependency-free animated text component.",
5
5
  "author": "Lochie Axon",
6
6
  "license": "MIT",
@@ -1,47 +0,0 @@
1
- <template>
2
- <div ref="containerRef"></div>
3
- </template>
4
-
5
- <script setup lang="ts">
6
- import { ref, onMounted, onUnmounted, watch } from 'vue';
7
- import { TextMorph as Morph } from '../lib/text-morph';
8
- import type { TextMorphOptions } from '../lib/text-morph/types';
9
-
10
- export interface TextMorphProps extends Omit<TextMorphOptions, 'element'> {
11
- text: string;
12
- }
13
-
14
- const props = withDefaults(defineProps<TextMorphProps>(), {
15
- locale: 'en',
16
- duration: 400,
17
- ease: 'cubic-bezier(0.19, 1, 0.22, 1)',
18
- });
19
-
20
- const containerRef = ref<HTMLDivElement | null>(null);
21
- let morphInstance: Morph | null = null;
22
-
23
- onMounted(() => {
24
- if (containerRef.value) {
25
- morphInstance = new Morph({
26
- element: containerRef.value,
27
- locale: props.locale,
28
- duration: props.duration,
29
- ease: props.ease,
30
- debug: props.debug,
31
- });
32
- morphInstance.update(props.text);
33
- }
34
- });
35
-
36
- onUnmounted(() => {
37
- morphInstance?.destroy();
38
- });
39
-
40
- watch(
41
- () => props.text,
42
- (newText) => {
43
- morphInstance?.update(newText);
44
- }
45
- );
46
- </script>
47
-
@@ -1,25 +0,0 @@
1
- "use client";
2
- var v=class g{element;options={};data;currentMeasures={};prevMeasures={};isInitialRender=!0;static styleEl;constructor(e){this.options={locale:"en",duration:400,ease:"cubic-bezier(0.19, 1, 0.22, 1)",...e},this.element=e.element,this.element.setAttribute("torph-root",""),this.element.style.transitionDuration=`${this.options.duration}ms`,this.element.style.transitionTimingFunction=this.options.ease,e.debug&&this.element.setAttribute("torph-debug",""),this.data=this.element.innerHTML,this.addStyles()}destroy(){this.element.getAnimations().forEach(e=>e.cancel()),this.element.removeAttribute("torph-root"),this.element.removeAttribute("torph-debug"),this.removeStyles()}update(e){if(e!==this.data){if(this.data=e,this.data instanceof HTMLElement)throw new Error("HTMLElement not yet supported");this.createTextGroup(this.data,this.element)}}createTextGroup(e,t){let n=t.offsetWidth,i=t.offsetHeight,r=e.includes(" "),m=new Intl.Segmenter(this.options.locale,{granularity:r?"word":"grapheme"}).segment(e)[Symbol.iterator](),d=this.blocks(m);this.prevMeasures=this.measure();let c=Array.from(t.children),p=new Set(d.map(s=>s.id)),a=c.filter(s=>!p.has(s.getAttribute("torph-id"))&&!s.hasAttribute("torph-exiting")),u=this.getUnscaledBoundingClientRect(t);if(a.forEach(s=>{let o=this.getUnscaledBoundingClientRect(s);s.setAttribute("torph-exiting",""),s.style.position="absolute",s.style.pointerEvents="none",s.style.left=`${o.left-u.left}px`,s.style.top=`${o.top-u.top}px`,s.style.width=`${o.width}px`,s.style.height=`${o.height}px`}),c.forEach(s=>{let o=s.getAttribute("torph-id");p.has(o)&&s.remove()}),d.forEach(s=>{let o=document.createElement("span");o.setAttribute("torph-item",""),o.setAttribute("torph-id",s.id),o.textContent=s.string,t.appendChild(o)}),this.currentMeasures=this.measure(),this.updateStyles(),a.forEach(s=>{if(this.isInitialRender){s.remove();return}let o=s.getAttribute("torph-id"),x=this.prevMeasures[o],M=Array.from(t.children).find(b=>{let T=b.getBoundingClientRect(),H=s.getBoundingClientRect();return Math.abs(T.left-H.left)<40}),y=M?this.currentMeasures[M.getAttribute("torph-id")]:x,E=(y?y.x-(x?.x||0):0)*.5,A=(y?y.y-(x?.y||0):0)*.5;s.getAnimations().forEach(b=>b.cancel());let w=s.animate({transform:`translate(${E}px, ${A}px) scale(0.95)`,opacity:0,offset:1},{duration:this.options.duration,easing:this.options.ease,fill:"both"});w.onfinish=()=>s.remove()}),this.isInitialRender){this.isInitialRender=!1,t.style.width="auto",t.style.height="auto";return}if(n===0||i===0)return;t.style.width="auto",t.style.height="auto",t.offsetWidth;let l=t.offsetWidth,f=t.offsetHeight;t.style.width=`${n}px`,t.style.height=`${i}px`,t.offsetWidth,t.style.width=`${l}px`,t.style.height=`${f}px`,setTimeout(()=>{t.style.width="auto",t.style.height="auto"},this.options.duration)}measure(){let e=Array.from(this.element.children),t={};return e.forEach((n,i)=>{if(n.hasAttribute("torph-exiting"))return;let r=n.getAttribute("torph-id")||`child-${i}`;t[r]={x:n.offsetLeft,y:n.offsetTop}}),t}updateStyles(){if(this.isInitialRender)return;Array.from(this.element.children).forEach((t,n)=>{if(t.hasAttribute("torph-exiting"))return;let i=t.getAttribute("torph-id")||`child-${n}`,r=this.prevMeasures[i],h=this.currentMeasures[i],m=h?.x||0,d=h?.y||0,c=r?r?.x-m:0,p=r?r?.y-d:0,a=!r;t.getAnimations().forEach(u=>u.cancel()),t.animate({transform:`translate(${c}px, ${p}px) scale(${a?.95:1})`,opacity:a?0:1,offset:0},{duration:this.options.duration,easing:this.options.ease,delay:a?this.options.duration*.2:0,fill:"both"})})}addStyles(){if(g.styleEl)return;let e=document.createElement("style");e.dataset.torph="true",e.innerHTML=`
3
- [torph-root] {
4
- display: inline-flex; /* TODO: remove for multi-line support */
5
- position: relative;
6
- will-change: width, height;
7
- transition-property: width, height;
8
- }
9
-
10
- [torph-item] {
11
- display: inline-block;
12
- will-change: opacity, transform;
13
- transform: none;
14
- opacity: 1;
15
- }
16
-
17
- [torph-root][torph-debug] {
18
- outline:2px solid magenta;
19
- [torph-item] {
20
- outline:2px solid cyan;
21
- outline-offset: -4px;
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((n,i)=>i.segment===" "?[...n,{id:`space-${i.index}`,string:"\xA0"}]:n.find(h=>h.string===i.segment)?[...n,{id:`${i.segment}-${i.index}`,string:i.segment}]:[...n,{id:i.segment,string:i.segment}],[])}getUnscaledBoundingClientRect(e){let t=e.getBoundingClientRect(),i=window.getComputedStyle(e).transform,r=1,h=1,m=/matrix\(([^)]+)\)/,d=i.match(m);if(d){let l=d[1]?.split(",").map(Number);l&&l?.length>=4&&(r=l[0],h=l[3])}else{let l=i.match(/scaleX\(([^)]+)\)/),f=i.match(/scaleY\(([^)]+)\)/);l&&(r=parseFloat(l[1])),f&&(h=parseFloat(f[1]))}let c=t.width/r,p=t.height/h,a=t.x+(t.width-c)/2,u=t.y+(t.height-p)/2;return{x:a,y:u,width:c,height:p,top:u,right:a+c,bottom:u+p,left:a}}log(...e){this.options.debug&&console.log("[TextMorph]",...e)}};export{v as a};
25
- //# sourceMappingURL=chunk-43OPPES3.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/lib/text-morph/index.ts"],"sourcesContent":["import type { TextMorphOptions } from \"./types\";\n\nexport { TextMorphOptions } from \"./types\";\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\n static styleEl: HTMLStyleElement;\n\n constructor(options: TextMorphOptions) {\n this.options = {\n locale: \"en\",\n duration: 400,\n ease: \"cubic-bezier(0.19, 1, 0.22, 1)\",\n ...options,\n };\n\n this.element = options.element;\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 this.data = this.element.innerHTML;\n\n this.addStyles();\n }\n\n destroy() {\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 update(value: HTMLElement | string) {\n if (value === this.data) return;\n this.data = value;\n\n if (this.data instanceof HTMLElement) {\n // TODO: handle HTMLElement case\n throw new Error(\"HTMLElement not yet supported\");\n } else {\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 const segmenter = new Intl.Segmenter(this.options.locale, {\n granularity: byWord ? \"word\" : \"grapheme\",\n });\n const iterator = segmenter.segment(value)[Symbol.iterator]();\n const blocks = this.blocks(iterator);\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 const parentRect = this.getUnscaledBoundingClientRect(element);\n exiting.forEach((child) => {\n const rect = this.getUnscaledBoundingClientRect(child);\n child.setAttribute(\"torph-exiting\", \"\");\n child.style.position = \"absolute\";\n child.style.pointerEvents = \"none\";\n child.style.left = `${rect.left - parentRect.left}px`;\n child.style.top = `${rect.top - parentRect.top}px`;\n child.style.width = `${rect.width}px`;\n child.style.height = `${rect.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 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();\n\n exiting.forEach((child) => {\n if (this.isInitialRender) {\n child.remove();\n return;\n }\n\n const id = child.getAttribute(\"torph-id\")!;\n\n const prev = this.prevMeasures[id];\n\n const siblings = Array.from(element.children) as HTMLElement[];\n const nearest = siblings.find((s) => {\n const sRect = s.getBoundingClientRect();\n const cRect = child.getBoundingClientRect();\n return Math.abs(sRect.left - cRect.left) < 40;\n });\n\n const nextPos = nearest\n ? this.currentMeasures[nearest.getAttribute(\"torph-id\")!]\n : prev;\n\n const dx = (nextPos ? nextPos.x - (prev?.x || 0) : 0) * 0.5;\n const dy = (nextPos ? nextPos.y - (prev?.y || 0) : 0) * 0.5;\n\n child.getAnimations().forEach((a) => a.cancel());\n const animation: Animation = child.animate(\n {\n transform: `translate(${dx}px, ${dy}px) scale(0.95)`,\n opacity: 0,\n offset: 1,\n },\n {\n duration: this.options.duration,\n easing: this.options.ease,\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 }, 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() {\n if (this.isInitialRender) return;\n\n const children = Array.from(this.element.children) as HTMLElement[];\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 const deltaX = prev ? prev?.x - cx : 0;\n const deltaY = prev ? prev?.y - cy : 0;\n const isNew = !prev;\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 opacity: isNew ? 0 : 1,\n offset: 0,\n },\n {\n duration: this.options.duration,\n easing: this.options.ease,\n delay: isNew ? this.options.duration! * 0.2 : 0,\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; /* TODO: remove for multi-line support */\n position: relative;\n will-change: width, height;\n transition-property: width, height;\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 getUnscaledBoundingClientRect(element: HTMLElement) {\n const scaledRect = element.getBoundingClientRect();\n const computedStyle = window.getComputedStyle(element);\n const transform = computedStyle.transform;\n\n let scaleX = 1;\n let scaleY = 1;\n\n const matrixRegex = /matrix\\(([^)]+)\\)/;\n const match = transform.match(matrixRegex);\n\n if (match) {\n const values = match[1]?.split(\",\").map(Number);\n if (values && values?.length >= 4) {\n scaleX = values[0]!;\n scaleY = values[3]!;\n }\n } else {\n const scaleXMatch = transform.match(/scaleX\\(([^)]+)\\)/);\n const scaleYMatch = transform.match(/scaleY\\(([^)]+)\\)/);\n if (scaleXMatch) scaleX = parseFloat(scaleXMatch[1]!);\n if (scaleYMatch) scaleY = parseFloat(scaleYMatch[1]!);\n }\n\n const unscaledWidth = scaledRect.width / scaleX;\n const unscaledHeight = scaledRect.height / scaleY;\n\n const unscaledX = scaledRect.x + (scaledRect.width - unscaledWidth) / 2;\n const unscaledY = scaledRect.y + (scaledRect.height - unscaledHeight) / 2;\n\n return {\n x: unscaledX,\n y: unscaledY,\n width: unscaledWidth,\n height: unscaledHeight,\n top: unscaledY,\n right: unscaledX + unscaledWidth,\n bottom: unscaledY + unscaledHeight,\n left: unscaledX,\n };\n }\n\n private log(...args: any[]) {\n if (this.options.debug) console.log(\"[TextMorph]\", ...args);\n }\n}\n"],"mappings":"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","names":["TextMorph","_TextMorph","options","anim","value","element","oldWidth","oldHeight","byWord","iterator","blocks","oldChildren","newIds","b","exiting","child","parentRect","rect","id","block","span","prev","nearest","s","sRect","cRect","nextPos","dx","dy","a","animation","newWidth","newHeight","children","measures","index","key","current","cx","cy","deltaX","deltaY","isNew","style","acc","string","x","scaledRect","transform","scaleX","scaleY","matrixRegex","match","values","scaleXMatch","scaleYMatch","unscaledWidth","unscaledHeight","unscaledX","unscaledY","args"]}