effect-motion 0.2.0

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 (84) hide show
  1. package/README.md +40 -0
  2. package/dist/Camera.d.ts +49 -0
  3. package/dist/Camera.js +33 -0
  4. package/dist/Entity.d.ts +40 -0
  5. package/dist/Entity.js +32 -0
  6. package/dist/Fonts.d.ts +31 -0
  7. package/dist/Fonts.js +11 -0
  8. package/dist/Instance.d.ts +16 -0
  9. package/dist/Instance.js +18 -0
  10. package/dist/Motion.d.ts +74 -0
  11. package/dist/Motion.js +125 -0
  12. package/dist/Phaser.d.ts +65 -0
  13. package/dist/Phaser.js +170 -0
  14. package/dist/Physics.d.ts +78 -0
  15. package/dist/Physics.js +117 -0
  16. package/dist/Renderer.d.ts +69 -0
  17. package/dist/Renderer.js +90 -0
  18. package/dist/Runner.d.ts +360 -0
  19. package/dist/Runner.js +257 -0
  20. package/dist/Scene.d.ts +241 -0
  21. package/dist/Scene.js +454 -0
  22. package/dist/Time.d.ts +38 -0
  23. package/dist/Time.js +43 -0
  24. package/dist/Timing.d.ts +96 -0
  25. package/dist/Timing.js +151 -0
  26. package/dist/demo.d.ts +186 -0
  27. package/dist/demo.js +76 -0
  28. package/dist/index.d.ts +13 -0
  29. package/dist/index.js +13 -0
  30. package/dist/particles/Particle.d.ts +91 -0
  31. package/dist/particles/Particle.js +1 -0
  32. package/dist/particles/ParticleField.d.ts +170 -0
  33. package/dist/particles/ParticleField.js +69 -0
  34. package/dist/particles/Prng.d.ts +28 -0
  35. package/dist/particles/Prng.js +43 -0
  36. package/dist/particles/constructors.d.ts +78 -0
  37. package/dist/particles/constructors.js +15 -0
  38. package/dist/particles/index.d.ts +6 -0
  39. package/dist/particles/index.js +6 -0
  40. package/dist/particles/overLife.d.ts +16 -0
  41. package/dist/particles/overLife.js +21 -0
  42. package/dist/particles/render.d.ts +13 -0
  43. package/dist/particles/render.js +33 -0
  44. package/dist/particles/simulate.d.ts +39 -0
  45. package/dist/particles/simulate.js +81 -0
  46. package/dist/particles/step.d.ts +24 -0
  47. package/dist/particles/step.js +167 -0
  48. package/dist/shapes/Circle.d.ts +37 -0
  49. package/dist/shapes/Circle.js +9 -0
  50. package/dist/shapes/Ellipse.d.ts +41 -0
  51. package/dist/shapes/Ellipse.js +10 -0
  52. package/dist/shapes/Group.d.ts +150 -0
  53. package/dist/shapes/Group.js +82 -0
  54. package/dist/shapes/Layer.d.ts +9 -0
  55. package/dist/shapes/Layer.js +23 -0
  56. package/dist/shapes/Line.d.ts +47 -0
  57. package/dist/shapes/Line.js +30 -0
  58. package/dist/shapes/Path.d.ts +38 -0
  59. package/dist/shapes/Path.js +13 -0
  60. package/dist/shapes/Rect.d.ts +41 -0
  61. package/dist/shapes/Rect.js +10 -0
  62. package/dist/shapes/Shape2D.d.ts +40 -0
  63. package/dist/shapes/Shape2D.js +41 -0
  64. package/dist/shapes/Square.d.ts +37 -0
  65. package/dist/shapes/Square.js +11 -0
  66. package/dist/shapes/Text.d.ts +60 -0
  67. package/dist/shapes/Text.js +24 -0
  68. package/dist/shapes/index.d.ts +10 -0
  69. package/dist/shapes/index.js +10 -0
  70. package/dist/svg/SvgDomRenderer.d.ts +28 -0
  71. package/dist/svg/SvgDomRenderer.js +50 -0
  72. package/dist/svg/SvgNode.d.ts +13 -0
  73. package/dist/svg/SvgNode.js +18 -0
  74. package/dist/svg/SvgRenderer.d.ts +22 -0
  75. package/dist/svg/SvgRenderer.js +20 -0
  76. package/dist/svg/camera.d.ts +21 -0
  77. package/dist/svg/camera.js +43 -0
  78. package/dist/svg/index.d.ts +6 -0
  79. package/dist/svg/index.js +6 -0
  80. package/dist/svg/layers.d.ts +18 -0
  81. package/dist/svg/layers.js +13 -0
  82. package/dist/svg/shapes.d.ts +1089 -0
  83. package/dist/svg/shapes.js +119 -0
  84. package/package.json +51 -0
