@ev-ry/fx 0.1.0-rc.3 → 0.1.0-rc.4

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/QUICKSTART.fa.md CHANGED
@@ -1,6 +1,6 @@
1
- # EV-RY FX Free 0.1.0-rc.3 — نصب آزمایشی
1
+ # EV-RY FX Free 0.1.0-rc.4 — نصب آزمایشی
2
2
 
3
- این نسخهٔ آزمایشی عمومی با مجوز MIT ارائه می‌شود. نام بسته در npm برابر @ev-ry/fx است.
3
+ این نسخهٔ آزمایشی عمومی با مجوز MIT ارائه می‌شود. نام بسته در npm برابر @ev-ry/fx است. [صفحهٔ رسمی FX](https://ev-ry.com/fx/) و [دموی تعاملی Free](https://kbaghini.github.io/evry-fx/docs/) جداگانه در دسترس‌اند.
4
4
 
5
5
  ## روش script
6
6
 
@@ -34,7 +34,7 @@ H1/H2 خودکار انتخاب می‌شوند. برای تصویر `data-thd-i
34
34
  ## نصب با npm
35
35
 
36
36
  ```sh
37
- npm install ./thd-free-0.1.0-rc.3.tgz
37
+ npm install @ev-ry/fx
38
38
  ```
39
39
 
40
40
  برای import از `@ev-ry/fx`، namespace سازگار THREE را خودتان ارائه کنید؛ نسخهٔ همراه script همان r158 است. راهنمای کامل API در docs/GUIDE.md قرار دارد.
@@ -63,13 +63,13 @@ const api = await loadFree({THREE, auto: true});
63
63
 
64
64
  پیش‌فرض `once:true` یعنی تنها اولین ورود. با `once:false`، خروج کامل آیتم آن را فوراً مخفی و برای ورود مجدد آماده می‌کند؛ این خروج افکت محو اجرا نمی‌کند. حرکت کوچک داخل محدوده نباید افکت را تکرار کند. ورود مجدد در حین افکت ناتمام، همان زمان‌بندی را ادامه می‌دهد؛ پس از پایان، ورود جدید افکت تازه می‌سازد. `play('enter')` درخواست بازپخش صریح و `play('exit')` درخواست محو متحرک است.
65
65
 
66
- `threshold` نسبت مساحت قابل مشاهده است: صفر برای اولین تقاطع مثبت، `0.5` برای نصف و `1` برای تمام آیتم. آیتم بزرگ‌تر از محدودهٔ دید ممکن است هرگز به مقدار یک نرسد.
67
-
68
- اگر بعد از اتصال دارای `revealOnView`، صریحاً `play()` را فراخوانی کنید، زمان‌بندی دستی جای ورود خودکار را می‌گیرد؛ ماسک اولیه تا اولین فریم حفظ می‌شود، اما ورود به دید دیگر افکت را از نو شروع نمی‌کند. برای متن اسلایدر که باید هم‌زمان با اسلاید شروع شود، همین روش مناسب است. متن خارج از دید فقط زمان شروع را نگه می‌دارد و رسم و محاسبات ذرات متوقف می‌شوند؛ با برگشت، وضعیت متناسب با زمان سپری‌شده نمایش داده می‌شود. اگر زمان تمام شده باشد، افکت دوباره اجرا نمی‌شود.
69
-
70
- برای پایان افکت از `await surface.whenFinished()` استفاده کنید؛ پایان گذار به متن بومی را هم در نظر می‌گیرد و خارج از دید نیز تکمیل می‌شود. نتیجه یکی از وضعیت‌های `completed`، `cancelled` و `unsupported` است. برای تشخیص پایان، تایمر ثابت یا آمار رندر را در کد سایت بررسی نکنید. لغو یا تخریب اتصال، انتظار جاری را با وضعیت `cancelled` آزاد می‌کند.
71
-
72
- اگر `play('exit')` را خارج از دید فراخوانی کنید، نمایش بومی همان لحظه مخفی می‌شود؛ اندازه، جای عنصر و محتوای DOM حذف نمی‌شوند. اگر حذف در حال اجرا از دید خارج شود نیز نمایش بومی مخفی می‌ماند. هنگام برگشت، فقط ذرات متناسب با زمان سپری‌شده رسم می‌شوند و اگر حذف تمام شده باشد، آیتم مخفی می‌ماند. `play('enter')` آن را دوباره تشکیل می‌دهد؛ `cancel()` یا `destroy()` نمایش و سبک‌های بومی را بازمی‌گردانند. این رفتار در خود موتور برای متن، تصویر و SVG اعمال می‌شود.
66
+ `threshold` نسبت مساحت قابل مشاهده است: صفر برای اولین تقاطع مثبت، `0.5` برای نصف و `1` برای تمام آیتم. آیتم بزرگ‌تر از محدودهٔ دید ممکن است هرگز به مقدار یک نرسد.
67
+
68
+ اگر بعد از اتصال دارای `revealOnView`، صریحاً `play()` را فراخوانی کنید، زمان‌بندی دستی جای ورود خودکار را می‌گیرد؛ ماسک اولیه تا اولین فریم حفظ می‌شود، اما ورود به دید دیگر افکت را از نو شروع نمی‌کند. برای متن اسلایدر که باید هم‌زمان با اسلاید شروع شود، همین روش مناسب است. متن خارج از دید فقط زمان شروع را نگه می‌دارد و رسم و محاسبات ذرات متوقف می‌شوند؛ با برگشت، وضعیت متناسب با زمان سپری‌شده نمایش داده می‌شود. اگر زمان تمام شده باشد، افکت دوباره اجرا نمی‌شود.
69
+
70
+ برای پایان افکت از `await surface.whenFinished()` استفاده کنید؛ پایان گذار به متن بومی را هم در نظر می‌گیرد و خارج از دید نیز تکمیل می‌شود. نتیجه یکی از وضعیت‌های `completed`، `cancelled` و `unsupported` است. برای تشخیص پایان، تایمر ثابت یا آمار رندر را در کد سایت بررسی نکنید. لغو یا تخریب اتصال، انتظار جاری را با وضعیت `cancelled` آزاد می‌کند.
71
+
72
+ اگر `play('exit')` را خارج از دید فراخوانی کنید، نمایش بومی همان لحظه مخفی می‌شود؛ اندازه، جای عنصر و محتوای DOM حذف نمی‌شوند. اگر حذف در حال اجرا از دید خارج شود نیز نمایش بومی مخفی می‌ماند. هنگام برگشت، فقط ذرات متناسب با زمان سپری‌شده رسم می‌شوند و اگر حذف تمام شده باشد، آیتم مخفی می‌ماند. `play('enter')` آن را دوباره تشکیل می‌دهد؛ `cancel()` یا `destroy()` نمایش و سبک‌های بومی را بازمی‌گردانند. این رفتار در خود موتور برای متن، تصویر و SVG اعمال می‌شود.
73
73
 
74
74
  ### محل canvas و لایه‌ها
75
75
 
@@ -83,19 +83,19 @@ const api = await loadFree({THREE, auto: true});
83
83
 
84
84
  loader خودکار هنگام رفتن صفحه به حافظهٔ Back/Forward مرورگر، اتصال را نگه می‌دارد و هنگام بازگشت موقعیتش را تازه می‌کند؛ ورودهای یک‌باره دوباره ساخته نمی‌شوند. خروج واقعی صفحه منابع را آزاد می‌کند. اگر اتصال را خودتان با `api.create()` یا `createFree()` ساخته‌اید، مدیریت عمر آن هم با شماست: روی `pagehide` فقط در صورت `event.persisted === false` آن را آزاد کنید؛ در بازگشتِ persisted، `refresh()` کافی است. اتصال عمداً destroyشده خودکار زنده نمی‌شود. پاک‌سازی هنگام unmount واقعی همچنان لازم است.
85
85
 
86
- ### آماده‌سازی و مصرف پردازش
87
-
88
- `surface.ready` نتیجهٔ آماده‌سازی است، نه پایان نصب موتور؛ برای متن یا SVG پایین صفحه ممکن است تا نزدیک‌شدن به دید منتظر بماند. فعال‌شدن دکمه‌های کل صفحه را به `ready` همهٔ آیتم‌ها وابسته نکنید. پس از ساخت اتصال می‌توانید `play()` را صدا بزنید و پایان اجرای درخواست‌شده را با `whenFinished()` بگیرید.
86
+ ### آماده‌سازی و مصرف پردازش
87
+
88
+ `surface.ready` نتیجهٔ آماده‌سازی است، نه پایان نصب موتور؛ برای متن یا SVG پایین صفحه ممکن است تا نزدیک‌شدن به دید منتظر بماند. فعال‌شدن دکمه‌های کل صفحه را به `ready` همهٔ آیتم‌ها وابسته نکنید. پس از ساخت اتصال می‌توانید `play()` را صدا بزنید و پایان اجرای درخواست‌شده را با `whenFinished()` بگیرید.
89
89
 
90
90
  برای تصویر خارج از دید یا با اندازهٔ صفر، `ready` ممکن است با وضعیت موقت بومی و دلیل `Image not visible` تمام شود؛ این به معنی آماده‌بودن مش روی GPU نیست. آماده‌سازی تصویر از نزدیکی صفحه، حدود نصف ارتفاع viewport جلوتر، آغاز می‌شود. بارگیری شبکهٔ خود `img` همچنان تابع مرورگر است. هنگام resize سریع، مش قبلی برای مدت کوتاه با کادر حرکت می‌کند و برش و گوشه‌های نهایی پس از تجمیع تغییرات بازسازی می‌شوند؛ ساعت افکت از ابتدا شروع نمی‌شود.
91
91
 
92
92
  متن ثابت از چیدمان معتبر و پیکسل‌های کش‌شده استفاده می‌کند. سقف کش مشترک پیکسل‌ها ۱۶MiB است؛ این سقف کل حافظهٔ صفحه یا GPU نیست. بارگیری فونت کش مرتبط را تازه می‌کند. متن پشتیبانی‌نشده بومی نمایش داده می‌شود و موتور روی همان خطای معلوم مدام تلاش نمی‌کند؛ پس از اصلاح سبک، `refresh()` امکان تلاش مجدد را می‌دهد.
93
93
 
94
- ### مشخصات نسخه
95
-
96
- برای پایان افکت از `await surface.whenFinished()` استفاده کنید؛ نتیجه `completed`، `cancelled` یا `unsupported` است و پایان تبدیل مش به نمایش بومی را هم لحاظ می‌کند. چند فراخوانی هم‌زمان یک انتظار مشترک دارند. اجرای جدید، انتظار اجرای قبلی را لغو می‌کند؛ `cancel()`، `destroy()` و جداشدن عنصر از سند نیز انتظار را آزاد می‌کنند. انتظار ورود خودکار تا اولین intersection محدود به زمان آماده‌سازی نیست.
97
-
98
- متن، تصویر و SVG خارج دید ساعت افکت را با پردازش کم حفظ می‌کنند؛ ورود مجدد افکت را از ابتدا شروع نمی‌کند. هنگام درخواست محو خارج دید، نمایش بومی همان لحظه مخفی می‌شود. در اسلایدر، متن و تصویر بعدی را تنها پس از موفقیت تعویض نهایی کنید. برای متن بعدی عنصر تازه بسازید؛ عنصر متصل به موتور ممکن است سبک یا ویژگی موقت داشته باشد و نباید همان حالت زنده را clone کرد.
94
+ ### مشخصات نسخه
95
+
96
+ برای پایان افکت از `await surface.whenFinished()` استفاده کنید؛ نتیجه `completed`، `cancelled` یا `unsupported` است و پایان تبدیل مش به نمایش بومی را هم لحاظ می‌کند. چند فراخوانی هم‌زمان یک انتظار مشترک دارند. اجرای جدید، انتظار اجرای قبلی را لغو می‌کند؛ `cancel()`، `destroy()` و جداشدن عنصر از سند نیز انتظار را آزاد می‌کنند. انتظار ورود خودکار تا اولین intersection محدود به زمان آماده‌سازی نیست.
97
+
98
+ متن، تصویر و SVG خارج دید ساعت افکت را با پردازش کم حفظ می‌کنند؛ ورود مجدد افکت را از ابتدا شروع نمی‌کند. هنگام درخواست محو خارج دید، نمایش بومی همان لحظه مخفی می‌شود. در اسلایدر، متن و تصویر بعدی را تنها پس از موفقیت تعویض نهایی کنید. برای متن بعدی عنصر تازه بسازید؛ عنصر متصل به موتور ممکن است سبک یا ویژگی موقت داشته باشد و نباید همان حالت زنده را clone کرد.
99
99
 
100
100
  - متن: ورود باد، خروج دود. تصویر/SVG: ورود برف، خروج ذوب.
101
101
  - مدت۲ ثانیه، ذرات مثلثی، سکون بومی، شکل‌گیری دیرتر برای نمایش‌دهنده‌ها.
package/README.md CHANGED
@@ -1,14 +1,15 @@
1
- <p align="center"><img src="https://raw.githubusercontent.com/kbaghini/evry-fx/main/docs/assets/cover.svg" alt="EV-RY FX — Motion for the text and images already on your page." width="100%"></p>
1
+ <p align="center"><a href="https://ev-ry.com/fx/"><img src="https://raw.githubusercontent.com/kbaghini/evry-fx/main/docs/assets/cover.svg" alt="EV-RY FX Free visit the official FX website." width="100%"></a></p>
2
2
 
3
3
  <h1 align="center">EV-RY FX</h1>
4
4
 
5
5
  <p align="center"><strong>Your HTML. Four particle effects. Native when still.</strong></p>
6
6
 
7
- <p align="center">Free edition · 0.1.0-rc.3 preview · <a href="https://github.com/kbaghini/evry-fx/blob/main/LICENSE">MIT licensed</a> · JavaScript + TypeScript declarations</p>
7
+ <p align="center">Free edition · 0.1.0-rc.4 preview · <a href="https://github.com/kbaghini/evry-fx/blob/main/LICENSE">MIT licensed</a> · JavaScript + TypeScript declarations</p>
8
8
 
9
- <p align="center">
10
- <a href="#quick-start">Quick start</a> ·
11
- <a href="https://kbaghini.github.io/evry-fx/docs/">Live demo</a> ·
9
+ <p align="center">
10
+ <a href="https://ev-ry.com/fx/">Official FX website ↗</a> ·
11
+ <a href="https://kbaghini.github.io/evry-fx/docs/">See FX Free in action ↗</a> ·
12
+ <a href="#quick-start">Quick start</a> ·
12
13
  <a href="https://github.com/kbaghini/evry-fx/blob/main/docs/GUIDE.md">Guide</a> ·
13
14
  <a href="https://github.com/kbaghini/evry-fx/blob/main/QUICKSTART.fa.md">راهنمای فارسی</a>
14
15
  </p>
@@ -21,7 +22,7 @@ Start with automatic scroll reveals, or attach selected elements through a small
21
22
 
22
23
  ![EV-RY FX motion preview](https://raw.githubusercontent.com/kbaghini/evry-fx/main/docs/assets/thd-preview.gif)
23
24
 
24
- The README shows an animated preview. Open the [live interactive demo](https://kbaghini.github.io/evry-fx/docs/) to try entry and exit effects on real text and images.
25
+ The README shows an animated preview. Open the [live interactive Free demo](https://kbaghini.github.io/evry-fx/docs/) to try the four fixed effects on real text and images. [Other FX editions](https://ev-ry.com/fx/) are separate from this MIT-licensed package.
25
26
 
26
27
  ## What you get
27
28
 
@@ -38,7 +39,7 @@ The README shows an animated preview. Open the [live interactive demo](https://k
38
39
 
39
40
  ## Quick start
40
41
 
41
- **Public preview: 0.1.0-rc.3.** Validate the supported content and layouts in your project before production use.
42
+ **Public preview: 0.1.0-rc.4.** Validate the supported content and layouts in your project before production use.
42
43
 
43
44
  Install from your project folder:
44
45
 
@@ -117,4 +118,4 @@ EV-RY FX Free is [MIT licensed](https://github.com/kbaghini/evry-fx/blob/main/LI
117
118
 
118
119
  ## Real integration: EV-RY website
119
120
 
120
- [See the EV-RY product-showcase integration](examples/evry-website.md): alternating snow/melt image transitions, animated captions and persistent-engine navigation. Includes initial-reveal and lifecycle guidance; the full website is currently a local integration.
121
+ [See the EV-RY product-showcase integration](examples/evry-website.md): alternating snow/melt image transitions, animated captions and persistent-engine navigation. This is an integration recipe; the [public FX page](https://ev-ry.com/fx/) may use features beyond the four-effect Free demo.
package/build-report.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.1.0-rc.3",
2
+ "version": "0.1.0-rc.4",
3
3
  "effects": [
4
4
  "dust-wind",
5
5
  "smoke",
@@ -14,8 +14,8 @@
14
14
  },
15
15
  {
16
16
  "file": "src/dom-free.js",
17
- "bytes": 5191,
18
- "gzip": 1910
17
+ "bytes": 5268,
18
+ "gzip": 1952
19
19
  },
20
20
  {
21
21
  "file": "src/dom-attachment.js",
@@ -34,8 +34,8 @@
34
34
  },
35
35
  {
36
36
  "file": "src/dom-image-surface.js",
37
- "bytes": 14775,
38
- "gzip": 4711
37
+ "bytes": 15284,
38
+ "gzip": 4834
39
39
  },
40
40
  {
41
41
  "file": "src/image-surface.js",
@@ -54,13 +54,13 @@
54
54
  },
55
55
  {
56
56
  "file": "src/raster-texture-mesh.js",
57
- "bytes": 2592,
58
- "gzip": 1150
57
+ "bytes": 2627,
58
+ "gzip": 1159
59
59
  },
60
60
  {
61
61
  "file": "src/raster-texture-material.js",
62
- "bytes": 4981,
63
- "gzip": 1903
62
+ "bytes": 5060,
63
+ "gzip": 1914
64
64
  },
65
65
  {
66
66
  "file": "src/text-mesh-density.js",
@@ -94,8 +94,8 @@
94
94
  },
95
95
  {
96
96
  "file": "src/triangle-effect.js",
97
- "bytes": 13758,
98
- "gzip": 4313
97
+ "bytes": 13953,
98
+ "gzip": 4324
99
99
  },
100
100
  {
101
101
  "file": "src/particle-centers.js",
@@ -104,13 +104,13 @@
104
104
  },
105
105
  {
106
106
  "file": "src/text-edit-motions.js",
107
- "bytes": 2068,
108
- "gzip": 1035
107
+ "bytes": 2083,
108
+ "gzip": 1045
109
109
  },
110
110
  {
111
111
  "file": "src/text-motion-recipes.js",
112
- "bytes": 4883,
113
- "gzip": 1895
112
+ "bytes": 4954,
113
+ "gzip": 1907
114
114
  },
115
115
  {
116
116
  "file": "src/text-motion-programs.js",
@@ -119,18 +119,18 @@
119
119
  },
120
120
  {
121
121
  "file": "src/text-effect-options.js",
122
- "bytes": 2309,
123
- "gzip": 1052
122
+ "bytes": 2337,
123
+ "gzip": 1055
124
124
  },
125
125
  {
126
126
  "file": "src/text-effect-path.js",
127
- "bytes": 2924,
128
- "gzip": 1132
127
+ "bytes": 2985,
128
+ "gzip": 1141
129
129
  },
130
130
  {
131
131
  "file": "src/text-motion-primitives.js",
132
- "bytes": 4764,
133
- "gzip": 2022
132
+ "bytes": 4862,
133
+ "gzip": 2031
134
134
  },
135
135
  {
136
136
  "file": "src/text-motion-contour.js",
@@ -154,8 +154,8 @@
154
154
  },
155
155
  {
156
156
  "file": "src/dom-image-swap.js",
157
- "bytes": 3310,
158
- "gzip": 1316
157
+ "bytes": 3722,
158
+ "gzip": 1441
159
159
  },
160
160
  {
161
161
  "file": "src/dom-once.js",
@@ -179,8 +179,8 @@
179
179
  },
180
180
  {
181
181
  "file": "src/dom-text-surface.js",
182
- "bytes": 22552,
183
- "gzip": 7092
182
+ "bytes": 22605,
183
+ "gzip": 7056
184
184
  },
185
185
  {
186
186
  "file": "src/hybrid-text-flow.js",
@@ -189,13 +189,13 @@
189
189
  },
190
190
  {
191
191
  "file": "src/runtime-font-engine.js",
192
- "bytes": 12202,
193
- "gzip": 3758
192
+ "bytes": 12245,
193
+ "gzip": 3731
194
194
  },
195
195
  {
196
196
  "file": "src/font-rasterizer.js",
197
- "bytes": 4384,
198
- "gzip": 1544
197
+ "bytes": 4404,
198
+ "gzip": 1531
199
199
  },
200
200
  {
201
201
  "file": "src/native-run-shaping.js",
@@ -214,13 +214,13 @@
214
214
  },
215
215
  {
216
216
  "file": "src/text-edit-effect.js",
217
- "bytes": 7704,
218
- "gzip": 2580
217
+ "bytes": 7805,
218
+ "gzip": 2590
219
219
  },
220
220
  {
221
221
  "file": "src/insertion-range.js",
222
- "bytes": 1858,
223
- "gzip": 667
222
+ "bytes": 1887,
223
+ "gzip": 675
224
224
  },
225
225
  {
226
226
  "file": "src/text-motion-character-centers.js",
@@ -239,8 +239,8 @@
239
239
  },
240
240
  {
241
241
  "file": "src/dom-raster-cache.js",
242
- "bytes": 1677,
243
- "gzip": 793
242
+ "bytes": 1710,
243
+ "gzip": 800
244
244
  },
245
245
  {
246
246
  "file": "src/dom-rich-text.js",
@@ -274,8 +274,8 @@
274
274
  },
275
275
  {
276
276
  "file": "src/dom-free-script.js",
277
- "bytes": 584,
278
- "gzip": 357
277
+ "bytes": 760,
278
+ "gzip": 446
279
279
  },
280
280
  {
281
281
  "file": "src/dom-free-bootstrap.js",
@@ -289,8 +289,8 @@
289
289
  },
290
290
  {
291
291
  "file": "src/dom-free-loader.js",
292
- "bytes": 593,
293
- "gzip": 361
292
+ "bytes": 761,
293
+ "gzip": 448
294
294
  },
295
295
  {
296
296
  "file": "src/dom-free-loader.d.ts",
@@ -309,8 +309,8 @@
309
309
  },
310
310
  {
311
311
  "file": "src/dom-attachment.d.ts",
312
- "bytes": 4537,
313
- "gzip": 1404
312
+ "bytes": 4609,
313
+ "gzip": 1410
314
314
  },
315
315
  {
316
316
  "file": "assets/vendor/three-LICENSE.txt",
@@ -328,6 +328,6 @@
328
328
  "gzip": 1971
329
329
  }
330
330
  ],
331
- "bytes": 974292,
332
- "gzipSum": 280473
333
- }
331
+ "bytes": 976567,
332
+ "gzipSum": 280968
333
+ }
@@ -1,15 +1,25 @@
1
- # EV-RY FX Free 0.1.0-rc.3
1
+ # EV-RY FX Free 0.1.0-rc.4
2
+
3
+ - Failed classic/module initialization can be retried after a dependency-loading error; successful first initialization remains shared.
4
+ - Cancelling an image swap settles promptly even if image decoding stalls. A late job cannot roll back host changes twice.
5
+ - Image cleanup preserves an inline opacity change made by the host while attached.
6
+ - The Free package retains the verified four-preset runtime from rc.3; no private Studio/Pro features were imported from the shared development tree.
7
+ - Documentation links the official [FX page](https://ev-ry.com/fx/) and keeps the [four-effect Free demo](https://kbaghini.github.io/evry-fx/docs/) distinct.
8
+
9
+ Validation covers a clean tarball install, Chrome desktop/mobile-layout/reduced-motion scenarios, loader retry and lifecycle checks. It does not certify physical devices, all SVG/CORS cases or production-site performance.
2
10
 
3
- - Cancel/update no longer starts a fresh text handoff; invalid play phases leave automatic reveal intact, and offscreen no-effect calls complete immediately.
4
- - Image/SVG source refresh preserves the active effect clock, seed and settled exit mask. SVG snapshot errors retain native fallback diagnostics.
5
- - SVG native pixels now appear below the settled mesh during the same 250ms handoff as images.
6
- - Cancelling an image swap restores the incoming image's original location, including removal when it was initially detached.
7
- - Completion waits share one pending poller, cancel promptly on superseding play or owner disposal, and do not time out untouched intersection reveals.
8
- - Public whenFinished() for completion, cancellation and unsupported rendering.
9
- - Offscreen text preserves its effect clock without particle updates or drawing; plain/rich text resumes at elapsed time and completion no longer waits for viewport entry.
10
- - Explicit play takes ownership from automatic reveal without dropping the initial mask or restarting on intersection. Existing automatic reveal behavior remains in effect until explicit play.
11
- - Offscreen exits suppress native text/image/SVG paint immediately and retain it through reentry and completion; cancellation and disposal restore original styles. Regression covers actual departure shader clocks, seeds, coordinates and rendered smoke pixels.
12
- - Transient effects and image swaps complete on their original offscreen timeline without waiting for visual readiness; hidden transient polling is infrequent and cancellation still restores native content.
11
+ # EV-RY FX Free 0.1.0-rc.3
12
+
13
+ - Cancel/update no longer starts a fresh text handoff; invalid play phases leave automatic reveal intact, and offscreen no-effect calls complete immediately.
14
+ - Image/SVG source refresh preserves the active effect clock, seed and settled exit mask. SVG snapshot errors retain native fallback diagnostics.
15
+ - SVG native pixels now appear below the settled mesh during the same 250ms handoff as images.
16
+ - Cancelling an image swap restores the incoming image's original location, including removal when it was initially detached.
17
+ - Completion waits share one pending poller, cancel promptly on superseding play or owner disposal, and do not time out untouched intersection reveals.
18
+ - Public whenFinished() for completion, cancellation and unsupported rendering.
19
+ - Offscreen text preserves its effect clock without particle updates or drawing; plain/rich text resumes at elapsed time and completion no longer waits for viewport entry.
20
+ - Explicit play takes ownership from automatic reveal without dropping the initial mask or restarting on intersection. Existing automatic reveal behavior remains in effect until explicit play.
21
+ - Offscreen exits suppress native text/image/SVG paint immediately and retain it through reentry and completion; cancellation and disposal restore original styles. Regression covers actual departure shader clocks, seeds, coordinates and rendered smoke pixels.
22
+ - Transient effects and image swaps complete on their original offscreen timeline without waiting for visual readiness; hidden transient polling is infrequent and cancellation still restores native content.
13
23
  - Images reveal native pixels at assembly completion, then fade the mesh for 250ms, including swaps.
14
24
 
15
25
  - Reuse local rendering buffers across differently sized surfaces, avoiding repeated GPU buffer allocation.
@@ -2,7 +2,7 @@
2
2
 
3
3
  The EV-RY marketing website is a real integration case: a four-product showcase, animated captions, one shared FX installation across client-side navigation, and native content at rest.
4
4
 
5
- The website is currently a local integration at `http://127.0.0.1:8780/`, not a hosted demo included in this package. The public runnable examples are linked from the package README. The website backend, forms and artwork are not dependencies of FX.
5
+ The [EV-RY website](https://ev-ry.com/) and [FX product page](https://ev-ry.com/fx/) are public. This file describes an integration pattern, not a copy of the deployed website or a Free-only live demo. Try the package's separate [interactive Free demo](https://kbaghini.github.io/evry-fx/docs/) for its four fixed effects. The website backend, forms and artwork are not dependencies of FX.
6
6
 
7
7
  ## Initial reveal without a flash
8
8
 
@@ -13,17 +13,17 @@ const imageSurface = engine.attachImage(image, {
13
13
  presentation: 'global',
14
14
  revealOnView: { threshold: 0, once: true }
15
15
  });
16
- const captionSurfaces = captionLines.map(line => {
17
- const surface = engine.attachText(line, {
18
- presentation: 'local',
19
- revealOnView: { threshold: 0, once: true }
20
- });
21
- surface.play('enter');
22
- return surface;
23
- });
24
- ```
25
-
26
- The captions explicitly start with the slide, even when below the viewport. `play()` takes control from automatic intersection reveal while retaining its initial paint mask until a rendered frame. It does not wait for visibility or restart on reentry. Without explicit `play()`, `revealOnView` continues to wait for the configured intersection and follows its `once` setting.
16
+ const captionSurfaces = captionLines.map(line => {
17
+ const surface = engine.attachText(line, {
18
+ presentation: 'local',
19
+ revealOnView: { threshold: 0, once: true }
20
+ });
21
+ surface.play('enter');
22
+ return surface;
23
+ });
24
+ ```
25
+
26
+ The captions explicitly start with the slide, even when below the viewport. `play()` takes control from automatic intersection reveal while retaining its initial paint mask until a rendered frame. It does not wait for visibility or restart on reentry. Without explicit `play()`, `revealOnView` continues to wait for the configured intersection and follows its `once` setting.
27
27
 
28
28
  ## Alternate two image transitions
29
29
 
@@ -41,18 +41,18 @@ const result = await transition.finished;
41
41
  if (result.status === 'completed') previous.remove();
42
42
  ```
43
43
 
44
- Use a busy flag to prevent overlapping swaps. Pause scheduling while the document is hidden. On navigation, cancel an outstanding transition, clear the scheduled timeout and destroy page handles; retain the shared engine and refresh its automatic attachments after inserting the new page. Install the boot mask before the new DOM can paint. Destroy the engine only when the application is disposed.
44
+ Use a busy flag to prevent overlapping swaps. Pause scheduling while the document is hidden. On navigation, cancel an outstanding transition, clear the scheduled timeout and destroy page handles; retain the shared engine and refresh its automatic attachments after inserting the new page. Install the boot mask before the new DOM can paint. Destroy the engine only when the application is disposed.
45
+
46
+ The five-second scheduling interval, caption layout, routing and product artwork belong to the website, not to the FX API. Local caption surfaces share rendering infrastructure; the retained scratch buffer avoids resizing the GPU buffer for each caption line.
45
47
 
46
- The five-second scheduling interval, caption layout, routing and product artwork belong to the website, not to the FX API. Local caption surfaces share rendering infrastructure; the retained scratch buffer avoids resizing the GPU buffer for each caption line.
47
-
48
- Create incoming captions from fresh authored markup rather than cloning a currently attached element: a live attachment can carry temporary engine-owned visibility attributes and styles. Commit the incoming image and caption together only after `transition.finished` reports `completed`. If image decoding, attachment or the swap fails, destroy incoming caption handles, remove their layer, retain the previous caption and image, then retry. Track each acquired handle immediately so partial attachment failures can also be cleaned up.
49
-
50
- Schedule one deadline five seconds from each transition start. After completion, wait only for the remaining time. If the transition itself overruns that deadline, start one next transition when available and establish a new deadline; do not discard interval ticks or queue catch-up transitions. Returning from a hidden tab and retrying a failed transition each establish a fresh five-second wait. This keeps start-to-start cadence stable without overlapping jobs.
48
+ Create incoming captions from fresh authored markup rather than cloning a currently attached element: a live attachment can carry temporary engine-owned visibility attributes and styles. Commit the incoming image and caption together only after `transition.finished` reports `completed`. If image decoding, attachment or the swap fails, destroy incoming caption handles, remove their layer, retain the previous caption and image, then retry. Track each acquired handle immediately so partial attachment failures can also be cleaned up.
49
+
50
+ Schedule one deadline five seconds from each transition start. After completion, wait only for the remaining time. If the transition itself overruns that deadline, start one next transition when available and establish a new deadline; do not discard interval ticks or queue catch-up transitions. Returning from a hidden tab and retrying a failed transition each establish a fresh five-second wait. This keeps start-to-start cadence stable without overlapping jobs.
51
51
 
52
52
  ## Completion
53
53
 
54
- After `surface.play()`, await `surface.whenFinished()`. It returns a status of `completed`, `cancelled`, or `unsupported`. Completion includes the native handoff; avoid fixed cleanup timers or renderer statistics. Destroy page surfaces when navigating away.
55
-
56
- Offscreen text and media retain their start time without running per-particle updates or drawing frames. Returning during the effect evaluates its current elapsed time; returning after it ends shows the final state without replay. `whenFinished()` also completes when content remains offscreen, so slider cleanup never depends on scrolling captions into view. It checks the suspended clock infrequently instead of maintaining a render loop. Concurrent waits share a pending promise; starting a new play cancels the previous wait. Cancel or destroy the handle to release an outstanding wait.
57
-
58
- When an exit is requested offscreen, the engine immediately suppresses native paint while retaining layout and the DOM content. Native paint also remains hidden if an active departure leaves view. Reentry renders only the remaining departure particles; an expired exit stays hidden. Text, image and SVG attachments own this masking, so the site should not toggle native opacity or visibility to emulate it. Cancel/destroy restores the original presentation.
54
+ After `surface.play()`, await `surface.whenFinished()`. It returns a status of `completed`, `cancelled`, or `unsupported`. Completion includes the native handoff; avoid fixed cleanup timers or renderer statistics. Destroy page surfaces when navigating away.
55
+
56
+ Offscreen text and media retain their start time without running per-particle updates or drawing frames. Returning during the effect evaluates its current elapsed time; returning after it ends shows the final state without replay. `whenFinished()` also completes when content remains offscreen, so slider cleanup never depends on scrolling captions into view. It checks the suspended clock infrequently instead of maintaining a render loop. Concurrent waits share a pending promise; starting a new play cancels the previous wait. Cancel or destroy the handle to release an outstanding wait.
57
+
58
+ When an exit is requested offscreen, the engine immediately suppresses native paint while retaining layout and the DOM content. Native paint also remains hidden if an active departure leaves view. Reentry renders only the remaining departure particles; an expired exit stays hidden. Text, image and SVG attachments own this masking, so the site should not toggle native opacity or visibility to emulate it. Cancel/destroy restores the original presentation.
package/package.json CHANGED
@@ -1,57 +1,57 @@
1
- {
2
- "name": "@ev-ry/fx",
3
- "version": "0.1.0-rc.3",
4
- "private": false,
5
- "type": "module",
6
- "exports": {
7
- ".": {
8
- "types": "./src/dom-free.d.ts",
9
- "import": "./src/dom-free.js"
10
- },
11
- "./script": {
12
- "types": "./src/dom-free-loader.d.ts",
13
- "import": "./src/dom-free-loader.js"
14
- },
15
- "./classic-script": "./src/dom-free-script.js"
16
- },
17
- "files": [
18
- "src",
19
- "assets",
20
- "examples",
21
- "README.md",
22
- "LICENSE",
23
- "NOTICE.md",
24
- "QUICKSTART.fa.md",
25
- "docs/GUIDE.md",
26
- "docs/RELEASE-NOTES.md",
27
- "build-report.json"
28
- ],
29
- "description": "Textured particle effects for existing HTML text, images and SVG. Native when still.",
30
- "license": "MIT",
31
- "author": {
32
- "name": "Kamran Baghini",
33
- "url": "https://ev-ry.com"
34
- },
35
- "keywords": [
36
- "animation",
37
- "particles",
38
- "webgl",
39
- "text-effects",
40
- "image-effects",
41
- "scroll-reveal",
42
- "svg",
43
- "rtl",
44
- "ev-ry"
45
- ],
46
- "publishConfig": {
47
- "access": "public"
48
- },
49
- "repository": {
50
- "type": "git",
51
- "url": "git+https://github.com/kbaghini/evry-fx.git"
52
- },
53
- "bugs": {
54
- "url": "https://github.com/kbaghini/evry-fx/issues"
55
- },
56
- "homepage": "https://kbaghini.github.io/evry-fx/docs/"
57
- }
1
+ {
2
+ "name": "@ev-ry/fx",
3
+ "version": "0.1.0-rc.4",
4
+ "private": false,
5
+ "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./src/dom-free.d.ts",
9
+ "import": "./src/dom-free.js"
10
+ },
11
+ "./script": {
12
+ "types": "./src/dom-free-loader.d.ts",
13
+ "import": "./src/dom-free-loader.js"
14
+ },
15
+ "./classic-script": "./src/dom-free-script.js"
16
+ },
17
+ "files": [
18
+ "src",
19
+ "assets",
20
+ "examples",
21
+ "README.md",
22
+ "LICENSE",
23
+ "NOTICE.md",
24
+ "QUICKSTART.fa.md",
25
+ "docs/GUIDE.md",
26
+ "docs/RELEASE-NOTES.md",
27
+ "build-report.json"
28
+ ],
29
+ "description": "Textured particle effects for existing HTML text, images and SVG. Native when still.",
30
+ "license": "MIT",
31
+ "author": {
32
+ "name": "Kamran Baghini",
33
+ "url": "https://ev-ry.com"
34
+ },
35
+ "keywords": [
36
+ "animation",
37
+ "particles",
38
+ "webgl",
39
+ "text-effects",
40
+ "image-effects",
41
+ "scroll-reveal",
42
+ "svg",
43
+ "rtl",
44
+ "ev-ry"
45
+ ],
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "repository": {
50
+ "type": "git",
51
+ "url": "git+https://github.com/kbaghini/evry-fx.git"
52
+ },
53
+ "bugs": {
54
+ "url": "https://github.com/kbaghini/evry-fx/issues"
55
+ },
56
+ "homepage": "https://ev-ry.com/fx/"
57
+ }