aispritejs 0.5.8 → 0.6.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.
@@ -35,7 +35,33 @@ var MAX_SPEED = 1e3;
35
35
  function isObject(v) {
36
36
  return typeof v === "object" && v !== null && !Array.isArray(v);
37
37
  }
38
+ function assertString(v, what) {
39
+ if (typeof v !== "string") {
40
+ throw new InvalidGraphError(`${what} must be a string, got ${typeof v}`);
41
+ }
42
+ }
43
+ function assertPositive(v, what, max, unit) {
44
+ if (!Number.isFinite(v) || v <= 0) {
45
+ throw new InvalidGraphError(`${what} must be a finite number > 0, got ${v}`);
46
+ }
47
+ if (v > max) throw new InvalidGraphError(`${what} must be \u2264 ${max}${unit}, got ${v}`);
48
+ }
49
+ function assertGraphShape(graph) {
50
+ if (!isObject(graph)) throw new InvalidGraphError("graph must be an object");
51
+ for (const key of ["animations", "inputs", "states"]) {
52
+ if (!isObject(graph[key])) throw new InvalidGraphError(`${key} must be an object`);
53
+ }
54
+ if (!Array.isArray(graph.transitions)) {
55
+ throw new InvalidGraphError("transitions must be an array");
56
+ }
57
+ for (const [name, list] of Object.entries(graph.animations)) {
58
+ if (!Array.isArray(list)) {
59
+ throw new InvalidGraphError(`animation "${name}" must be an array of frame keys`);
60
+ }
61
+ }
62
+ }
38
63
  function compileGraph(graph) {
64
+ assertGraphShape(graph);
39
65
  if (Object.keys(graph.animations).length === 0) {
40
66
  throw new InvalidGraphError("animations must declare at least one animation");
41
67
  }
@@ -44,59 +70,38 @@ function compileGraph(graph) {
44
70
  throw new InvalidGraphError("states must declare at least one state");
45
71
  }
46
72
  for (const [name, def] of Object.entries(graph.inputs)) {
47
- if (def.type !== "number" && def.type !== "boolean" && def.type !== "trigger") {
73
+ const type = def?.type;
74
+ if (type !== "number" && type !== "boolean" && type !== "trigger") {
75
+ throw new InvalidGraphError(`input "${name}" has unknown type "${type}"`);
76
+ }
77
+ const d = def.default;
78
+ if (d !== void 0 && (type === "number" && typeof d !== "number" || type === "boolean" && typeof d !== "boolean")) {
48
79
  throw new InvalidGraphError(
49
- `input "${name}" has unknown type "${def.type}"`
80
+ `input "${name}" default must be a ${type} (declared type "${type}"), got ${typeof d}`
50
81
  );
51
82
  }
52
- const rawDef = def;
53
- if (rawDef.default !== void 0) {
54
- if (def.type === "number" && typeof rawDef.default !== "number") {
55
- throw new InvalidGraphError(
56
- `input "${name}" default must be a number (declared type "number"), got ${typeof rawDef.default}`
57
- );
58
- }
59
- if (def.type === "boolean" && typeof rawDef.default !== "boolean") {
60
- throw new InvalidGraphError(
61
- `input "${name}" default must be a boolean (declared type "boolean"), got ${typeof rawDef.default}`
62
- );
63
- }
64
- }
65
83
  }
66
84
  const defaultDuration = graph.defaultFrameDuration ?? DEFAULT_FRAME_DURATION;
67
- if (!Number.isFinite(defaultDuration) || defaultDuration <= 0) {
68
- throw new InvalidGraphError(
69
- `defaultFrameDuration must be a finite number > 0, got ${defaultDuration}`
70
- );
71
- }
72
- if (defaultDuration > MAX_DURATION) {
73
- throw new InvalidGraphError(
74
- `defaultFrameDuration must be \u2264 ${MAX_DURATION} ms, got ${defaultDuration}`
75
- );
76
- }
85
+ assertPositive(defaultDuration, "defaultFrameDuration", MAX_DURATION, " ms");
77
86
  if (graph.frames) {
78
87
  for (const [key, timing] of Object.entries(graph.frames)) {
79
88
  if (!isObject(timing)) {
80
89
  throw new InvalidGraphError(`frame "${key}" timing must be an object`);
81
90
  }
82
- if (timing.duration !== void 0 && (!Number.isFinite(timing.duration) || timing.duration <= 0)) {
83
- throw new InvalidGraphError(
84
- `frame "${key}" duration must be a finite number > 0, got ${timing.duration}`
85
- );
86
- }
87
- if (timing.duration !== void 0 && timing.duration > MAX_DURATION) {
88
- throw new InvalidGraphError(
89
- `frame "${key}" duration must be \u2264 ${MAX_DURATION} ms, got ${timing.duration}`
90
- );
91
+ if (timing.duration !== void 0) {
92
+ assertPositive(timing.duration, `frame "${key}" duration`, MAX_DURATION, " ms");
91
93
  }
92
94
  }
93
95
  }
96
+ if (graph.initial !== void 0) assertString(graph.initial, "initial");
94
97
  const initial = graph.initial ?? stateEntries[0][0];
95
98
  if (!Object.hasOwn(graph.states, initial)) {
96
99
  throw new InvalidGraphError(`initial state "${initial}" is not declared`);
97
100
  }
98
101
  const states = /* @__PURE__ */ new Map();
99
102
  for (const [name, st] of stateEntries) {
103
+ assertString(st?.animation, `state "${name}" animation`);
104
+ if (st.onEnd !== void 0) assertString(st.onEnd, `state "${name}" onEnd`);
100
105
  const frameKeys = graph.animations[st.animation];
101
106
  if (frameKeys === void 0 || !Object.hasOwn(graph.animations, st.animation)) {
102
107
  throw new InvalidGraphError(`state "${name}" references unknown animation "${st.animation}"`);
@@ -105,14 +110,7 @@ function compileGraph(graph) {
105
110
  throw new InvalidGraphError(`animation "${st.animation}" (state "${name}") has no frames`);
106
111
  }
107
112
  const speed = st.speed ?? 1;
108
- if (!Number.isFinite(speed) || speed <= 0) {
109
- throw new InvalidGraphError(
110
- `state "${name}" speed must be a finite number > 0, got ${speed}`
111
- );
112
- }
113
- if (speed > MAX_SPEED) {
114
- throw new InvalidGraphError(`state "${name}" speed must be \u2264 ${MAX_SPEED}, got ${speed}`);
115
- }
113
+ assertPositive(speed, `state "${name}" speed`, MAX_SPEED, "");
116
114
  const loop = st.loop === true;
117
115
  if (loop && st.onEnd !== void 0) {
118
116
  throw new InvalidGraphError(
@@ -128,23 +126,7 @@ function compileGraph(graph) {
128
126
  running += graph.frames?.[key]?.duration ?? defaultDuration;
129
127
  cumulative.push(running);
130
128
  }
131
- states.set(name, {
132
- name,
133
- animation: st.animation,
134
- loop,
135
- speed,
136
- onEnd: st.onEnd,
137
- // `frameKeys` is aliased directly from `graph.animations[st.animation]`
138
- // without copying. The declared `readonly` typing makes mutation a
139
- // compile-time error for typed callers, but callers holding the raw JSON
140
- // object can mutate it at runtime. Callers must NOT mutate the atlas
141
- // `animations` arrays while a machine built from that graph is alive;
142
- // doing so desyncs `frameKeys` from the precomputed `cumulative` timings
143
- // and can cause `frameKeys[activeFrameIndex]` to yield `undefined`.
144
- frameKeys,
145
- cumulative,
146
- total: running
147
- });
129
+ states.set(name, { name, loop, speed, onEnd: st.onEnd, frameKeys, cumulative, total: running });
148
130
  }
149
131
  const compiled = [];
150
132
  graph.transitions.forEach((t, order) => {
@@ -154,6 +136,13 @@ function compileGraph(graph) {
154
136
  if (t.when !== void 0 && !Array.isArray(t.when)) {
155
137
  throw new InvalidGraphError(`transition #${order} "when" must be an array`);
156
138
  }
139
+ assertString(t.from, `transition #${order} "from"`);
140
+ assertString(t.to, `transition #${order} "to"`);
141
+ if (t.priority !== void 0 && !Number.isInteger(t.priority)) {
142
+ throw new InvalidGraphError(
143
+ `transition #${order} priority must be an integer, got ${t.priority}`
144
+ );
145
+ }
157
146
  if (t.from !== "*" && !Object.hasOwn(graph.states, t.from)) {
158
147
  throw new InvalidGraphError(`transition #${order} from "${t.from}" is not a declared state`);
159
148
  }
@@ -163,6 +152,11 @@ function compileGraph(graph) {
163
152
  const conditions = [];
164
153
  const triggers = [];
165
154
  for (const c of t.when ?? []) {
155
+ assertString(
156
+ c?.input,
157
+ `transition #${order} condition "input"`
158
+ );
159
+ assertString(c.op, `transition #${order} condition "op"`);
166
160
  const def = graph.inputs[c.input];
167
161
  if (def === void 0 || !Object.hasOwn(graph.inputs, c.input)) {
168
162
  throw new InvalidGraphError(
@@ -260,30 +254,25 @@ function compileCondition(order, input, op, value, kind, out, triggers) {
260
254
 
261
255
  // src/sprite/emitter.ts
262
256
  function createSignal() {
263
- const listeners = /* @__PURE__ */ new Set();
264
- const cleanups = /* @__PURE__ */ new Map();
257
+ const listeners = /* @__PURE__ */ new Map();
265
258
  function on(handler, options) {
266
- if (options?.signal?.aborted) return () => {
259
+ const once = options?.once;
260
+ const sig = options?.signal;
261
+ if (sig?.aborted) return () => {
267
262
  };
268
263
  let detachAbort;
269
264
  const cleanup = () => {
270
265
  listeners.delete(wrapped);
271
- cleanups.delete(wrapped);
272
266
  if (detachAbort) {
273
267
  detachAbort();
274
268
  detachAbort = void 0;
275
269
  }
276
270
  };
277
- let wrapped = handler;
278
- if (options?.once) {
279
- wrapped = (payload) => {
280
- cleanup();
281
- handler(payload);
282
- };
283
- }
284
- listeners.add(wrapped);
285
- cleanups.set(wrapped, cleanup);
286
- const sig = options?.signal;
271
+ const wrapped = (payload) => {
272
+ if (once) cleanup();
273
+ handler(payload);
274
+ };
275
+ listeners.set(wrapped, cleanup);
287
276
  if (sig) {
288
277
  const onAbort = () => cleanup();
289
278
  sig.addEventListener("abort", onAbort, { once: true });
@@ -293,12 +282,28 @@ function createSignal() {
293
282
  }
294
283
  function emit(payload) {
295
284
  if (listeners.size === 0) return;
296
- for (const fn of [...listeners]) fn(payload);
285
+ let failure;
286
+ for (const fn of [...listeners.keys()]) {
287
+ if (!listeners.has(fn)) continue;
288
+ try {
289
+ fn(payload);
290
+ } catch (error) {
291
+ failure ??= { error };
292
+ }
293
+ }
294
+ if (failure) throw failure.error;
297
295
  }
298
296
  function clear() {
299
- for (const cleanup of [...cleanups.values()]) cleanup();
300
- listeners.clear();
301
- cleanups.clear();
297
+ try {
298
+ for (const cleanup of [...listeners.values()]) {
299
+ try {
300
+ cleanup();
301
+ } catch {
302
+ }
303
+ }
304
+ } finally {
305
+ listeners.clear();
306
+ }
302
307
  }
303
308
  return { on, emit, clear };
304
309
  }
@@ -357,9 +362,6 @@ function createInputStore(inputs) {
357
362
  return {
358
363
  setInput,
359
364
  fireTrigger,
360
- // `!` is sound: every declared input is seeded at construction and the
361
- // compiler validates that conditions only read declared inputs of the
362
- // matching kind, so these reads always hit a present entry.
363
365
  readNumber: (name) => numbers.get(name),
364
366
  readBoolean: (name) => booleans.get(name),
365
367
  isPending: (name) => triggers.get(name) === true,
@@ -387,6 +389,8 @@ function createSpriteAnimator(graph) {
387
389
  let activeFrameIndex = 0;
388
390
  let activeFrameKey = current.frameKeys[0];
389
391
  let disposed = false;
392
+ let dispatching = false;
393
+ const mailbox = [];
390
394
  function mustState(name) {
391
395
  return compiled.states.get(name);
392
396
  }
@@ -416,13 +420,13 @@ function createSpriteAnimator(graph) {
416
420
  }
417
421
  if (!ok) continue;
418
422
  if (t.to === current.name && t.triggers.length === 0) continue;
419
- return { to: t.to, triggers: t.triggers };
423
+ return t;
420
424
  }
421
425
  return void 0;
422
426
  }
423
- function update(deltaMs) {
424
- if (disposed) throw new SpriteAnimatorDisposedError();
425
- elapsed += (Number.isFinite(deltaMs) && deltaMs > 0 ? deltaMs : 0) * current.speed;
427
+ function processUpdate(deltaMs) {
428
+ const next = elapsed + (Number.isFinite(deltaMs) && deltaMs > 0 ? deltaMs : 0) * current.speed;
429
+ if (Number.isFinite(next)) elapsed = next;
426
430
  const chosen = resolve();
427
431
  if (chosen) {
428
432
  enter(chosen.to, chosen.triggers);
@@ -443,24 +447,45 @@ function createSpriteAnimator(graph) {
443
447
  activeFrameKey = cs.frameKeys[activeFrameIndex];
444
448
  if (ended && !completed) {
445
449
  completed = true;
446
- complete.emit(cs.name);
447
- if (cs.onEnd !== void 0) enter(cs.onEnd, NO_TRIGGERS);
450
+ try {
451
+ complete.emit(cs.name);
452
+ } finally {
453
+ if (cs.onEnd !== void 0 && !disposed) enter(cs.onEnd, NO_TRIGGERS);
454
+ }
455
+ }
456
+ }
457
+ function processReset() {
458
+ store.reset();
459
+ enter(compiled.initial, NO_TRIGGERS);
460
+ }
461
+ function run(first, dt) {
462
+ dispatching = true;
463
+ try {
464
+ first(dt);
465
+ while (mailbox.length > 0) {
466
+ const m = mailbox.shift();
467
+ if (m.kind === "update") processUpdate(m.dt);
468
+ else processReset();
469
+ }
470
+ } finally {
471
+ dispatching = false;
472
+ mailbox.length = 0;
448
473
  }
449
474
  }
475
+ function update(deltaMs) {
476
+ if (disposed) throw new SpriteAnimatorDisposedError();
477
+ if (dispatching) mailbox.push({ kind: "update", dt: deltaMs });
478
+ else run(processUpdate, deltaMs);
479
+ }
450
480
  function reset() {
451
481
  if (disposed) throw new SpriteAnimatorDisposedError();
452
- const from = current.name;
453
- store.reset();
454
- current = mustState(compiled.initial);
455
- elapsed = 0;
456
- completed = false;
457
- activeFrameIndex = 0;
458
- activeFrameKey = current.frameKeys[0];
459
- if (from !== compiled.initial) stateChange.emit({ to: compiled.initial, from });
482
+ if (dispatching) mailbox.push({ kind: "reset" });
483
+ else run(processReset, 0);
460
484
  }
461
485
  function dispose() {
462
486
  if (disposed) return;
463
487
  disposed = true;
488
+ mailbox.length = 0;
464
489
  stateChange.clear();
465
490
  complete.clear();
466
491
  }
@@ -501,6 +526,6 @@ function createSpriteAnimator(graph) {
501
526
  };
502
527
  }
503
528
 
504
- export { InputTypeError, InvalidGraphError, SpriteAnimatorDisposedError, UnknownInputError, createSpriteAnimator, isObject };
505
- //# sourceMappingURL=chunk-6E4ILDBY.js.map
506
- //# sourceMappingURL=chunk-6E4ILDBY.js.map
529
+ export { InputTypeError, InvalidGraphError, SpriteAnimatorDisposedError, UnknownInputError, assertGraphShape, createSpriteAnimator, isObject };
530
+ //# sourceMappingURL=chunk-NBMU2UNJ.js.map
531
+ //# sourceMappingURL=chunk-NBMU2UNJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sprite/errors.ts","../src/sprite/compile.ts","../src/sprite/emitter.ts","../src/sprite/inputs.ts","../src/sprite/machine.ts"],"names":["v"],"mappings":"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","file":"chunk-NBMU2UNJ.js","sourcesContent":["// aispritejs — named error classes. Named errors instead of bare throws let\n// callers branch on failure mode (e.g. distinguish a typo'd input from a\n// post-dispose call) and keep stack traces meaningful.\n\n/**\n * Thrown by `setInput` / `fireTrigger` / `update` / `reset` after the animator\n * has been disposed.\n *\n * @public\n */\nexport class SpriteAnimatorDisposedError extends Error {\n constructor() {\n super(\"aispritejs: animator has been disposed; this operation is not allowed\");\n this.name = \"SpriteAnimatorDisposedError\";\n }\n}\n\n/**\n * Thrown by `createSpriteAnimator` when the graph fails validation — the graph\n * or one of its blocks has the wrong shape, a state/transition/condition\n * identifier is not a string, a state references a missing animation, a\n * transition points at an unknown state or has a non-integer priority, a\n * condition uses an operator the input kind does not support, a duration is\n * non-positive, and so on. Fail-fast: an invalid graph never produces a\n * half-built animator.\n *\n * @public\n */\nexport class InvalidGraphError extends Error {\n constructor(message: string) {\n super(`aispritejs: invalid graph — ${message}`);\n this.name = \"InvalidGraphError\";\n }\n}\n\n/**\n * Thrown by `setInput` / `fireTrigger` when the named input is not declared in\n * the graph's `inputs` block.\n *\n * @public\n */\nexport class UnknownInputError extends Error {\n readonly input: string;\n constructor(input: string) {\n super(`aispritejs: unknown input \"${input}\"; declare it in the graph's inputs block`);\n this.name = \"UnknownInputError\";\n this.input = input;\n }\n}\n\n/**\n * Thrown when an input is used against its kind — `setInput` with the wrong\n * value type, `setInput` on a Trigger, or `fireTrigger` on a non-Trigger.\n *\n * @public\n */\nexport class InputTypeError extends Error {\n readonly input: string;\n constructor(input: string, message: string) {\n super(`aispritejs: input \"${input}\" — ${message}`);\n this.name = \"InputTypeError\";\n this.input = input;\n }\n}\n","// aispritejs — graph compiler. Validates the graph's shape and every\n// cross-reference the type system cannot (identifier types, animation\n// existence, transition targets, operator/kind compatibility, integer\n// priorities, positive durations) and normalises the graph into a precomputed\n// runtime form: per-state cumulative frame timings and per-state transition\n// candidate lists sorted by (priority desc, declared-order asc). All allocation\n// happens here, once, so `update()` stays allocation-free.\n\nimport { InvalidGraphError } from \"./errors.js\";\nimport type { InputStore } from \"./inputs.js\";\nimport type { InputDef, SpriteGraph, StateDef, TransitionCondition } from \"./types.js\";\n\n/** A compiled condition: a closure that reads the live store and returns a boolean. */\nexport type ConditionFn = (store: InputStore) => boolean;\n\nexport interface CompiledTransition {\n readonly from: string;\n readonly to: string;\n readonly priority: number;\n /** Declared index — the deterministic tie-break when priorities are equal. */\n readonly order: number;\n /** AND-ed at runtime; empty means \"matches unconditionally\". */\n readonly conditions: readonly ConditionFn[];\n /** Trigger input names this transition consumes when taken. */\n readonly triggers: readonly string[];\n}\n\nexport interface CompiledState {\n readonly name: string;\n readonly loop: boolean;\n readonly speed: number;\n readonly onEnd: string | undefined;\n readonly frameKeys: readonly string[];\n /** `cumulative[i]` = summed duration of frames `0..i`; last entry === `total`. */\n readonly cumulative: readonly number[];\n readonly total: number;\n}\n\nexport interface CompiledGraph {\n readonly initial: string;\n readonly states: ReadonlyMap<string, CompiledState>;\n readonly candidatesByState: ReadonlyMap<string, readonly CompiledTransition[]>;\n}\n\nconst DEFAULT_FRAME_DURATION = 100;\n/** Maximum allowed frame / default-frame duration in ms (24 hours). */\nconst MAX_DURATION = 86_400_000;\n/** Maximum allowed state speed multiplier (1000× normal). */\nconst MAX_SPEED = 1_000;\n\n/** @internal */\nexport function isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\n/**\n * Throw {@link InvalidGraphError} naming `what` unless `v` is a string. Runs\n * before every `Object.hasOwn` lookup, which would otherwise stringify a number\n * or an array and resolve it to a declared name.\n */\nfunction assertString(v: unknown, what: string): void {\n if (typeof v !== \"string\") {\n throw new InvalidGraphError(`${what} must be a string, got ${typeof v}`);\n }\n}\n\n/** Throw {@link InvalidGraphError} unless `v` is a finite number in `(0, max]`. */\nfunction assertPositive(v: number, what: string, max: number, unit: string): void {\n if (!Number.isFinite(v) || v <= 0) {\n throw new InvalidGraphError(`${what} must be a finite number > 0, got ${v}`);\n }\n if (v > max) throw new InvalidGraphError(`${what} must be ≤ ${max}${unit}, got ${v}`);\n}\n\n/**\n * @internal Structural guard: the graph and its containers have the shapes the\n * compiler (and the Pixi adapter's texture scan) iterate, so misuse from\n * untyped callers is an {@link InvalidGraphError}, never a bare `TypeError`.\n */\nexport function assertGraphShape(graph: SpriteGraph): void {\n if (!isObject(graph)) throw new InvalidGraphError(\"graph must be an object\");\n for (const key of [\"animations\", \"inputs\", \"states\"] as const) {\n if (!isObject(graph[key])) throw new InvalidGraphError(`${key} must be an object`);\n }\n if (!Array.isArray(graph.transitions)) {\n throw new InvalidGraphError(\"transitions must be an array\");\n }\n for (const [name, list] of Object.entries(graph.animations)) {\n if (!Array.isArray(list)) {\n throw new InvalidGraphError(`animation \"${name}\" must be an array of frame keys`);\n }\n }\n}\n\nexport function compileGraph(graph: SpriteGraph): CompiledGraph {\n assertGraphShape(graph);\n if (Object.keys(graph.animations).length === 0) {\n throw new InvalidGraphError(\"animations must declare at least one animation\");\n }\n\n const stateEntries = Object.entries(graph.states);\n if (stateEntries.length === 0) {\n throw new InvalidGraphError(\"states must declare at least one state\");\n }\n\n // Inputs: types are enforced by TS, but a graph loaded from untyped JSON can\n // still carry a bad `type` or a `default` whose typeof mismatches the kind.\n // Validate so a bad input fails here, not silently in the store.\n for (const [name, def] of Object.entries(graph.inputs)) {\n // `?.`: a null / non-object entry from untyped JSON reports an unknown type.\n const type = (def as InputDef | null)?.type;\n if (type !== \"number\" && type !== \"boolean\" && type !== \"trigger\") {\n throw new InvalidGraphError(`input \"${name}\" has unknown type \"${type}\"`);\n }\n // Validate `default` typeof matches the declared kind (schema constraint in\n // code). A wrong-typed default would be adopted unvalidated and silently\n // misevaluate conditions (e.g. \"5\" === 5 is false for Equals).\n const d = (def as { default?: unknown }).default;\n if (\n d !== undefined &&\n ((type === \"number\" && typeof d !== \"number\") ||\n (type === \"boolean\" && typeof d !== \"boolean\"))\n ) {\n throw new InvalidGraphError(\n `input \"${name}\" default must be a ${type} (declared type \"${type}\"), got ${typeof d}`,\n );\n }\n }\n\n const defaultDuration = graph.defaultFrameDuration ?? DEFAULT_FRAME_DURATION;\n assertPositive(defaultDuration, \"defaultFrameDuration\", MAX_DURATION, \" ms\");\n\n if (graph.frames) {\n for (const [key, timing] of Object.entries(graph.frames)) {\n if (!isObject(timing as unknown)) {\n throw new InvalidGraphError(`frame \"${key}\" timing must be an object`);\n }\n if (timing.duration !== undefined) {\n assertPositive(timing.duration, `frame \"${key}\" duration`, MAX_DURATION, \" ms\");\n }\n }\n }\n\n if (graph.initial !== undefined) assertString(graph.initial, \"initial\");\n const initial = graph.initial ?? stateEntries[0]![0];\n if (!Object.hasOwn(graph.states, initial)) {\n throw new InvalidGraphError(`initial state \"${initial}\" is not declared`);\n }\n\n // --- compile states -----------------------------------------------------\n const states = new Map<string, CompiledState>();\n for (const [name, st] of stateEntries) {\n // `?.`: a null / non-object state entry fails the animation-type check.\n assertString((st as StateDef | null)?.animation, `state \"${name}\" animation`);\n if (st.onEnd !== undefined) assertString(st.onEnd, `state \"${name}\" onEnd`);\n const frameKeys = graph.animations[st.animation];\n if (frameKeys === undefined || !Object.hasOwn(graph.animations, st.animation)) {\n throw new InvalidGraphError(`state \"${name}\" references unknown animation \"${st.animation}\"`);\n }\n if (frameKeys.length === 0) {\n throw new InvalidGraphError(`animation \"${st.animation}\" (state \"${name}\") has no frames`);\n }\n const speed = st.speed ?? 1;\n assertPositive(speed, `state \"${name}\" speed`, MAX_SPEED, \"\");\n const loop = st.loop === true;\n if (loop && st.onEnd !== undefined) {\n throw new InvalidGraphError(\n `state \"${name}\" loops, so onEnd \"${st.onEnd}\" would never fire; set loop:false or drop onEnd`,\n );\n }\n if (st.onEnd !== undefined && !Object.hasOwn(graph.states, st.onEnd)) {\n throw new InvalidGraphError(`state \"${name}\" onEnd target \"${st.onEnd}\" is not declared`);\n }\n\n const cumulative: number[] = [];\n let running = 0;\n for (const key of frameKeys) {\n running += graph.frames?.[key]?.duration ?? defaultDuration;\n cumulative.push(running);\n }\n\n // `frameKeys` is aliased directly from `graph.animations[st.animation]`\n // without copying. The declared `readonly` typing makes mutation a\n // compile-time error for typed callers, but callers holding the raw JSON\n // object can mutate it at runtime. Callers must NOT mutate the atlas\n // `animations` arrays while a machine built from that graph is alive;\n // doing so desyncs `frameKeys` from the precomputed `cumulative` timings\n // and can cause `frameKeys[activeFrameIndex]` to yield `undefined`.\n states.set(name, { name, loop, speed, onEnd: st.onEnd, frameKeys, cumulative, total: running });\n }\n\n // --- compile transitions ------------------------------------------------\n const compiled: CompiledTransition[] = [];\n graph.transitions.forEach((t, order) => {\n if (!isObject(t as unknown)) {\n throw new InvalidGraphError(`transition #${order} must be an object`);\n }\n if (t.when !== undefined && !Array.isArray(t.when)) {\n throw new InvalidGraphError(`transition #${order} \"when\" must be an array`);\n }\n assertString(t.from, `transition #${order} \"from\"`);\n assertString(t.to, `transition #${order} \"to\"`);\n if (t.priority !== undefined && !Number.isInteger(t.priority)) {\n throw new InvalidGraphError(\n `transition #${order} priority must be an integer, got ${t.priority}`,\n );\n }\n if (t.from !== \"*\" && !Object.hasOwn(graph.states, t.from)) {\n throw new InvalidGraphError(`transition #${order} from \"${t.from}\" is not a declared state`);\n }\n if (!Object.hasOwn(graph.states, t.to)) {\n throw new InvalidGraphError(`transition #${order} to \"${t.to}\" is not a declared state`);\n }\n\n const conditions: ConditionFn[] = [];\n const triggers: string[] = [];\n for (const c of t.when ?? []) {\n // `?.`: a null / non-object condition fails the input-type check.\n assertString(\n (c as TransitionCondition | null)?.input,\n `transition #${order} condition \"input\"`,\n );\n assertString(c.op, `transition #${order} condition \"op\"`);\n const def = graph.inputs[c.input];\n if (def === undefined || !Object.hasOwn(graph.inputs, c.input)) {\n throw new InvalidGraphError(\n `transition #${order} condition references unknown input \"${c.input}\"`,\n );\n }\n compileCondition(order, c.input, c.op, c.value, def.type, conditions, triggers);\n }\n\n compiled.push({\n from: t.from,\n to: t.to,\n priority: t.priority ?? 0,\n order,\n conditions,\n triggers,\n });\n });\n\n // --- group candidates per state (own + Any-State), sorted ---------------\n const candidatesByState = new Map<string, readonly CompiledTransition[]>();\n for (const [name] of stateEntries) {\n const list = compiled.filter((t) => t.from === name || t.from === \"*\");\n // Stable by construction (declared order), but make the tie-break explicit.\n list.sort((a, b) => b.priority - a.priority || a.order - b.order);\n candidatesByState.set(name, list);\n }\n\n return { initial, states, candidatesByState };\n}\n\nfunction compileCondition(\n order: number,\n input: string,\n op: string,\n value: number | boolean | undefined,\n kind: \"number\" | \"boolean\" | \"trigger\",\n out: ConditionFn[],\n triggers: string[],\n): void {\n switch (op) {\n case \"Trigger\": {\n if (kind !== \"trigger\") {\n throw new InvalidGraphError(\n `transition #${order}: op Trigger requires a trigger input, but \"${input}\" is ${kind}`,\n );\n }\n if (value !== undefined) {\n throw new InvalidGraphError(\n `transition #${order}: Trigger condition on \"${input}\" must not carry a value`,\n );\n }\n out.push((s) => s.isPending(input));\n triggers.push(input);\n return;\n }\n case \"GreaterThan\":\n case \"LessThan\": {\n if (kind !== \"number\") {\n throw new InvalidGraphError(\n `transition #${order}: op ${op} requires a number input, but \"${input}\" is ${kind}`,\n );\n }\n if (typeof value !== \"number\") {\n throw new InvalidGraphError(\n `transition #${order}: op ${op} on \"${input}\" needs a numeric value`,\n );\n }\n const v = value;\n out.push(\n op === \"GreaterThan\" ? (s) => s.readNumber(input) > v : (s) => s.readNumber(input) < v,\n );\n return;\n }\n case \"Equals\":\n case \"NotEquals\": {\n if (kind === \"trigger\") {\n throw new InvalidGraphError(\n `transition #${order}: op ${op} cannot apply to trigger input \"${input}\"`,\n );\n }\n if (kind === \"number\") {\n if (typeof value !== \"number\") {\n throw new InvalidGraphError(\n `transition #${order}: op ${op} on number input \"${input}\" needs a numeric value`,\n );\n }\n const v = value;\n out.push(\n op === \"Equals\" ? (s) => s.readNumber(input) === v : (s) => s.readNumber(input) !== v,\n );\n return;\n }\n // kind === \"boolean\"\n if (typeof value !== \"boolean\") {\n throw new InvalidGraphError(\n `transition #${order}: op ${op} on boolean input \"${input}\" needs a boolean value`,\n );\n }\n const v = value;\n out.push(\n op === \"Equals\" ? (s) => s.readBoolean(input) === v : (s) => s.readBoolean(input) !== v,\n );\n return;\n }\n default:\n throw new InvalidGraphError(`transition #${order}: unknown operator \"${op}\"`);\n }\n}\n","// aispritejs — a tiny single-payload typed signal. This is the package's OWN\n// emitter; it deliberately does NOT import `aieventjs` or any sibling (P0\n// zero-cross-package rule). Two instances back `onStateChange` and\n// `onComplete`.\n\nimport type { ListenerOptions, Unsubscribe } from \"./types.js\";\n\n/**\n * A typed fan-out of one payload `P`. `emit` is allocation-free in the common\n * case; it snapshots listeners only when there is at least one, so a handler\n * that unsubscribes (or a `once` handler) cannot corrupt the in-flight\n * iteration. A listener removed during a dispatch is skipped for the rest of it.\n * If listeners throw, the rest still run and the first error is rethrown.\n */\nexport interface Signal<P> {\n on(handler: (payload: P) => void, options?: ListenerOptions): Unsubscribe;\n emit(payload: P): void;\n /** Drop every listener (used by `dispose`). */\n clear(): void;\n}\n\nexport function createSignal<P>(): Signal<P> {\n // Each listener maps to its cleanup function so clear() can detach abort\n // hooks as well as emptying the registry (fixes SPR-R-01).\n const listeners = new Map<(payload: P) => void, Unsubscribe>();\n\n function on(handler: (payload: P) => void, options?: ListenerOptions): Unsubscribe {\n const once = options?.once;\n const sig = options?.signal;\n // An already-aborted signal means the listener is dead on arrival.\n if (sig?.aborted) return () => {};\n\n let detachAbort: (() => void) | undefined;\n // One teardown shared by the unsubscribe return, the once-wrapper, and the\n // abort handler, so every path also detaches the abort listener — a `once`\n // handler that passed a `{ signal }` must not leave the abort listener\n // attached after it fires.\n const cleanup: Unsubscribe = () => {\n listeners.delete(wrapped);\n if (detachAbort) {\n detachAbort();\n detachAbort = undefined;\n }\n };\n\n // Always wrap, so every registration has its own identity in `listeners`\n // even when the same handler is subscribed more than once.\n const wrapped = (payload: P): void => {\n if (once) cleanup();\n handler(payload);\n };\n listeners.set(wrapped, cleanup);\n\n if (sig) {\n const onAbort = () => cleanup();\n sig.addEventListener(\"abort\", onAbort, { once: true });\n detachAbort = () => sig.removeEventListener(\"abort\", onAbort);\n }\n\n return cleanup;\n }\n\n function emit(payload: P): void {\n if (listeners.size === 0) return;\n // Snapshot so a handler that unsubscribes (including the once-wrapper)\n // during dispatch does not perturb this pass, but re-check membership so a\n // listener removed mid-dispatch (by a re-entrant emit that already fired a\n // once-wrapper, by dispose(), or by an aborted signal) is not called.\n // A throwing listener must not starve the rest: call every listener, then\n // rethrow the first error once the pass is complete.\n let failure: { error: unknown } | undefined;\n for (const fn of [...listeners.keys()]) {\n if (!listeners.has(fn)) continue;\n try {\n fn(payload);\n } catch (error) {\n failure ??= { error };\n }\n }\n if (failure) throw failure.error;\n }\n\n function clear(): void {\n // Run each cleanup so abort hooks are detached from caller AbortSignals\n // (SPR-R-01). Snapshot the values first because cleanup() mutates the map.\n // A throwing cleanup (e.g. a misbehaving AbortSignal.removeEventListener)\n // must not abort the iteration and must not prevent the map from being\n // fully emptied — mirror the aifsmjs dispose() try/catch + finally pattern.\n try {\n for (const cleanup of [...listeners.values()]) {\n try {\n cleanup();\n } catch {\n // Swallow per-cleanup errors; every registered cleanup must still run.\n }\n }\n } finally {\n // Guarantee an empty post-condition even if the loop itself somehow throws.\n listeners.clear();\n }\n }\n\n return { on, emit, clear };\n}\n","// aispritejs — the input store. Holds Number / Boolean values and Trigger\n// pending flags with O(1) lookup. All declared inputs are seeded at\n// construction so reads are total (the compiler guarantees every condition\n// references a declared input of the matching kind, so the non-null reads\n// below are sound).\n\nimport { InputTypeError, UnknownInputError } from \"./errors.js\";\nimport type { InputDef } from \"./types.js\";\n\nexport interface InputStore {\n /** Set a Number/Boolean input. Throws on unknown name or kind mismatch. */\n setInput(name: string, value: number | boolean): void;\n /** Mark a Trigger pending. Throws on unknown name or non-Trigger. */\n fireTrigger(name: string): void;\n /** Read a Number input (caller guarantees `name` is a declared Number). */\n readNumber(name: string): number;\n /** Read a Boolean input (caller guarantees `name` is a declared Boolean). */\n readBoolean(name: string): boolean;\n /** Whether a Trigger is currently pending. */\n isPending(name: string): boolean;\n /** Consume (reset) a pending Trigger after a transition takes it. */\n consume(name: string): void;\n /** Restore every input to its declared default and clear all triggers. */\n reset(): void;\n}\n\ntype Kind = \"number\" | \"boolean\" | \"trigger\";\n\nexport function createInputStore(inputs: Readonly<Record<string, InputDef>>): InputStore {\n const kinds = new Map<string, Kind>();\n const numberDefaults = new Map<string, number>();\n const booleanDefaults = new Map<string, boolean>();\n const numbers = new Map<string, number>();\n const booleans = new Map<string, boolean>();\n const triggers = new Map<string, boolean>();\n\n for (const [name, def] of Object.entries(inputs)) {\n kinds.set(name, def.type);\n if (def.type === \"number\") {\n const d = def.default ?? 0;\n numberDefaults.set(name, d);\n numbers.set(name, d);\n } else if (def.type === \"boolean\") {\n const d = def.default ?? false;\n booleanDefaults.set(name, d);\n booleans.set(name, d);\n } else {\n triggers.set(name, false);\n }\n }\n\n function setInput(name: string, value: number | boolean): void {\n const kind = kinds.get(name);\n if (kind === undefined) throw new UnknownInputError(name);\n if (kind === \"trigger\") {\n throw new InputTypeError(name, \"is a Trigger; use fireTrigger()\");\n }\n if (kind === \"number\") {\n if (typeof value !== \"number\") {\n throw new InputTypeError(name, `expects a number, received ${typeof value}`);\n }\n if (Number.isNaN(value)) {\n throw new InputTypeError(name, \"cannot be set to NaN\");\n }\n numbers.set(name, value);\n return;\n }\n // kind === \"boolean\"\n if (typeof value !== \"boolean\") {\n throw new InputTypeError(name, `expects a boolean, received ${typeof value}`);\n }\n booleans.set(name, value);\n }\n\n function fireTrigger(name: string): void {\n const kind = kinds.get(name);\n if (kind === undefined) throw new UnknownInputError(name);\n if (kind !== \"trigger\") {\n throw new InputTypeError(name, \"is not a Trigger; use setInput()\");\n }\n triggers.set(name, true);\n }\n\n // `!` is sound: every declared input is seeded at construction and the\n // compiler validates that conditions only read declared inputs of the\n // matching kind, so these reads always hit a present entry.\n return {\n setInput,\n fireTrigger,\n readNumber: (name) => numbers.get(name)!,\n readBoolean: (name) => booleans.get(name)!,\n isPending: (name) => triggers.get(name) === true,\n consume: (name) => {\n triggers.set(name, false);\n },\n reset: () => {\n for (const [name, d] of numberDefaults) numbers.set(name, d);\n for (const [name, d] of booleanDefaults) booleans.set(name, d);\n for (const name of triggers.keys()) triggers.set(name, false);\n },\n };\n}\n","// aispritejs — the input-driven visual state machine (the \"RiveSpriteStateMachine\"\n// engine), exposed only through the `createSpriteAnimator` factory. Implemented\n// as closures, not a class, so methods never depend on `this` and the\n// constructor surface stays hidden (family convention: public API = createX).\n//\n// Determinism: the only state advanced by `update` is `elapsed` (by `dt * speed`)\n// plus the input store; transitions are resolved over precomputed, deterministically\n// ordered candidate lists. Identical input + dt sequences therefore yield identical\n// frame sequences. The no-transition path allocates nothing.\n//\n// Run-to-completion: `update()` / `reset()` own the machine's state, so a call\n// made while one is already dispatching (from an `onStateChange` / `onComplete`\n// listener) is queued in a FIFO mailbox and runs after the current call's last\n// notification (ai*js family rule for state-owning dispatchers).\n\nimport { type CompiledState, type CompiledTransition, compileGraph } from \"./compile.js\";\nimport { createSignal } from \"./emitter.js\";\nimport { SpriteAnimatorDisposedError } from \"./errors.js\";\nimport { createInputStore } from \"./inputs.js\";\nimport type {\n CompleteHandler,\n ListenerOptions,\n SpriteAnimator,\n SpriteGraph,\n StateChangeHandler,\n Unsubscribe,\n} from \"./types.js\";\n\ninterface StateChangePayload {\n readonly to: string;\n readonly from: string;\n}\n\nconst NO_TRIGGERS: readonly string[] = [];\n\n/** A nested `update()` / `reset()` waiting for the current dispatch to finish. */\ntype Queued = { readonly kind: \"update\"; readonly dt: number } | { readonly kind: \"reset\" };\n\n/**\n * Build a renderer-agnostic visual animator from an input-driven graph.\n *\n * @param graph - inputs, states, transitions, animations (+ optional per-frame\n * timings). Validated eagerly; an invalid graph throws {@link InvalidGraphError}\n * and no animator is returned.\n * @returns a {@link SpriteAnimator}.\n *\n * @public\n */\nexport function createSpriteAnimator(graph: SpriteGraph): SpriteAnimator {\n const compiled = compileGraph(graph);\n const store = createInputStore(graph.inputs);\n const stateChange = createSignal<StateChangePayload>();\n const complete = createSignal<string>();\n\n let current: CompiledState = mustState(compiled.initial);\n let elapsed = 0;\n let completed = false;\n let activeFrameIndex = 0;\n // Every compiled state has >= 1 frame (validated), so frame 0 always exists.\n let activeFrameKey: string = current.frameKeys[0]!;\n let disposed = false;\n let dispatching = false;\n const mailbox: Queued[] = [];\n\n // `name` is always an initial / transition `to` / `onEnd` target, all\n // validated to exist by compileGraph, so the lookup never misses.\n function mustState(name: string): CompiledState {\n return compiled.states.get(name)!;\n }\n\n /** Enter `to`, optionally consuming the triggers the taking transition used. */\n function enter(to: string, consume: readonly string[]): void {\n const from = current.name;\n for (let i = 0; i < consume.length; i++) {\n store.consume(consume[i]!);\n }\n current = mustState(to);\n elapsed = 0;\n completed = false;\n activeFrameIndex = 0;\n activeFrameKey = current.frameKeys[0]!;\n // A self-re-entry (to === from) restarts the clip but is not a state change.\n if (to !== from) stateChange.emit({ to, from });\n }\n\n /**\n * First *effective* transition leaving `current` (own + Any-State), in\n * (priority desc, declared order) — or `undefined`. A transition whose target\n * equals the current state is effective only if it consumes a Trigger (a\n * Number/Boolean self-loop would otherwise restart the clip every frame).\n */\n function resolve(): CompiledTransition | undefined {\n // Every state has a candidate list (built for all states by compileGraph).\n const list = compiled.candidatesByState.get(current.name)!;\n for (let i = 0; i < list.length; i++) {\n const t = list[i]!;\n let ok = true;\n const conds = t.conditions;\n for (let j = 0; j < conds.length; j++) {\n if (!conds[j]!(store)) {\n ok = false;\n break;\n }\n }\n if (!ok) continue;\n if (t.to === current.name && t.triggers.length === 0) continue;\n return t;\n }\n return undefined;\n }\n\n function processUpdate(deltaMs: number): void {\n // Advance the playback timer (non-finite or non-positive dt clamped to 0 for determinism).\n // NOTE: `elapsed` accumulates without bound in looping states (intentional design choice).\n // Drift from floating-point accumulation is sub-ULP-relevant only after continuous play\n // on the order of years; a periodic reset (e.g. on state entry) would be premature.\n // A step that would overflow `elapsed` to Infinity (whose `% total` is NaN) is\n // dropped: clamped to no progress, like an invalid dt.\n const next = elapsed + (Number.isFinite(deltaMs) && deltaMs > 0 ? deltaMs : 0) * current.speed;\n if (Number.isFinite(next)) elapsed = next;\n\n // Evaluate input-driven transitions first; an explicit transition wins over\n // implicit end-of-clip behaviour.\n const chosen = resolve();\n if (chosen) {\n enter(chosen.to, chosen.triggers);\n return;\n }\n\n // Compute the active frame from accumulated time vs cumulative durations.\n const cs = current;\n const n = cs.frameKeys.length;\n let ended = false;\n if (!cs.loop && elapsed >= cs.total) {\n activeFrameIndex = n - 1;\n ended = true;\n } else {\n const t = cs.loop ? elapsed % cs.total : elapsed;\n let i = 0;\n // First index whose cumulative end exceeds t (i < n-1 keeps it in range,\n // and t < total guarantees a match no later than the last frame).\n while (i < n - 1 && t >= cs.cumulative[i]!) i++;\n activeFrameIndex = i;\n }\n activeFrameKey = cs.frameKeys[activeFrameIndex]!;\n\n // Fire onComplete once for a finished non-looping clip, then auto-transition.\n if (ended && !completed) {\n completed = true;\n try {\n complete.emit(cs.name);\n } finally {\n // A reset() / update() from an onComplete handler is queued (it runs\n // after this), so only dispose() can intervene here. Runs in `finally`\n // so a throwing handler cannot wedge the machine on its last frame\n // (`completed` is already set, so no later tick would).\n if (cs.onEnd !== undefined && !disposed) enter(cs.onEnd, NO_TRIGGERS);\n }\n }\n }\n\n function processReset(): void {\n store.reset();\n // Restarts the initial clip; notifies only if the state actually changes.\n enter(compiled.initial, NO_TRIGGERS);\n }\n\n /**\n * Run `first(dt)` to completion, then drain the calls its listeners queued,\n * in order. dispose() empties the mailbox, which ends the drain. A throw drops\n * whatever is still queued and propagates from this (outermost) call. Takes\n * `dt` separately so the per-frame path allocates no closure.\n */\n function run(first: (dt: number) => void, dt: number): void {\n dispatching = true;\n try {\n first(dt);\n while (mailbox.length > 0) {\n const m = mailbox.shift()!;\n if (m.kind === \"update\") processUpdate(m.dt);\n else processReset();\n }\n } finally {\n dispatching = false;\n mailbox.length = 0;\n }\n }\n\n function update(deltaMs: number): void {\n if (disposed) throw new SpriteAnimatorDisposedError();\n if (dispatching) mailbox.push({ kind: \"update\", dt: deltaMs });\n else run(processUpdate, deltaMs);\n }\n\n function reset(): void {\n if (disposed) throw new SpriteAnimatorDisposedError();\n if (dispatching) mailbox.push({ kind: \"reset\" });\n else run(processReset, 0);\n }\n\n function dispose(): void {\n if (disposed) return;\n disposed = true;\n mailbox.length = 0;\n stateChange.clear();\n complete.clear();\n }\n\n return {\n setInput(name, value) {\n if (disposed) throw new SpriteAnimatorDisposedError();\n store.setInput(name, value);\n },\n fireTrigger(name) {\n if (disposed) throw new SpriteAnimatorDisposedError();\n store.fireTrigger(name);\n },\n update,\n reset,\n dispose,\n onStateChange(handler: StateChangeHandler, options?: ListenerOptions): Unsubscribe {\n if (disposed) return () => {};\n return stateChange.on((p) => handler(p.to, p.from), options);\n },\n onComplete(handler: CompleteHandler, options?: ListenerOptions): Unsubscribe {\n if (disposed) return () => {};\n return complete.on(handler, options);\n },\n get activeState() {\n return current.name;\n },\n get activeFrameKey() {\n return activeFrameKey;\n },\n get activeFrameIndex() {\n return activeFrameIndex;\n },\n get disposed() {\n return disposed;\n },\n };\n}\n"]}
package/dist/index.cjs CHANGED
@@ -1,28 +1,28 @@
1
1
  'use strict';
2
2
 
3
- var chunkQF5N7LOI_cjs = require('./chunk-QF5N7LOI.cjs');
3
+ var chunkGEQWS7FY_cjs = require('./chunk-GEQWS7FY.cjs');
4
4
 
5
5
 
6
6
 
7
7
  Object.defineProperty(exports, "InputTypeError", {
8
8
  enumerable: true,
9
- get: function () { return chunkQF5N7LOI_cjs.InputTypeError; }
9
+ get: function () { return chunkGEQWS7FY_cjs.InputTypeError; }
10
10
  });
11
11
  Object.defineProperty(exports, "InvalidGraphError", {
12
12
  enumerable: true,
13
- get: function () { return chunkQF5N7LOI_cjs.InvalidGraphError; }
13
+ get: function () { return chunkGEQWS7FY_cjs.InvalidGraphError; }
14
14
  });
15
15
  Object.defineProperty(exports, "SpriteAnimatorDisposedError", {
16
16
  enumerable: true,
17
- get: function () { return chunkQF5N7LOI_cjs.SpriteAnimatorDisposedError; }
17
+ get: function () { return chunkGEQWS7FY_cjs.SpriteAnimatorDisposedError; }
18
18
  });
19
19
  Object.defineProperty(exports, "UnknownInputError", {
20
20
  enumerable: true,
21
- get: function () { return chunkQF5N7LOI_cjs.UnknownInputError; }
21
+ get: function () { return chunkGEQWS7FY_cjs.UnknownInputError; }
22
22
  });
23
23
  Object.defineProperty(exports, "createSpriteAnimator", {
24
24
  enumerable: true,
25
- get: function () { return chunkQF5N7LOI_cjs.createSpriteAnimator; }
25
+ get: function () { return chunkGEQWS7FY_cjs.createSpriteAnimator; }
26
26
  });
27
27
  //# sourceMappingURL=index.cjs.map
28
28
  //# sourceMappingURL=index.cjs.map
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { b as SpriteGraph, a as SpriteAnimator } from './types-BS72pefJ.cjs';
2
- export { B as BooleanInputDef, C as CompleteHandler, c as ConditionOp, F as FrameTiming, I as InputDef, L as ListenerOptions, N as NumberInputDef, d as StateChangeHandler, S as StateDef, e as TransitionCondition, T as TransitionDef, f as TriggerInputDef, U as Unsubscribe } from './types-BS72pefJ.cjs';
1
+ import { b as SpriteGraph, a as SpriteAnimator } from './types-Dr7yXTRQ.cjs';
2
+ export { B as BooleanInputDef, C as CompleteHandler, c as ConditionOp, F as FrameTiming, I as InputDef, L as ListenerOptions, N as NumberInputDef, d as StateChangeHandler, S as StateDef, e as TransitionCondition, T as TransitionDef, f as TriggerInputDef, U as Unsubscribe } from './types-Dr7yXTRQ.cjs';
3
3
 
4
4
  /**
5
5
  * Build a renderer-agnostic visual animator from an input-driven graph.
@@ -23,8 +23,10 @@ declare class SpriteAnimatorDisposedError extends Error {
23
23
  constructor();
24
24
  }
25
25
  /**
26
- * Thrown by `createSpriteAnimator` when the graph fails validation — a state
27
- * references a missing animation, a transition points at an unknown state, a
26
+ * Thrown by `createSpriteAnimator` when the graph fails validation — the graph
27
+ * or one of its blocks has the wrong shape, a state/transition/condition
28
+ * identifier is not a string, a state references a missing animation, a
29
+ * transition points at an unknown state or has a non-integer priority, a
28
30
  * condition uses an operator the input kind does not support, a duration is
29
31
  * non-positive, and so on. Fail-fast: an invalid graph never produces a
30
32
  * half-built animator.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { b as SpriteGraph, a as SpriteAnimator } from './types-BS72pefJ.js';
2
- export { B as BooleanInputDef, C as CompleteHandler, c as ConditionOp, F as FrameTiming, I as InputDef, L as ListenerOptions, N as NumberInputDef, d as StateChangeHandler, S as StateDef, e as TransitionCondition, T as TransitionDef, f as TriggerInputDef, U as Unsubscribe } from './types-BS72pefJ.js';
1
+ import { b as SpriteGraph, a as SpriteAnimator } from './types-Dr7yXTRQ.js';
2
+ export { B as BooleanInputDef, C as CompleteHandler, c as ConditionOp, F as FrameTiming, I as InputDef, L as ListenerOptions, N as NumberInputDef, d as StateChangeHandler, S as StateDef, e as TransitionCondition, T as TransitionDef, f as TriggerInputDef, U as Unsubscribe } from './types-Dr7yXTRQ.js';
3
3
 
4
4
  /**
5
5
  * Build a renderer-agnostic visual animator from an input-driven graph.
@@ -23,8 +23,10 @@ declare class SpriteAnimatorDisposedError extends Error {
23
23
  constructor();
24
24
  }
25
25
  /**
26
- * Thrown by `createSpriteAnimator` when the graph fails validation — a state
27
- * references a missing animation, a transition points at an unknown state, a
26
+ * Thrown by `createSpriteAnimator` when the graph fails validation — the graph
27
+ * or one of its blocks has the wrong shape, a state/transition/condition
28
+ * identifier is not a string, a state references a missing animation, a
29
+ * transition points at an unknown state or has a non-integer priority, a
28
30
  * condition uses an operator the input kind does not support, a duration is
29
31
  * non-positive, and so on. Fail-fast: an invalid graph never produces a
30
32
  * half-built animator.
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- export { InputTypeError, InvalidGraphError, SpriteAnimatorDisposedError, UnknownInputError, createSpriteAnimator } from './chunk-6E4ILDBY.js';
1
+ export { InputTypeError, InvalidGraphError, SpriteAnimatorDisposedError, UnknownInputError, createSpriteAnimator } from './chunk-NBMU2UNJ.js';
2
2
  //# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkQF5N7LOI_cjs = require('../chunk-QF5N7LOI.cjs');
3
+ var chunkGEQWS7FY_cjs = require('../chunk-GEQWS7FY.cjs');
4
4
 
5
5
  // src/pixi/animator.ts
6
6
  var MissingTextureError = class extends Error {
@@ -13,26 +13,28 @@ var MissingTextureError = class extends Error {
13
13
  };
14
14
  function toTextureMap(src) {
15
15
  const maybe = src;
16
- if (maybe.textures && typeof maybe.textures === "object") {
16
+ if (maybe?.textures && typeof maybe.textures === "object") {
17
17
  return maybe.textures;
18
18
  }
19
- return src;
19
+ return src ?? {};
20
20
  }
21
21
  function createPixiSpriteAnimator(sprite, graph, textures, options) {
22
+ chunkGEQWS7FY_cjs.assertGraphShape(graph);
22
23
  const map = toTextureMap(textures);
23
24
  const applyAnchor = options?.applyAnchor !== false;
24
- const playable = sprite;
25
- if (typeof playable.stop === "function") playable.stop();
26
25
  const missing = /* @__PURE__ */ new Set();
27
26
  for (const frameKeys of Object.values(graph.animations)) {
28
27
  for (const key of frameKeys) {
29
- if (!Object.hasOwn(map, key)) missing.add(key);
28
+ if (!Object.hasOwn(map, key) || map[key] == null) missing.add(key);
30
29
  }
31
30
  }
32
31
  if (missing.size > 0) throw new MissingTextureError([...missing]);
33
- const core = chunkQF5N7LOI_cjs.createSpriteAnimator(graph);
34
- let boundKey = "";
32
+ const core = chunkGEQWS7FY_cjs.createSpriteAnimator(graph);
33
+ const playable = sprite;
34
+ if (typeof playable.stop === "function") playable.stop();
35
+ let boundKey;
35
36
  function sync() {
37
+ if (core.disposed) return;
36
38
  const key = core.activeFrameKey;
37
39
  if (key === boundKey) return;
38
40
  boundKey = key;
@@ -46,8 +48,11 @@ function createPixiSpriteAnimator(sprite, graph, textures, options) {
46
48
  return {
47
49
  sprite,
48
50
  update(deltaMs) {
49
- core.update(deltaMs);
50
- sync();
51
+ try {
52
+ core.update(deltaMs);
53
+ } finally {
54
+ sync();
55
+ }
51
56
  },
52
57
  setInput(name, value) {
53
58
  core.setInput(name, value);
@@ -56,8 +61,11 @@ function createPixiSpriteAnimator(sprite, graph, textures, options) {
56
61
  core.fireTrigger(name);
57
62
  },
58
63
  reset() {
59
- core.reset();
60
- sync();
64
+ try {
65
+ core.reset();
66
+ } finally {
67
+ sync();
68
+ }
61
69
  },
62
70
  dispose() {
63
71
  core.dispose();