partforge 0.44.0 → 0.46.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.
package/types/part.d.ts CHANGED
@@ -297,11 +297,18 @@ export type Easing = "linear" | "ease-in" | "ease-out" | "ease-in-out";
297
297
  export type Keyframes = Array<[number, number]>;
298
298
 
299
299
  /**
300
- * A camera cue angle: one of the seven canonical angles (`CanonicalView` in the
301
- * app entry `"iso" | "front" | "back" | "top" | "bottom" | "left" | "right"`).
302
- * Cues fire during play only; scrubbing never moves the camera.
300
+ * The seven angles the viewer can frame a part from. Defined here rather than in
301
+ * the app entry so `CameraCue` can be the real union without an import cycle
302
+ * the app entry re-exports it under its own name.
303
303
  */
304
- export type CameraCue = string;
304
+ export type CanonicalView = "iso" | "front" | "back" | "left" | "right" | "top" | "bottom";
305
+
306
+ /**
307
+ * A camera cue angle. `partforge lint` rejects anything outside the canonical
308
+ * seven (`animation-camera-invalid`), so the type says so too. Cues fire during
309
+ * play only; scrubbing never moves the camera.
310
+ */
311
+ export type CameraCue = CanonicalView;
305
312
 
306
313
  /** One step of a multi-step animation. Steps play in order; prev/next navigate them. */
307
314
  export interface AnimationStep {
@@ -310,31 +317,31 @@ export interface AnimationStep {
310
317
  /** Seconds. Step durations are relative — they set each step's share of the timeline. */
311
318
  duration: number;
312
319
  easing?: Easing;
313
- /** Param key -> keyframes. A param tracked nowhere keeps its current value. */
314
- tracks: Record<string, Keyframes>;
320
+ /**
321
+ * Param key -> keyframes. A param tracked nowhere keeps its current value.
322
+ *
323
+ * Optional so a step can move only the camera — an establishing shot that
324
+ * holds the pose while the view swings round. `partforge lint` still requires
325
+ * that at least one step in the animation carries tracks, which is a
326
+ * whole-animation rule the type system can't express per step.
327
+ */
328
+ tracks?: Record<string, Keyframes>;
315
329
  /** Swing the camera to this angle when the step begins. */
316
330
  camera?: CameraCue;
317
331
  }
318
332
 
319
333
  /**
320
- * One named animation: pure keyframe data over EXISTING params. Declare either
321
- * `tracks` (one anonymous step) or `steps`, never both. See
322
- * docs/AUTHORING-PARTS.md "Animations".
334
+ * The fields both animation forms share. Exported so a host can extend it —
335
+ * `AnimationSpec` itself is a union and cannot be `extends`-ed.
323
336
  */
324
- export interface AnimationSpec {
337
+ export interface AnimationSpecCommon {
325
338
  /** Shown in the transport bar's picker. Defaults to the animation's key. */
326
339
  label?: string;
327
340
  /** CommonMark, shown behind the ⓘ glyph. */
328
341
  description?: string;
329
- /** Seconds. Required in the single-step (`tracks`) form. */
330
- duration?: number;
331
342
  easing?: Easing;
332
343
  /** Wrap continuously. Single-step animations only. */
333
344
  loop?: boolean;
334
- /** The single-step form: param key -> keyframes. */
335
- tracks?: Record<string, Keyframes>;
336
- /** The multi-step form. */
337
- steps?: AnimationStep[];
338
345
  /**
339
346
  * One mechanism per animation: an angle (an intro cue at t=0), a
340
347
  * `[[t, angle], …]` cue list, or per-step `camera` names.
@@ -350,6 +357,27 @@ export interface AnimationSpec {
350
357
  autoplay?: boolean;
351
358
  }
352
359
 
360
+ /**
361
+ * An animation is EITHER single-phase (`tracks` + `duration`) OR stepped
362
+ * (`steps`) — never both, never neither. `partforge lint` enforces that
363
+ * (`animation-tracks-or-steps`), and the union says the same thing, so a block
364
+ * carrying both is rejected before it ever reaches lint.
365
+ */
366
+ export type AnimationSpec =
367
+ | (AnimationSpecCommon & {
368
+ /** Seconds — the whole animation's duration in the single-phase form. */
369
+ duration: number;
370
+ /** Param key -> keyframes. */
371
+ tracks: Record<string, Keyframes>;
372
+ steps?: never;
373
+ })
374
+ | (AnimationSpecCommon & {
375
+ /** The multi-step form; each step carries its own relative `duration`. */
376
+ steps: AnimationStep[];
377
+ tracks?: never;
378
+ duration?: never;
379
+ });
380
+
353
381
  // --- the part itself --------------------------------------------------------
354
382
 
355
383
  /**