@markdy/astro 0.3.0 → 0.5.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 +19 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markdy/astro",
3
- "version": "0.3.0",
3
+ "version": "0.5.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.3.0"
40
+ "@markdy/renderer-dom": "0.5.1"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "astro": ">=4.0.0"
package/src/Markdy.astro CHANGED
@@ -36,6 +36,10 @@ export interface Props {
36
36
  assets?: Record<string, string>;
37
37
  /** Start playing as soon as the scene is hydrated. Defaults to true. */
38
38
  autoplay?: boolean;
39
+ /** Loop the animation when it ends. Defaults to true. */
40
+ loop?: boolean;
41
+ /** Show a small "Powered by Markdy" badge below the animation. Defaults to true. */
42
+ copyright?: boolean;
39
43
  class?: string;
40
44
  /**
41
45
  * Short human-readable title for the animation.
@@ -57,6 +61,8 @@ const {
57
61
  bg = "white",
58
62
  assets = {},
59
63
  autoplay = true,
64
+ loop = true,
65
+ copyright = true,
60
66
  class: className,
61
67
  title = "Markdy animation",
62
68
  description,
@@ -68,10 +74,12 @@ const {
68
74
  data-markdy-code={code}
69
75
  data-markdy-assets={JSON.stringify(assets)}
70
76
  data-markdy-autoplay={String(autoplay)}
77
+ data-markdy-loop={String(loop)}
78
+ data-markdy-copyright={String(copyright)}
71
79
  role="img"
72
80
  aria-label={title}
73
81
  aria-busy="true"
74
- style={`width:${width}px;height:${height}px;overflow:hidden`}
82
+ style={`max-width:${width}px;width:100%;aspect-ratio:${width}/${height};overflow:hidden`}
75
83
  >
76
84
  <!--
77
85
  SSR placeholder: keeps layout stable before the island hydrates.
@@ -82,7 +90,7 @@ const {
82
90
  <div
83
91
  class="markdy-placeholder"
84
92
  aria-hidden="true"
85
- style={`width:${width}px;height:${height}px;background:${bg};display:flex;align-items:center;justify-content:center`}
93
+ style={`width:100%;height:100%;background:${bg};display:flex;align-items:center;justify-content:center`}
86
94
  >
87
95
  <span
88
96
  style="font-family:sans-serif;font-size:12px;color:#bbb;letter-spacing:0.05em"
@@ -98,7 +106,7 @@ const {
98
106
  -->
99
107
  <noscript>
100
108
  <div
101
- style={`width:${width}px;height:${height}px;background:${bg};display:flex;align-items:center;justify-content:center`}
109
+ style={`width:100%;height:100%;background:${bg};display:flex;align-items:center;justify-content:center`}
102
110
  >
103
111
  <p
104
112
  style="font-family:sans-serif;font-size:14px;color:#888;text-align:center;padding:1rem;margin:0"
@@ -130,6 +138,8 @@ const {
130
138
  }
131
139
 
132
140
  const autoplay = el.dataset.markdyAutoplay !== "false";
141
+ const loop = el.dataset.markdyLoop !== "false";
142
+ const copyright = el.dataset.markdyCopyright !== "false";
133
143
 
134
144
  // Code-split: renderer-dom is NOT part of the initial page bundle.
135
145
  const { createPlayer } = await import("@markdy/renderer-dom");
@@ -137,9 +147,8 @@ const {
137
147
  // Clear the SSR placeholder and mount the canvas atomically after the
138
148
  // async import resolves, so there is no flash of empty content.
139
149
  el.innerHTML = "";
140
- el.style.overflow = "visible";
141
150
 
142
- createPlayer({ container: el, code, assets, autoplay });
151
+ createPlayer({ container: el, code, assets, autoplay, loop, copyright });
143
152
 
144
153
  el.dataset.markdyInit = "done";
145
154
  el.removeAttribute("aria-busy");
@@ -169,9 +178,10 @@ const {
169
178
  }
170
179
 
171
180
  // ── Intersection observer ────────────────────────────────────────────────
172
- // Observe every unhydrated .markdy-root element and hydrate it when it
173
- // enters the viewport (100 px root margin so the scene is ready before
174
- // the user actually sees it).
181
+ // Observe every unhydrated .markdy-root element. We use threshold: 1.0
182
+ // so hydration (and autoplay) only triggers once the element's bottom
183
+ // edge is fully inside the viewport the animation is never started
184
+ // while partially cut off.
175
185
 
176
186
  const observer = new IntersectionObserver(
177
187
  (entries) => {
@@ -191,7 +201,7 @@ const {
191
201
  }
192
202
  }
193
203
  },
194
- { rootMargin: "100px" },
204
+ { threshold: 1.0 },
195
205
  );
196
206
 
197
207
  function initAll(): void {