canvasengine 2.0.0-beta.6 → 2.0.0-beta.8

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/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _signe_reactive from '@signe/reactive';
2
- import { WritableSignal, Signal, WritableArraySignal } from '@signe/reactive';
2
+ import { WritableSignal, Signal, WritableArraySignal, WritableObjectSignal } from '@signe/reactive';
3
3
  export * from '@signe/reactive';
4
4
  import { Subscription, Subject, Observable } from 'rxjs';
5
5
  export { isObservable } from 'rxjs';
@@ -13,6 +13,7 @@ interface AnimateOptions<T> {
13
13
  duration?: number;
14
14
  ease?: (t: number) => number;
15
15
  onUpdate?: (value: T) => void;
16
+ onComplete?: () => void;
16
17
  }
17
18
  interface AnimatedState<T> {
18
19
  current: T;
@@ -21,7 +22,7 @@ interface AnimatedState<T> {
21
22
  }
22
23
  interface AnimatedSignal<T> extends Omit<WritableSignal<T>, 'set'> {
23
24
  (): T;
24
- set: (newValue: T) => void;
25
+ set: (newValue: T, options?: AnimateOptions<T>) => Promise<void>;
25
26
  animatedState: WritableSignal<AnimatedState<T>>;
26
27
  update: (updater: (value: T) => T) => void;
27
28
  }
@@ -45,6 +46,25 @@ declare function isAnimatedSignal(signal: WritableSignal<any>): boolean;
45
46
  * animatedValue.animatedState() // { current: 10, start: 10, end: 11 }
46
47
  */
47
48
  declare function animatedSignal<T>(initialValue: T, options?: AnimateOptions<T>): AnimatedSignal<T>;
49
+ /**
50
+ * Executes a sequence of animations. If an array is provided as an element in the sequence,
51
+ * those animations will be executed in parallel.
52
+ *
53
+ * @param sequence Array of animation functions or arrays of animation functions for parallel execution
54
+ * @returns Promise that resolves when all animations are complete
55
+ * @example
56
+ * ```ts
57
+ * await animatedSequence([
58
+ * () => value1.set(10),
59
+ * [
60
+ * () => value2.set(20),
61
+ * () => value3.set(30)
62
+ * ],
63
+ * () => value1.set(0)
64
+ * ])
65
+ * ```
66
+ */
67
+ declare function animatedSequence(sequence: ((() => Promise<void>) | (() => Promise<void>)[])[]): Promise<void>;
48
68
 
49
69
  type SignalOrPrimitive<T> = T | Signal<T> | AnimatedSignal<T>;
50
70
 
@@ -157,7 +177,7 @@ declare function DisplayObject(extendClass: any): {
157
177
  onInit(props: any): void;
158
178
  onMount({ parent, props }: Element</*elided*/ any>, index?: number): void;
159
179
  effectSize(width: Size, height: Size): void;
160
- "__#1@#applyFlexLayout"(): void;
180
+ applyFlexLayout(): void;
161
181
  "__#1@#flexRender"(props: any): void;
162
182
  onUpdate(props: any): void;
163
183
  onDestroy(): void;
@@ -204,6 +224,12 @@ type ArrayChange<T> = {
204
224
  index?: number;
205
225
  items: T[];
206
226
  };
227
+ type ObjectChange<T> = {
228
+ type: "add" | "remove" | "update" | "init" | "reset";
229
+ key?: string;
230
+ value?: T;
231
+ items: T[];
232
+ };
207
233
  type NestedSignalObjects = {
208
234
  [Key in string]: NestedSignalObjects | Signal<any>;
209
235
  };
@@ -226,10 +252,12 @@ interface Element<T = ComponentInstance> {
226
252
  destroy: () => void;
227
253
  allElements: Subject<void>;
228
254
  }
229
- type FlowObservable = Observable<{
255
+ type FlowResult = {
230
256
  elements: Element[];
231
257
  prev?: Element;
232
- }>;
258
+ fullElements?: Element[];
259
+ };
260
+ type FlowObservable = Observable<FlowResult>;
233
261
  declare const isElement: (value: any) => value is Element;
234
262
  declare const isPrimitive: (value: any) => boolean;
235
263
  declare function registerComponent(name: any, component: any): void;
@@ -245,13 +273,13 @@ declare function registerComponent(name: any, component: any): void;
245
273
  */
246
274
  declare function createComponent(tag: string, props?: Props): Element;
247
275
  /**
248
- * Observes a BehaviorSubject containing an array of items and dynamically creates child elements for each item.
276
+ * Observes a BehaviorSubject containing an array or object of items and dynamically creates child elements for each item.
249
277
  *
250
- * @param {BehaviorSubject<Array>} itemsSubject - A BehaviorSubject that emits an array of items.
278
+ * @param {WritableArraySignal<T> | WritableObjectSignal<T>} itemsSubject - A signal that emits an array or object of items.
251
279
  * @param {Function} createElementFn - A function that takes an item and returns an element representation.
252
280
  * @returns {Observable} An observable that emits the list of created child elements.
253
281
  */
254
- declare function loop<T = any>(itemsSubject: WritableArraySignal<T>, createElementFn: (item: any, index: number) => Element | Promise<Element>): FlowObservable;
282
+ declare function loop<T>(itemsSubject: WritableArraySignal<T[]> | WritableObjectSignal<T>, createElementFn: (item: T, index: number | string) => Element | null): FlowObservable;
255
283
  /**
256
284
  * Conditionally creates and destroys elements based on a condition signal.
257
285
  *
@@ -1106,4 +1134,4 @@ declare namespace utils {
1106
1134
  export { utils_arrayEquals as arrayEquals, utils_calculateDistance as calculateDistance, utils_error as error, utils_fps2ms as fps2ms, utils_get as get, utils_isBrowser as isBrowser, utils_isFunction as isFunction, utils_isObject as isObject, utils_isPromise as isPromise, utils_log as log, utils_preciseNow as preciseNow, utils_set as set, utils_setObservablePoint as setObservablePoint };
1107
1135
  }
1108
1136
 
1109
- export { type AnimatedSignal, type AnimatedState, type ArrayChange, Canvas, Circle, type ComponentFunction, type ComponentInstance, Container, DisplayObject, EVENTS, Easing, type Element, Ellipse, Graphics, NineSliceSprite, ParticlesEmitter, type Props, RadialGradient, Rect, Scene, Sprite, Text, TilingSprite, Triangle, utils as Utils, Video, Viewport, animatedSignal, bootstrapCanvas, cond, createComponent, currentSubscriptionsTracker, h, isAnimatedSignal, isElement, isPrimitive, isTrigger, loop, mount, mountTracker, on, registerComponent, Svg as svg, tick, trigger, useDefineProps, useProps };
1137
+ export { type AnimateOptions, type AnimatedSignal, type AnimatedState, type ArrayChange, Canvas, Circle, type ComponentFunction, type ComponentInstance, Container, DisplayObject, EVENTS, Easing, type Element, Ellipse, Graphics, NineSliceSprite, type ObjectChange, ParticlesEmitter, type Props, RadialGradient, Rect, Scene, Sprite, Text, TilingSprite, Triangle, utils as Utils, Video, Viewport, animatedSequence, animatedSignal, bootstrapCanvas, cond, createComponent, currentSubscriptionsTracker, h, isAnimatedSignal, isElement, isPrimitive, isTrigger, loop, mount, mountTracker, on, registerComponent, Svg as svg, tick, trigger, useDefineProps, useProps };
package/dist/index.js CHANGED
@@ -1307,19 +1307,42 @@ function createComponent(tag, props) {
1307
1307
  }
1308
1308
  function loop(itemsSubject, createElementFn) {
1309
1309
  let elements = [];
1310
- const addAt = (items, insertIndex) => {
1310
+ const isArraySignal = "_subject" in itemsSubject && "items" in itemsSubject._subject;
1311
+ const addAt = (items, insertIndex, keys) => {
1311
1312
  return items.map((item, index) => {
1312
- const element = createElementFn(item, insertIndex + index);
1313
- elements.splice(insertIndex + index, 0, element);
1313
+ const key = keys ? keys[index] : typeof insertIndex === "number" ? insertIndex + index : insertIndex;
1314
+ const element = createElementFn(item, key);
1315
+ if (typeof insertIndex === "number") {
1316
+ elements.splice(insertIndex + index, 0, element);
1317
+ } else {
1318
+ elements.push(element);
1319
+ }
1314
1320
  return element;
1315
1321
  });
1316
1322
  };
1323
+ const getInitialItems = () => {
1324
+ if (isArraySignal) {
1325
+ return {
1326
+ items: itemsSubject._subject.items,
1327
+ keys: void 0
1328
+ };
1329
+ } else {
1330
+ const entries = Object.entries(itemsSubject._subject.value.value);
1331
+ return {
1332
+ items: entries.map(([_, value]) => value),
1333
+ keys: entries.map(([key]) => key)
1334
+ };
1335
+ }
1336
+ };
1317
1337
  return defer(() => {
1318
- let initialItems = [...itemsSubject._subject.items];
1338
+ const { items, keys } = getInitialItems();
1339
+ let initialItems = [...items];
1340
+ let initialKeys = keys ? [...keys] : void 0;
1319
1341
  let init = true;
1320
1342
  return itemsSubject.observable.pipe(
1321
1343
  map((event) => {
1322
- const { type, items, index } = event;
1344
+ const { type, items: items2 } = event;
1345
+ const index = "index" in event ? event.index : event.key;
1323
1346
  if (init) {
1324
1347
  if (elements.length > 0) {
1325
1348
  return {
@@ -1327,8 +1350,9 @@ function loop(itemsSubject, createElementFn) {
1327
1350
  fullElements: elements
1328
1351
  };
1329
1352
  }
1330
- const newElements = addAt(initialItems, 0);
1353
+ const newElements = addAt(initialItems, 0, initialKeys);
1331
1354
  initialItems = [];
1355
+ initialKeys = void 0;
1332
1356
  init = false;
1333
1357
  return {
1334
1358
  elements: newElements,
@@ -1341,25 +1365,60 @@ function loop(itemsSubject, createElementFn) {
1341
1365
  });
1342
1366
  elements = [];
1343
1367
  }
1344
- const newElements = addAt(items, 0);
1368
+ if (!isArraySignal) {
1369
+ const entries = Object.entries(itemsSubject._subject.value.value);
1370
+ const newElements2 = addAt(
1371
+ entries.map(([_, value]) => value),
1372
+ 0,
1373
+ entries.map(([key]) => key)
1374
+ );
1375
+ return {
1376
+ elements: newElements2,
1377
+ fullElements: elements
1378
+ };
1379
+ }
1380
+ const newElements = addAt(items2, 0);
1345
1381
  return {
1346
1382
  elements: newElements,
1347
1383
  fullElements: elements
1348
1384
  };
1349
1385
  } else if (type == "add" && index != void 0) {
1350
- const lastElement = elements[index - 1];
1351
- const newElements = addAt(items, index);
1386
+ const lastElement = typeof index === "number" ? elements[index - 1] : elements[elements.length - 1];
1387
+ let newElements;
1388
+ if (!isArraySignal && typeof index === "string") {
1389
+ const value = event.value;
1390
+ if (value !== void 0) {
1391
+ newElements = [createElementFn(value, index)];
1392
+ elements.push(newElements[0]);
1393
+ } else {
1394
+ newElements = [];
1395
+ }
1396
+ } else {
1397
+ newElements = addAt(items2, index);
1398
+ }
1352
1399
  return {
1353
1400
  prev: lastElement,
1354
1401
  elements: newElements,
1355
1402
  fullElements: elements
1356
1403
  };
1357
- } else if (index != void 0 && type == "remove") {
1358
- const currentElement = elements[index];
1359
- destroyElement(currentElement);
1360
- elements.splice(index, 1);
1404
+ } else if (type == "remove") {
1405
+ if (!isArraySignal && typeof index === "string") {
1406
+ const elementIndex = elements.findIndex((el) => {
1407
+ return el.props.text === index || el.props.key === index;
1408
+ });
1409
+ if (elementIndex !== -1) {
1410
+ const currentElement = elements[elementIndex];
1411
+ destroyElement(currentElement);
1412
+ elements.splice(elementIndex, 1);
1413
+ }
1414
+ } else if (typeof index === "number") {
1415
+ const currentElement = elements[index];
1416
+ destroyElement(currentElement);
1417
+ elements.splice(index, 1);
1418
+ }
1361
1419
  return {
1362
- elements: []
1420
+ elements: [],
1421
+ fullElements: elements
1363
1422
  };
1364
1423
  }
1365
1424
  return {
@@ -1579,7 +1638,7 @@ var EVENTS2 = [
1579
1638
  "wheelcapture"
1580
1639
  ];
1581
1640
  function DisplayObject(extendClass) {
1582
- var _canvasContext, _DisplayObject_instances, applyFlexLayout_fn, flexRender_fn, setAlign_fn, setEdgeSize_fn, _a;
1641
+ var _canvasContext, _DisplayObject_instances, flexRender_fn, setAlign_fn, setEdgeSize_fn, _a;
1583
1642
  return _a = class extends extendClass {
1584
1643
  constructor() {
1585
1644
  super(...arguments);
@@ -1648,7 +1707,7 @@ function DisplayObject(extendClass) {
1648
1707
  effect3(() => {
1649
1708
  setter(parentSize() * (parseInt(size) / 100));
1650
1709
  if (this.isFlex) {
1651
- __privateMethod(this, _DisplayObject_instances, applyFlexLayout_fn).call(this);
1710
+ this.applyFlexLayout();
1652
1711
  }
1653
1712
  });
1654
1713
  } else {
@@ -1664,6 +1723,14 @@ function DisplayObject(extendClass) {
1664
1723
  this.parent.displayHeight
1665
1724
  );
1666
1725
  }
1726
+ applyFlexLayout() {
1727
+ this.calculateLayout();
1728
+ for (let child of this.children) {
1729
+ const { left, top } = child.node.getComputedLayout();
1730
+ child.x = left;
1731
+ child.y = top;
1732
+ }
1733
+ }
1667
1734
  onUpdate(props) {
1668
1735
  this.fullProps = {
1669
1736
  ...this.fullProps,
@@ -1841,18 +1908,11 @@ function DisplayObject(extendClass) {
1841
1908
  getHeight() {
1842
1909
  return this.displayHeight();
1843
1910
  }
1844
- }, _canvasContext = new WeakMap(), _DisplayObject_instances = new WeakSet(), applyFlexLayout_fn = function() {
1845
- this.calculateLayout();
1846
- for (let child of this.children) {
1847
- const { left, top } = child.node.getComputedLayout();
1848
- child.x = left;
1849
- child.y = top;
1850
- }
1851
- }, flexRender_fn = function(props) {
1911
+ }, _canvasContext = new WeakMap(), _DisplayObject_instances = new WeakSet(), flexRender_fn = function(props) {
1852
1912
  if (!this.parent) return;
1853
1913
  if (props.flexDirection || props.justifyContent) {
1854
1914
  this.isFlex = true;
1855
- __privateMethod(this, _DisplayObject_instances, applyFlexLayout_fn).call(this);
1915
+ this.applyFlexLayout();
1856
1916
  }
1857
1917
  }, setAlign_fn = function(methodName, align) {
1858
1918
  const mapping = {
@@ -2218,7 +2278,7 @@ function animatedSignal(initialValue, options = {}) {
2218
2278
  const currentState = privateSignal();
2219
2279
  publicSignal.set(currentState.current);
2220
2280
  });
2221
- function animatedSignal2(newValue) {
2281
+ function animatedSignal2(newValue, animationConfig = {}) {
2222
2282
  if (newValue === void 0) {
2223
2283
  return privateSignal();
2224
2284
  }
@@ -2236,6 +2296,7 @@ function animatedSignal(initialValue, options = {}) {
2236
2296
  // TODO
2237
2297
  duration: 20,
2238
2298
  ...options,
2299
+ ...animationConfig,
2239
2300
  from: prevState.current,
2240
2301
  to: newValue,
2241
2302
  onUpdate: (value) => {
@@ -2256,11 +2317,25 @@ function animatedSignal(initialValue, options = {}) {
2256
2317
  fn.update = (updater) => {
2257
2318
  animatedSignal2(updater(privateSignal().current));
2258
2319
  };
2259
- fn.set = (newValue) => {
2260
- animatedSignal2(newValue);
2320
+ fn.set = async (newValue, animationConfig = {}) => {
2321
+ return new Promise((resolve) => {
2322
+ animatedSignal2(newValue, {
2323
+ ...animationConfig,
2324
+ onComplete: resolve
2325
+ });
2326
+ });
2261
2327
  };
2262
2328
  return fn;
2263
2329
  }
2330
+ async function animatedSequence(sequence) {
2331
+ for (const item of sequence) {
2332
+ if (Array.isArray(item)) {
2333
+ await Promise.all(item.map((fn) => fn()));
2334
+ } else {
2335
+ await item();
2336
+ }
2337
+ }
2338
+ }
2264
2339
 
2265
2340
  // src/components/Sprite.ts
2266
2341
  var log2 = console.log;
@@ -2762,8 +2837,8 @@ var CanvasText = class extends DisplayObject(PixiText) {
2762
2837
  this.typewriterOptions = props.typewriter;
2763
2838
  }
2764
2839
  }
2765
- if (props.text) {
2766
- this.text = props.text;
2840
+ if (props.text !== void 0) {
2841
+ this.text = "" + props.text;
2767
2842
  }
2768
2843
  if (props.text !== void 0 && props.text !== this.fullText && this.fullProps.typewriter) {
2769
2844
  this.text = "";
@@ -3159,6 +3234,7 @@ export {
3159
3234
  utils_exports as Utils,
3160
3235
  Video,
3161
3236
  Viewport,
3237
+ animatedSequence,
3162
3238
  animatedSignal,
3163
3239
  bootstrapCanvas,
3164
3240
  cond,