canvasengine 2.0.0-beta.7 → 2.0.0-beta.9

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": "canvasengine",
3
- "version": "2.0.0-beta.7",
3
+ "version": "2.0.0-beta.9",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -170,7 +170,7 @@ export function DisplayObject(extendClass) {
170
170
  effect(() => {
171
171
  setter(parentSize() * (parseInt(size) / 100));
172
172
  if (this.isFlex) {
173
- this.#applyFlexLayout();
173
+ this.applyFlexLayout();
174
174
  }
175
175
  });
176
176
  } else {
@@ -188,7 +188,7 @@ export function DisplayObject(extendClass) {
188
188
  );
189
189
  }
190
190
 
191
- #applyFlexLayout() {
191
+ applyFlexLayout() {
192
192
  this.calculateLayout();
193
193
  for (let child of this.children) {
194
194
  const { left, top } = child.node.getComputedLayout();
@@ -201,7 +201,7 @@ export function DisplayObject(extendClass) {
201
201
  if (!this.parent) return;
202
202
  if (props.flexDirection || props.justifyContent) {
203
203
  this.isFlex = true;
204
- this.#applyFlexLayout();
204
+ this.applyFlexLayout();
205
205
  }
206
206
  }
207
207
 
@@ -65,8 +65,8 @@ class CanvasText extends DisplayObject(PixiText) {
65
65
  this.typewriterOptions = props.typewriter;
66
66
  }
67
67
  }
68
- if (props.text) {
69
- this.text = props.text;
68
+ if (props.text !== undefined) {
69
+ this.text = ''+props.text;
70
70
  }
71
71
  if (props.text !== undefined && props.text !== this.fullText && this.fullProps.typewriter) {
72
72
  this.text = "";
@@ -1,10 +1,11 @@
1
1
  import { effect, signal, type WritableSignal } from "@signe/reactive";
2
2
  import { animate as animatePopmotion } from "popmotion";
3
3
 
4
- interface AnimateOptions<T> {
4
+ export interface AnimateOptions<T> {
5
5
  duration?: number;
6
6
  ease?: (t: number) => number;
7
7
  onUpdate?: (value: T) => void;
8
+ onComplete?: () => void;
8
9
  }
9
10
 
10
11
  export interface AnimatedState<T> {
@@ -15,7 +16,7 @@ export interface AnimatedState<T> {
15
16
 
16
17
  export interface AnimatedSignal<T> extends Omit<WritableSignal<T>, 'set'> {
17
18
  (): T;
18
- set: (newValue: T) => void;
19
+ set: (newValue: T, options?: AnimateOptions<T>) => Promise<void>;
19
20
  animatedState: WritableSignal<AnimatedState<T>>;
20
21
  update: (updater: (value: T) => T) => void;
21
22
  }
@@ -60,7 +61,8 @@ export function animatedSignal<T>(initialValue: T, options: AnimateOptions<T> =
60
61
 
61
62
  function animatedSignal(): AnimatedState<T>;
62
63
  function animatedSignal(newValue: T): void;
63
- function animatedSignal(newValue?: T): AnimatedState<T> | void {
64
+ function animatedSignal(newValue: T, animationConfig: AnimateOptions<T>): void;
65
+ function animatedSignal(newValue?: T, animationConfig: AnimateOptions<T> = {}): AnimatedState<T> | void {
64
66
  if (newValue === undefined) {
65
67
  return privateSignal();
66
68
  }
@@ -82,6 +84,7 @@ export function animatedSignal<T>(initialValue: T, options: AnimateOptions<T> =
82
84
  // TODO
83
85
  duration: 20,
84
86
  ...options,
87
+ ...animationConfig,
85
88
  from: prevState.current,
86
89
  to: newValue,
87
90
  onUpdate: (value) => {
@@ -105,9 +108,42 @@ export function animatedSignal<T>(initialValue: T, options: AnimateOptions<T> =
105
108
  fn.update = (updater: (value: T) => any) => {
106
109
  animatedSignal(updater(privateSignal().current));
107
110
  }
108
- fn.set = (newValue: T) => {
109
- animatedSignal(newValue);
111
+ fn.set = async (newValue: T, animationConfig: AnimateOptions<T> = {}) => {
112
+ return new Promise<void>((resolve) => {
113
+ animatedSignal(newValue, {
114
+ ...animationConfig,
115
+ onComplete: resolve
116
+ });
117
+ })
110
118
  }
111
119
 
112
120
  return fn as any
121
+ }
122
+
123
+ /**
124
+ * Executes a sequence of animations. If an array is provided as an element in the sequence,
125
+ * those animations will be executed in parallel.
126
+ *
127
+ * @param sequence Array of animation functions or arrays of animation functions for parallel execution
128
+ * @returns Promise that resolves when all animations are complete
129
+ * @example
130
+ * ```ts
131
+ * await animatedSequence([
132
+ * () => value1.set(10),
133
+ * [
134
+ * () => value2.set(20),
135
+ * () => value3.set(30)
136
+ * ],
137
+ * () => value1.set(0)
138
+ * ])
139
+ * ```
140
+ */
141
+ export async function animatedSequence(sequence: ((() => Promise<void>) | (() => Promise<void>)[])[]) {
142
+ for (const item of sequence) {
143
+ if (Array.isArray(item)) {
144
+ await Promise.all(item.map(fn => fn()));
145
+ } else {
146
+ await item();
147
+ }
148
+ }
113
149
  }
@@ -344,9 +344,8 @@ export function loop<T>(
344
344
  }
345
345
  };
346
346
 
347
- const { items, keys } = getInitialItems();
348
-
349
347
  return defer(() => {
348
+ const { items, keys } = getInitialItems();
350
349
  let initialItems = [...items];
351
350
  let initialKeys = keys ? [...keys] : undefined;
352
351
  let init = true;
@@ -354,8 +353,7 @@ export function loop<T>(
354
353
  map((event: ArrayChange<T> | ObjectChange<T>): FlowResult => {
355
354
  const { type, items } = event;
356
355
  const index = 'index' in event ? event.index : (event as ObjectChange<T>).key;
357
-
358
- if (init) {
356
+ if (init && type != "add") {
359
357
  if (elements.length > 0) {
360
358
  return {
361
359
  elements: elements,
@@ -410,6 +408,7 @@ export function loop<T>(
410
408
  // For array updates, use addAt with the items array
411
409
  newElements = addAt(items as T[], index);
412
410
  }
411
+ init = false;
413
412
  return {
414
413
  prev: lastElement,
415
414
  elements: newElements,