@markdy/astro 0.6.0 → 0.7.1

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.
Files changed (2) hide show
  1. package/package.json +2 -2
  2. package/src/Markdy.astro +43 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markdy/astro",
3
- "version": "0.6.0",
3
+ "version": "0.7.1",
4
4
  "description": "Astro island component for MarkdyScript animations.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -37,7 +37,7 @@
37
37
  "access": "public"
38
38
  },
39
39
  "dependencies": {
40
- "@markdy/renderer-dom": "0.6.0"
40
+ "@markdy/renderer-dom": "0.7.1"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "astro": ">=4.0.0"
package/src/Markdy.astro CHANGED
@@ -94,7 +94,7 @@ const {
94
94
  <div
95
95
  class="markdy-placeholder"
96
96
  aria-hidden="true"
97
- style={`width:100%;height:100%;background:${bg};display:flex;align-items:center;justify-content:center`}
97
+ style={`width:100%;height:100%;background:${bg};display:flex;align-items:center;justify-content:center;cursor:pointer`}
98
98
  >
99
99
  <span
100
100
  style="font-family:sans-serif;font-size:12px;color:#bbb;letter-spacing:0.05em"
@@ -183,10 +183,10 @@ const {
183
183
  }
184
184
 
185
185
  // ── Intersection observer ────────────────────────────────────────────────
186
- // Observe every unhydrated .markdy-root element. We use threshold: 1.0
187
- // so hydration (and autoplay) only triggers once the element's bottom
188
- // edge is fully inside the viewport the animation is never started
189
- // while partially cut off.
186
+ // threshold: 0.25 trigger as soon as a quarter of the element is visible.
187
+ // We intentionally avoid threshold: 1.0 because it is unreliable: on first
188
+ // navigation (fresh link, no F5) the browser may not fire the callback when
189
+ // the element is very close to — but not fully inside — the viewport.
190
190
 
191
191
  const observer = new IntersectionObserver(
192
192
  (entries) => {
@@ -206,15 +206,40 @@ const {
206
206
  }
207
207
  }
208
208
  },
209
- { threshold: 1.0 },
209
+ { threshold: 0.25 },
210
210
  );
211
211
 
212
+ function doHydrate(el: HTMLElement): void {
213
+ observer.unobserve(el);
214
+ el.dataset.markdyInit = "hydrating";
215
+ scheduleHydration(() => {
216
+ hydrate(el).catch(() => {
217
+ el.dataset.markdyInit = "error";
218
+ el.removeAttribute("aria-busy");
219
+ });
220
+ });
221
+ }
222
+
212
223
  function initAll(): void {
213
224
  document
214
225
  .querySelectorAll<HTMLElement>(".markdy-root:not([data-markdy-init])")
215
226
  .forEach((el) => {
216
227
  el.dataset.markdyInit = "pending";
217
- observer.observe(el);
228
+ // Proactively hydrate elements already in the viewport so we never
229
+ // depend on the observer firing for elements visible at page load.
230
+ // This fixes autoplay on first navigation from an external site where
231
+ // IntersectionObserver callbacks may be delayed or skipped.
232
+ const rect = el.getBoundingClientRect();
233
+ const inViewport =
234
+ rect.bottom > 0 &&
235
+ rect.right > 0 &&
236
+ rect.top < (window.innerHeight || document.documentElement.clientHeight) &&
237
+ rect.left < (window.innerWidth || document.documentElement.clientWidth);
238
+ if (inViewport) {
239
+ doHydrate(el);
240
+ } else {
241
+ observer.observe(el);
242
+ }
218
243
  });
219
244
  }
220
245
 
@@ -227,4 +252,15 @@ const {
227
252
 
228
253
  // Re-run after Astro View Transitions / client-side navigation.
229
254
  document.addEventListener("astro:page-load", initAll);
255
+
256
+ // Click on placeholder to play immediately without waiting for full visibility.
257
+ document.addEventListener("click", (e) => {
258
+ const placeholder = (e.target as Element).closest(".markdy-placeholder");
259
+ if (!placeholder) return;
260
+ const root = placeholder.closest<HTMLElement>(".markdy-root");
261
+ if (!root) return;
262
+ const state = root.dataset.markdyInit;
263
+ if (state === "done" || state === "hydrating") return;
264
+ doHydrate(root);
265
+ });
230
266
  </script>