astro-magic-move 0.1.0 → 0.1.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro-magic-move",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Animated code morphing for Astro, powered by Shiki Magic Move. Build-time tokenization, zero-framework client JS, CSS-variable theming.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -34,4 +34,4 @@
34
34
  "shiki": "^3.0.0",
35
35
  "shiki-magic-move": "^1.3.0"
36
36
  }
37
- }
37
+ }
@@ -1,8 +1,8 @@
1
1
  ---
2
- import type { MagicMoveProps } from "./types";
3
- import { cssVarTheme } from "./theme";
4
2
  import { createHighlighter, type HighlighterGeneric } from "shiki";
5
3
  import { codeToKeyedTokens, createMagicMoveMachine } from "shiki-magic-move/core";
4
+ import { cssVarTheme } from "./theme";
5
+ import type { MagicMoveProps } from "./types";
6
6
 
7
7
  interface Props extends MagicMoveProps {}
8
8
 
@@ -29,15 +29,14 @@ if (stepsProp) {
29
29
  } else if (before != null && after != null) {
30
30
  steps = [before, after];
31
31
  } else {
32
- throw new Error(
33
- "[astro-magic-move] Provide either `before` + `after` or `steps` (min 2 items).",
34
- );
32
+ throw new Error("[astro-magic-move] Provide either `before` + `after` or `steps` (min 2 items).");
35
33
  }
36
34
 
37
35
  // Module-level highlighter cache (survives HMR via globalThis)
38
36
  const CACHE_KEY = "__astro_magic_move_hl";
39
37
  type HLCache = Map<string, HighlighterGeneric<string, string>>;
40
- const hlCache: HLCache = ((globalThis as Record<string, unknown>)[CACHE_KEY] ??= new Map()) as HLCache;
38
+ const hlCache: HLCache = ((globalThis as Record<string, unknown>)[CACHE_KEY] ??=
39
+ new Map()) as HLCache;
41
40
 
42
41
  let highlighter = hlCache.get(lang);
43
42
  if (!highlighter) {
@@ -50,8 +49,7 @@ if (!highlighter) {
50
49
 
51
50
  // Build the magic move machine and compile all steps at build time
52
51
  const machine = createMagicMoveMachine(
53
- (code) =>
54
- codeToKeyedTokens(highlighter, code, { lang, theme: "css-variables" }, lineNumbers),
52
+ (code) => codeToKeyedTokens(highlighter, code, { lang, theme: "css-variables" }, lineNumbers),
55
53
  {},
56
54
  );
57
55
 
@@ -105,9 +103,12 @@ const stepsJson = JSON.stringify(compiledSteps);
105
103
  animateContainer: true,
106
104
  });
107
105
 
108
- // replace() for instant initial display (no animation, no empty frame)
109
- this.renderer.replace(this.steps[0]);
110
- this.currentStep = 0;
106
+ if (trigger === "auto") {
107
+ this.currentStep = -1;
108
+ } else {
109
+ this.renderer.replace(this.steps[0]);
110
+ this.currentStep = 0;
111
+ }
111
112
  this.setupTrigger(trigger, threshold);
112
113
  }
113
114
 
@@ -128,9 +129,7 @@ const stepsJson = JSON.stringify(compiledSteps);
128
129
  });
129
130
  break;
130
131
  case "auto":
131
- requestAnimationFrame(() => {
132
- this.animateToStep(1);
133
- });
132
+ requestAnimationFrame(() => this.autoPlay());
134
133
  break;
135
134
  }
136
135
  }
@@ -148,7 +147,17 @@ const stepsJson = JSON.stringify(compiledSteps);
148
147
  this.observer.observe(this);
149
148
  }
150
149
 
151
- private async animateToStep(stepIndex: number) {
150
+ private async autoPlay() {
151
+ const duration = Number(this.dataset.duration ?? 800);
152
+ for (let i = 0; i < this.steps.length; i++) {
153
+ await this.animateToStep(i);
154
+ if (i < this.steps.length - 1) {
155
+ await new Promise((r) => setTimeout(r, duration + 200));
156
+ }
157
+ }
158
+ }
159
+
160
+ private async animateToStep(stepIndex: number) {
152
161
  if (!this.renderer || stepIndex === this.currentStep) return;
153
162
  if (stepIndex < 0 || stepIndex >= this.steps.length) return;
154
163
 
@@ -11,10 +11,11 @@ magic-move {
11
11
  margin: 0;
12
12
  overflow-x: auto;
13
13
  overflow-y: hidden;
14
- padding: 1rem 1.25rem;
15
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
16
- "Liberation Mono", "Courier New", monospace;
17
- font-size: 0.875rem;
14
+ padding: 0.75rem 1rem;
15
+ font-family:
16
+ ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New",
17
+ monospace;
18
+ font-size: clamp(0.75rem, 2vw, 0.875rem);
18
19
  line-height: 1.7;
19
20
  text-align: left;
20
21
  background: var(--shiki-background, #1e1e1e);