@@ -0,0 +1,241 @@
1
+ import { Context } from "effect";
2
+ import * as Cause from "effect/Cause";
3
+ import type * as Duration from "effect/Duration";
4
+ import * as Effect from "effect/Effect";
5
+ import * as Fiber from "effect/Fiber";
6
+ import type * as Schedule from "effect/Schedule";
7
+ import type * as Schema from "effect/Schema";
8
+ import type * as Scope from "effect/Scope";
9
+ import * as Stream from "effect/Stream";
10
+ import type * as Entity from "./Entity";
11
+ import type * as Instance from "./Instance";
12
+ import * as Phaser from "./Phaser";
13
+ import * as Runner from "./Runner";
14
+ export declare const TypeId: "~motion/Scene";
15
+ export interface Scene<E, R, Entities> {
16
+ readonly [TypeId]: typeof TypeId;
17
+ readonly runner: Effect.Effect<void, E, R | Scope.Scope>;
18
+ readonly "~entities": Entities;
19
+ /** tooling-facing metadata; never read by the runtime */
20
+ readonly annotations: Context.Context<never>;
21
+ annotate<I, S>(key: Context.Key<I, S>, value: S): Scene<E, R, Entities>;
22
+ annotateMerge(context: Context.Context<never>): Scene<E, R, Entities>;
23
+ }
24
+ type MakeEffect<Eff extends Effect.Effect<any, any, any>, AEff> = Effect.Effect<AEff, [
25
+ Eff
26
+ ] extends [never] ? never : [Eff] extends [Effect.Effect<infer _A, infer E, infer _R>] ? E : never, [
27
+ Eff
28
+ ] extends [never] ? never : [Eff] extends [Effect.Effect<infer _A, infer _E, infer R>] ? R : never>;
29
+ export declare const make: <const Eff extends Effect.Effect<any, any, any>, AEff>(f: () => Generator<Eff, void, never>) => MakeEffect<Eff, AEff> extends Effect.Effect<AEff, infer E, infer R> ? Scene<E, Exclude<R, {
30
+ readonly [Entity.TypeId]: typeof Entity.TypeId;
31
+ }> | Scope.Scope, Extract<R, {
32
+ readonly [Entity.TypeId]: typeof Entity.TypeId;
33
+ }>> : never;
34
+ export declare const instantiate: <Name extends string, Data extends Schema.Top, Traits extends Partial<Entity.EntityTraits<Data["Type"]>>, MakeInput>(entity: Entity.Entity<Name, Data, Traits, MakeInput>, props: Runner.InstantiateProps<MakeInput>) => Effect.Effect<Instance.Instance<Name, Data, Traits>, unknown, Entity.Entity<Name, Data, Traits, MakeInput> | Runner.Runner>;
35
+ export declare const tick: Effect.Effect<void, never, Runner.Runner>;
36
+ /**
37
+ * Hold the scene for `duration` of scene time (frames at the runner's
38
+ * frame rate) — `Effect.sleep`'s sibling, but in frames, not wall time.
39
+ * A zero-length duration is a no-op.
40
+ */
41
+ export declare const sleep: (duration: Duration.Input) => Effect.Effect<void, never, Runner.Runner>;
42
+ export interface FrameEntry<Entity extends Entity.AnyEntity> {
43
+ data: Entity["data"]["Type"];
44
+ entity: Entity;
45
+ /**
46
+ * builtin visibility, held beside the data; renderers skip `false`.
47
+ * Optional in the frame type (a hand-built frame or external producer
48
+ * may omit it) — absent means visible; the runner always sets it.
49
+ */
50
+ $visible?: boolean;
51
+ }
52
+ export type EntriesFromEntities<Entities> = Entities extends Entity.AnyEntity ? {
53
+ [K in Entities as K["name"]]: FrameEntry<K>;
54
+ }[Entities["name"]] : never;
55
+ export interface Frame<Entities extends Entity.AnyEntity> {
56
+ instances: Record<string, EntriesFromEntities<Entities>>;
57
+ /** id of the root group (conventionally "root"); never rendered itself */
58
+ root: string;
59
+ /** render metadata from the runner settings — a frame is self-describing */
60
+ frameRate: number;
61
+ width: number;
62
+ height: number;
63
+ backgroundColor: string;
64
+ /** the active camera's view; identity `{0,0,1}` when unused */
65
+ camera: {
66
+ x: number;
67
+ y: number;
68
+ zoom: number;
69
+ };
70
+ }
71
+ export declare const step: <E, R, Entities extends Entity.AnyEntity>(runningScene: RunningScene<E, R, Entities>) => Effect.Effect<Frame<Entities> | null, E, never>;
72
+ interface RunningScene<E, R, Entities> {
73
+ readonly runner: Runner.Runner["Service"];
74
+ readonly scene: Scene<E, R, Entities>;
75
+ readonly fiber: Fiber.Fiber<void, E>;
76
+ readonly done: boolean;
77
+ /** frames delivered so far — mutated by `step` for the maxFrames cap */
78
+ framesDelivered: number;
79
+ }
80
+ export declare const run: <E, R, Entities>(scene: Scene<E, R, Entities>, settings?: Partial<Runner.Settings>) => Effect.Effect<RunningScene<E, R, Entities>, never, Exclude<Exclude<Exclude<Exclude<R, Scope.Scope>, never>, Phaser.Phaser>, Runner.Runner>>;
81
+ export declare const stream: <E, R, Entities extends Entity.AnyEntity>(scene: Scene<E, R, Entities>, settings?: Partial<Runner.Settings>) => Stream.Stream<Frame<Entities>, Exclude<E, Cause.Done<any>>, Exclude<Exclude<Exclude<Exclude<Exclude<R, Scope.Scope>, never>, Phaser.Phaser>, Runner.Runner>, Scope.Scope>>;
82
+ type Updater<Data> = Data | ((data: Data) => Data);
83
+ export declare const data: <Name extends string, Data extends Schema.Top>(instance: Instance.Instance<Name, Data>) => Effect.Effect<Data["Type"] & ({} | undefined), never, Runner.Runner>;
84
+ export declare const update: <Name extends string, Data extends Schema.Top>(instance: Instance.Instance<Name, Data>, props: Updater<Data["Type"]>) => Effect.Effect<void | false, never, Runner.Runner>;
85
+ /**
86
+ * Move `child` under `parent`, detaching it from its current parent first
87
+ * (so it is never double-referenced). Instances are born mounted under the
88
+ * ambient parent; `appendChild` is the explicit reparent — the door to
89
+ * placing a lazily-created node into an existing group.
90
+ */
91
+ export declare const appendChild: (parent: Runner.GroupInstance, child: Instance.Instance) => Effect.Effect<void, never, Runner.Runner>;
92
+ /** Detach `child` from `parent` (no-op unless it is currently its child). */
93
+ export declare const removeChild: (parent: Runner.GroupInstance, child: Instance.Instance) => Effect.Effect<void, never, Runner.Runner>;
94
+ export declare const settings: () => Effect.Effect<{
95
+ frameRate: number;
96
+ width: number;
97
+ height: number;
98
+ backgroundColor: string;
99
+ seed: Runner.Seed;
100
+ maxFrames: number;
101
+ }, never, Runner.Runner>;
102
+ /**
103
+ * The active camera instance — an ordinary instance carrying `~position`
104
+ * (x/y pan) and a `zoom` field, so the existing animators drive it:
105
+ * `Scene.make(function* () { const cam = yield* Scene.camera; yield*
106
+ * cam.pipe(Motion.moveTo({ x: 400 })) })`. A default identity camera is
107
+ * always present; animate it directly, or `Scene.setCamera` to swap in
108
+ * another instance. The camera is never drawn.
109
+ */
110
+ export declare const camera: Effect.Effect<Instance.Instance<"Camera", Schema.Struct<{
111
+ x: Schema.withConstructorDefault<Schema.Number>;
112
+ y: Schema.withConstructorDefault<Schema.Number>;
113
+ zoom: Schema.withConstructorDefault<Schema.Number>;
114
+ }>, {
115
+ readonly "~position": {
116
+ get: (data: Schema.Struct.ReadonlySide<{
117
+ x: Schema.withConstructorDefault<Schema.Number>;
118
+ y: Schema.withConstructorDefault<Schema.Number>;
119
+ zoom: Schema.withConstructorDefault<Schema.Number>;
120
+ }, "Type">) => {
121
+ x: number;
122
+ y: number;
123
+ };
124
+ set: (data: Schema.Struct.ReadonlySide<{
125
+ x: Schema.withConstructorDefault<Schema.Number>;
126
+ y: Schema.withConstructorDefault<Schema.Number>;
127
+ zoom: Schema.withConstructorDefault<Schema.Number>;
128
+ }, "Type">, value: Entity.Position) => Schema.Struct.ReadonlySide<{
129
+ x: Schema.withConstructorDefault<Schema.Number>;
130
+ y: Schema.withConstructorDefault<Schema.Number>;
131
+ zoom: Schema.withConstructorDefault<Schema.Number>;
132
+ }, "Type">;
133
+ };
134
+ }>, never, Runner.Runner>;
135
+ /** Swap the active camera to `instance`; its live data becomes the view. */
136
+ export declare const setCamera: (instance: Instance.Instance) => Effect.Effect<void, never, Runner.Runner>;
137
+ /**
138
+ * Handle to a branch of animation (a fork, background, or played scene).
139
+ * `finished` resolves at the branch's SEMANTIC end — `Scene.finish` or
140
+ * completion, whichever comes first. Awaiting it from scene code HOLDS
141
+ * the scene (the waiter keeps ticking frames, like `Scene.sleep`), so
142
+ * the rest of the scene stays live while you wait. `fiber` is the
143
+ * branch's physical execution — interrupt it to bound a tail.
144
+ */
145
+ export interface BranchHandle<A = unknown, E = unknown> {
146
+ readonly finished: Effect.Effect<void, never, Runner.Runner>;
147
+ readonly fiber: Fiber.Fiber<A, E>;
148
+ }
149
+ /**
150
+ * Finish the innermost enclosing branch (the current fork, played scene,
151
+ * or the scene body itself): whoever awaits the branch's `finished`
152
+ * proceeds, the branch stops blocking its parent's end, and the code
153
+ * after `finish` keeps running as a TAIL — bounded by the parent, which
154
+ * interrupts it at scene end like a background. Idempotent; completion
155
+ * implies finish. NOTE: a failure in the tail (after finish) is NOT
156
+ * reported — by then nothing is listening.
157
+ */
158
+ export declare const finish: Effect.Effect<undefined, never, never>;
159
+ /**
160
+ * Run `effect`, then repeat it as long as `schedule` recurs, with the
161
+ * schedule evaluated in scene time (frames at the runner's frame rate) —
162
+ * `Effect.repeat`'s sibling, but paced by frames instead of the wall
163
+ * clock. The first run is immediate; the schedule paces the gaps after
164
+ * runs; each run's result is fed to the schedule as input. Resolves with
165
+ * the schedule's final output once it is done; a failed run fails
166
+ * immediately without consulting the schedule again.
167
+ */
168
+ export declare const repeat: <A, E, R, Output, ScheduleE, ScheduleR>(effect: Effect.Effect<A, E, R>, schedule: Schedule.Schedule<Output, A, ScheduleE, ScheduleR>) => Effect.Effect<Output, E | ScheduleE, R | ScheduleR | Runner.Runner>;
169
+ /**
170
+ * Run `effect` concurrently with the rest of the scene, sharing frame
171
+ * phases, and return its fiber immediately.
172
+ *
173
+ * NOTE: this inverts Effect's own `fork` semantics — the scene's end
174
+ * WAITS for forked work. A scene whose body returns while forks are
175
+ * still animating keeps producing frames until the last fork finishes
176
+ * (so a scene containing only a fork still plays). Use
177
+ * {@link background} for work that should be cut off at scene end
178
+ * instead. Forks are supervised by the fiber that spawned them: a fork
179
+ * made inside another fork is interrupted when its spawner completes.
180
+ */
181
+ export declare const fork: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<BranchHandle<A, E>, never, Runner.Runner | Exclude<Exclude<R, never>, Phaser.Phaser>>;
182
+ /**
183
+ * Like {@link fork}, but the fiber is INTERRUPTED at scene end instead
184
+ * of awaited — for indefinite work (`Scene.repeat(…, Schedule.forever)`)
185
+ * that should play for the duration of the scene without keeping it
186
+ * alive. "Scene end" includes the fork drain: backgrounds keep animating
187
+ * while awaited forks finish, and are stopped after the last one.
188
+ */
189
+ export declare const background: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<BranchHandle<A, E>, never, Runner.Runner | Exclude<Exclude<R, never>, Phaser.Phaser>>;
190
+ export interface PlayOptions {
191
+ /** group to mount the scene's instances under (default: the root) */
192
+ readonly parent?: Runner.GroupInstance;
193
+ /** seed for this evaluation (default: the movie's seed) */
194
+ readonly seed?: Runner.Seed;
195
+ }
196
+ /**
197
+ * Play a scene as a branch of the current scene — the explicit door to
198
+ * nesting. The child shares the movie's runner, phaser, frame rate, and
199
+ * frame cap, and gets its own scope, branch handle, mount parent, and a
200
+ * FRESH seeded Random stream: `play(scene)` inside a movie seeded `S`
201
+ * animates exactly like `run(scene, { seed: S })` standalone. Awaited
202
+ * like a fork — `yield* handle.finished` for sequential nesting, or
203
+ * don't await for concurrent scenes.
204
+ */
205
+ export declare const play: <E, R, Entities>(scene: Scene<E, R, Entities>, options?: PlayOptions) => Effect.Effect<BranchHandle<void, E>, never, Runner.Runner | Exclude<R, Scope.Scope>>;
206
+ /**
207
+ * Run effects in lockstep parallel, sharing frame phases — the public
208
+ * counterpart to the low-level `Phaser.all`. Takes no schedule: pacing a
209
+ * list sequentially belongs to {@link chain}, overlapping staggered
210
+ * starts to {@link stagger}.
211
+ */
212
+ export declare const all: typeof Phaser.all;
213
+ /**
214
+ * Run items one at a time, in order — items NEVER overlap, mirroring
215
+ * Effect's guarantee for scheduled effects. The first item runs
216
+ * immediately; after each item completes, `schedule` is stepped once
217
+ * (with the item's result as input) to pace the next start. `fixed`
218
+ * gives a start cadence with catch-up, `spaced` gives rests between
219
+ * items. When the schedule ends early, the remaining items are skipped —
220
+ * it is the release policy, including how many. Without a schedule,
221
+ * plain sequential composition. Resolves with how many items completed.
222
+ * For overlapping runs, reach for {@link stagger} or {@link fork}
223
+ * explicitly.
224
+ */
225
+ export declare const chain: <Eff extends Effect.Effect<any, any, any>, ScheduleE = never, ScheduleR = never>(effects: Iterable<Eff>, schedule?: Schedule.Schedule<unknown, Eff extends Effect.Effect<infer A, any, any> ? A : never, ScheduleE, ScheduleR>) => Effect.Effect<{
226
+ completed: number;
227
+ }, (Eff extends Effect.Effect<any, infer E, any> ? E : never) | ScheduleE, (Eff extends Effect.Effect<any, any, infer R> ? R : never) | Runner.Runner | ScheduleR>;
228
+ /**
229
+ * Release effects on `schedule` with OVERLAP: the first starts
230
+ * immediately, each next one on the schedule's next emission, and
231
+ * released effects run concurrently — semantically
232
+ * `chain(effects.map(Scene.fork))`, but resolving when all released
233
+ * effects finish rather than at the last release. When the schedule ends
234
+ * early, the remaining effects are skipped. Overlap is this
235
+ * combinator's purpose; the schedule-paced default ({@link chain})
236
+ * never overlaps.
237
+ */
238
+ export declare const stagger: <Eff extends Effect.Effect<any, any, any>, ScheduleE = never, ScheduleR = never>(effects: Iterable<Eff>, schedule: Schedule.Schedule<unknown, void, ScheduleE, ScheduleR>) => Effect.Effect<{
239
+ released: number;
240
+ }, (Eff extends Effect.Effect<any, infer E, any> ? E : never) | ScheduleE, (Eff extends Effect.Effect<any, any, infer R> ? R : never) | Phaser.Phaser | Runner.Runner | ScheduleR>;
241
+ export {};