@markgrafhq/markgraf-react 0.1.14 → 0.1.16

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
@@ -1,6 +1,6 @@
1
1
  # @markgrafhq/markgraf-react
2
2
 
3
- React hook + component for embedding [markgraf](https://github.com/i-am-the-slime/markgraf) animations. Drives play/pause/seek imperatively and exposes `time`, `currentKeyframe`, and `playing` as reactive state.
3
+ React hook + component for embedding [markgraf](https://github.com/i-am-the-slime/markgraf) animations. Drives play/pause/seek imperatively and exposes `time`, `keyframe`, and `playing` as reactive state.
4
4
 
5
5
  ## Install
6
6
 
@@ -9,30 +9,31 @@ bun add @markgrafhq/markgraf-react
9
9
  # or: npm install @markgrafhq/markgraf-react
10
10
  ```
11
11
 
12
- Also pull in the embed CSS for canvas styling:
12
+ Import the package CSS for player styling:
13
13
 
14
14
  ```js
15
- import "@markgrafhq/markgraf-embed/css";
15
+ import "@markgrafhq/markgraf-react/css";
16
16
  ```
17
17
 
18
18
  ## `<MarkgrafPlayer src=... />`
19
19
 
20
- Headless component renders a `<canvas>` (default) or `<svg>` with the scene drawn directly into it. Bring your own controls.
20
+ Headless component that draws the scene directly into the selected Canvas2D, SVG, or WebGL surface. Bring your own controls.
21
21
 
22
22
  ```jsx
23
23
  import { MarkgrafPlayer } from "@markgrafhq/markgraf-react";
24
24
 
25
25
  const src = `seed 1
26
- keyframe v1 {
27
- +node client "Client"
28
- +node api "API"
29
- +edge client api
30
- client -> api "GET"
26
+ scene v1 {
27
+ + client: Client
28
+ + api: API
29
+ + client -> api
30
+ client ~> api: GET
31
31
  }`;
32
32
 
33
33
  export default function App() {
34
34
  return <MarkgrafPlayer src={src} />;
35
35
  // Or: <MarkgrafPlayer src={src} renderer="svg" />
36
+ // Or: <MarkgrafPlayer src={src} renderer="sdf" />
36
37
  }
37
38
  ```
38
39
 
@@ -84,6 +85,7 @@ export function Player({ src }) {
84
85
 
85
86
  - **`canvas`** (default) — Canvas2D with DPR-aware scaling and label springs. Fastest, best for many tokens.
86
87
  - **`svg`** — Inline SVG. Easier to inspect/style, scales crisply at any zoom, no DPR concerns. No spring labels.
88
+ - **`sdf`** (alias **`webgl`**) — WebGL raymarched 3D rendering; available through `MarkgrafPlayer` only.
87
89
 
88
90
  ## License
89
91
 
@@ -22,8 +22,10 @@
22
22
  overflow: hidden;
23
23
  }
24
24
 
25
- .markgraf-embed canvas[data-mg="stage"] {
25
+ .markgraf-embed canvas[data-mg="stage"],
26
+ .markgraf-embed svg[data-mg="stage"] {
26
27
  width: 100%;
28
+ height: auto;
27
29
  display: block;
28
30
  max-height: var(--mg-max-height, 90svh);
29
31
  object-fit: contain;
@@ -3,6 +3,51 @@
3
3
 
4
4
  import type { FC, MutableRefObject } from "react";
5
5
 
6
+ export type MarkgrafCueKind = "step" | "tokenLine";
7
+ export type MarkgrafPlaybackDirection = "auto" | "forward" | "backward";
8
+
9
+ export interface MarkgrafPlaybackOptions {
10
+ direction?: MarkgrafPlaybackDirection;
11
+ speed?: number;
12
+ duration?: number;
13
+ loop?: boolean;
14
+ stopAt?: MarkgrafCueKind[];
15
+ }
16
+
17
+ export interface MarkgrafCueBase {
18
+ readonly id: string;
19
+ readonly index: number;
20
+ readonly kind: MarkgrafCueKind;
21
+ readonly time: number;
22
+ readonly endTime: number;
23
+ readonly path: readonly string[];
24
+ }
25
+
26
+ export interface MarkgrafStepCue extends MarkgrafCueBase {
27
+ readonly kind: "step";
28
+ readonly name: string;
29
+ }
30
+
31
+ export interface MarkgrafTokenLineCue extends MarkgrafCueBase {
32
+ readonly kind: "tokenLine";
33
+ readonly tokenIndex: number;
34
+ readonly lineIndex: number;
35
+ readonly text: string;
36
+ readonly from: string;
37
+ readonly to: string;
38
+ }
39
+
40
+ export type MarkgrafCue = MarkgrafStepCue | MarkgrafTokenLineCue;
41
+
42
+ export interface MarkgrafCompleteEvent {
43
+ readonly reason: "target" | "boundary" | string;
44
+ readonly direction: "forward" | "backward";
45
+ readonly targetId: string;
46
+ readonly targetStep: string;
47
+ readonly reached: boolean;
48
+ readonly time: number;
49
+ }
50
+
6
51
  /**
7
52
  * Reactive view of a mounted markgraf player. `time`, `keyframe`, and
8
53
  * `playing` update on every animation frame; the imperative methods are
@@ -27,21 +72,25 @@ export interface MarkgrafApi<E extends Element = HTMLCanvasElement> {
27
72
  readonly duration: number;
28
73
  /** `true` once parse + layout + first render have completed. */
29
74
  readonly ready: boolean;
30
- play(): void;
75
+ readonly cues: readonly MarkgrafCue[];
76
+ readonly steps: readonly MarkgrafStepCue[];
77
+ play(options?: MarkgrafPlaybackOptions): void;
78
+ playWith(options?: MarkgrafPlaybackOptions): void;
31
79
  pause(): void;
32
80
  toggle(): void;
33
81
  /** Clamped to `[0, duration]`. Pauses the player. */
34
82
  seek(seconds: number): void;
83
+ seekCue(cueId: string): void;
84
+ seekStep(stepName: string): void;
85
+ playToCue(cueId: string, options?: MarkgrafPlaybackOptions): void;
86
+ playToStep(stepName: string, options?: MarkgrafPlaybackOptions): void;
87
+ playNext(options?: MarkgrafPlaybackOptions): void;
88
+ playPrevious(options?: MarkgrafPlaybackOptions): void;
35
89
  /** `1.0` is normal playback speed. */
36
90
  setSpeed(speed: number): void;
37
- /**
38
- * Register a callback that fires every time the player enters the named
39
- * keyframe. Fires immediately if already in that frame. Returns an
40
- * unsubscribe function.
41
- */
42
- onFrameEnter(frameName: string, callback: () => void): () => void;
43
- /** Seek to the start of the named keyframe. No-op if the frame doesn't exist. */
44
- seekFrame(frameName: string): void;
91
+ onCueEnter(callback: (cue: MarkgrafCue) => void): () => void;
92
+ onStepEnter(stepName: string, callback: (cue: MarkgrafStepCue) => void): () => void;
93
+ onComplete(callback: (event: MarkgrafCompleteEvent) => void): () => void;
45
94
  }
46
95
 
47
96
  export interface UseMarkgrafOptions<R extends "canvas" | "svg" = "canvas"> {
@@ -82,8 +131,13 @@ export function useMarkgraf(
82
131
 
83
132
  export interface MarkgrafPlayerProps {
84
133
  src: string;
85
- /** `"canvas"` (default) or `"svg"`. */
86
- renderer?: "canvas" | "svg";
134
+ /**
135
+ * `"canvas"` (default), `"svg"`, or `"sdf"` (alias `"webgl"`) — the WebGL
136
+ * raymarched 3D renderer. The SDF renderer is self-driving: it ignores
137
+ * `width`/`height` (it fills its container) and isn't available through the
138
+ * lower-level `useMarkgraf` hook.
139
+ */
140
+ renderer?: "canvas" | "svg" | "sdf" | "webgl";
87
141
  /** Visual theme. `"light"` (default), `"dark"`, or `"blueprint"`. */
88
142
  theme?: "light" | "dark" | "blueprint";
89
143
  /** When `true`, skip the background fill so the page bg shows through. */