canvasengine 2.0.0-beta.4 → 2.0.0-beta.5

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
@@ -5,7 +5,7 @@ import { Subscription, Subject, Observable } from 'rxjs';
5
5
  export { isObservable } from 'rxjs';
6
6
  import { Node } from 'yoga-layout';
7
7
  import * as PIXI from 'pixi.js';
8
- import { ObservablePoint, Graphics as Graphics$1, TextStyle, Texture, Matrix } from 'pixi.js';
8
+ import { ObservablePoint, Graphics as Graphics$1, Texture, TextStyle, Matrix } from 'pixi.js';
9
9
  export { Howler } from 'howler';
10
10
  import * as popmotion from 'popmotion';
11
11
 
@@ -749,10 +749,26 @@ interface SpritePropsWithSheet extends Omit<SpriteProps, "image" | "rectangle">
749
749
  params?: any;
750
750
  onFinish?: () => void;
751
751
  };
752
+ loader?: {
753
+ onProgress?: (progress: number) => void;
754
+ onComplete?: (texture: Texture) => void;
755
+ };
752
756
  }
753
757
  type SpritePropTypes = SpritePropsWithImage | SpritePropsWithSheet;
754
758
  declare const Sprite: ComponentFunction<SpritePropTypes>;
755
759
 
760
+ interface VideoProps {
761
+ source: string;
762
+ paused?: boolean;
763
+ loop?: boolean;
764
+ muted?: boolean;
765
+ loader?: {
766
+ onComplete?: (texture: Texture) => void;
767
+ onProgress?: (progress: number) => void;
768
+ };
769
+ }
770
+ declare function Video(props: VideoProps): Element<ComponentInstance> | Promise<Element<ComponentInstance>>;
771
+
756
772
  interface TextProps extends DisplayObjectProps {
757
773
  text?: string;
758
774
  style?: Partial<TextStyle>;
@@ -1082,4 +1098,4 @@ declare namespace utils {
1082
1098
  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 };
1083
1099
  }
1084
1100
 
1085
- 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, Viewport, animatedSignal, bootstrapCanvas, cond, createComponent, currentSubscriptionsTracker, h, isAnimatedSignal, isElement, isPrimitive, isTrigger, loop, mount, mountTracker, on, registerComponent, Svg as svg, tick, trigger, useDefineProps, useProps };
1101
+ 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 };
package/dist/index.js CHANGED
@@ -1209,8 +1209,20 @@ function createComponent(tag, props) {
1209
1209
  recursiveProps(props);
1210
1210
  }
1211
1211
  instance.onInit?.(element.props);
1212
- instance.onUpdate?.(element.props);
1213
- const onMount = (parent, element2, index) => {
1212
+ const elementsListen = new Subject();
1213
+ if (props?.isRoot) {
1214
+ element.allElements = elementsListen;
1215
+ element.props.context.rootElement = element;
1216
+ element.componentInstance.onMount?.(element);
1217
+ propagateContext(element);
1218
+ }
1219
+ if (props) {
1220
+ for (let key in props) {
1221
+ const directive = applyDirective(element, key);
1222
+ if (directive) element.directives[key] = directive;
1223
+ }
1224
+ }
1225
+ function onMount(parent, element2, index) {
1214
1226
  element2.props.context = parent.props.context;
1215
1227
  element2.parent = parent;
1216
1228
  element2.componentInstance.onMount?.(element2, index);
@@ -1220,78 +1232,76 @@ function createComponent(tag, props) {
1220
1232
  element2.effectMounts.forEach((fn) => {
1221
1233
  element2.effectUnmounts.push(fn(element2));
1222
1234
  });
1223
- };
1224
- const elementsListen = new Subject();
1225
- if (props?.isRoot) {
1226
- const propagateContext = async (element2) => {
1227
- if (element2.props.attach) {
1228
- const isReactiveAttach = isSignal2(element2.propObservables?.attach);
1229
- if (!isReactiveAttach) {
1230
- element2.props.children.push(element2.props.attach);
1231
- } else {
1235
+ }
1236
+ ;
1237
+ async function propagateContext(element2) {
1238
+ if (element2.props.attach) {
1239
+ const isReactiveAttach = isSignal2(element2.propObservables?.attach);
1240
+ if (!isReactiveAttach) {
1241
+ element2.props.children.push(element2.props.attach);
1242
+ } else {
1243
+ await new Promise((resolve) => {
1232
1244
  let lastElement = null;
1233
- element2.propObservables.attach.observable.subscribe(({ value, type }) => {
1234
- if (type != "init") {
1245
+ element2.propSubscriptions.push(element2.propObservables.attach.observable.subscribe(async (args) => {
1246
+ const value = args?.value ?? args;
1247
+ if (!value) {
1248
+ throw new Error(`attach in ${element2.tag} is undefined or null, add a component`);
1249
+ }
1250
+ if (lastElement) {
1235
1251
  destroyElement(lastElement);
1236
1252
  }
1237
1253
  lastElement = value;
1238
- onMount(element2, value);
1239
- propagateContext(value);
1240
- });
1241
- }
1242
- }
1243
- if (!element2.props.children) {
1244
- return;
1254
+ await createElement(element2, value);
1255
+ resolve(void 0);
1256
+ }));
1257
+ });
1245
1258
  }
1246
- for (let child of element2.props.children) {
1247
- if (!child) continue;
1248
- if (isPromise(child)) {
1249
- child = await child;
1250
- }
1251
- if (child instanceof Observable) {
1252
- child.subscribe(
1253
- ({
1254
- elements: comp,
1255
- prev
1256
- }) => {
1257
- const components2 = comp.filter((c) => c !== null);
1258
- if (prev) {
1259
- components2.forEach((c) => {
1260
- const index = element2.props.children.indexOf(prev.props.key);
1261
- onMount(element2, c, index + 1);
1262
- propagateContext(c);
1263
- });
1264
- return;
1265
- }
1266
- components2.forEach((component) => {
1267
- if (!Array.isArray(component)) {
1268
- onMount(element2, component);
1269
- propagateContext(component);
1270
- } else {
1271
- component.forEach((comp2) => {
1272
- onMount(element2, comp2);
1273
- propagateContext(comp2);
1274
- });
1275
- }
1259
+ }
1260
+ if (!element2.props.children) {
1261
+ return;
1262
+ }
1263
+ for (let child of element2.props.children) {
1264
+ if (!child) continue;
1265
+ await createElement(element2, child);
1266
+ }
1267
+ }
1268
+ ;
1269
+ async function createElement(parent, child) {
1270
+ if (isPromise(child)) {
1271
+ child = await child;
1272
+ }
1273
+ if (child instanceof Observable) {
1274
+ child.subscribe(
1275
+ ({
1276
+ elements: comp,
1277
+ prev
1278
+ }) => {
1279
+ const components2 = comp.filter((c) => c !== null);
1280
+ if (prev) {
1281
+ components2.forEach((c) => {
1282
+ const index = parent.props.children.indexOf(prev.props.key);
1283
+ onMount(parent, c, index + 1);
1284
+ propagateContext(c);
1285
+ });
1286
+ return;
1287
+ }
1288
+ components2.forEach((component) => {
1289
+ if (!Array.isArray(component)) {
1290
+ onMount(parent, component);
1291
+ propagateContext(component);
1292
+ } else {
1293
+ component.forEach((comp2) => {
1294
+ onMount(parent, comp2);
1295
+ propagateContext(comp2);
1276
1296
  });
1277
- elementsListen.next(void 0);
1278
1297
  }
1279
- );
1280
- } else {
1281
- onMount(element2, child);
1282
- await propagateContext(child);
1298
+ });
1299
+ elementsListen.next(void 0);
1283
1300
  }
1284
- }
1285
- };
1286
- element.allElements = elementsListen;
1287
- element.props.context.rootElement = element;
1288
- element.componentInstance.onMount?.(element);
1289
- propagateContext(element);
1290
- }
1291
- if (props) {
1292
- for (let key in props) {
1293
- const directive = applyDirective(element, key);
1294
- if (directive) element.directives[key] = directive;
1301
+ );
1302
+ } else {
1303
+ onMount(parent, child);
1304
+ await propagateContext(child);
1295
1305
  }
1296
1306
  }
1297
1307
  return element;
@@ -2168,8 +2178,8 @@ import {
2168
2178
  // src/engine/animation.ts
2169
2179
  import { effect as effect6, signal as signal4 } from "@signe/reactive";
2170
2180
  import { animate as animatePopmotion } from "popmotion";
2171
- function isAnimatedSignal(signal6) {
2172
- return signal6.animatedState !== void 0;
2181
+ function isAnimatedSignal(signal7) {
2182
+ return signal7.animatedState !== void 0;
2173
2183
  }
2174
2184
  function animatedSignal(initialValue, options = {}) {
2175
2185
  const state = {
@@ -2374,6 +2384,21 @@ var CanvasSprite = class extends DisplayObject(PixiSprite) {
2374
2384
  }
2375
2385
  async onUpdate(props) {
2376
2386
  super.onUpdate(props);
2387
+ const setTexture = async (image) => {
2388
+ const onProgress = this.fullProps.loader?.onProgress;
2389
+ const texture = await Assets.load(image, (progress) => {
2390
+ if (onProgress) onProgress(progress);
2391
+ if (progress == 1) {
2392
+ const onComplete = this.fullProps.loader?.onComplete;
2393
+ if (onComplete) {
2394
+ setTimeout(() => {
2395
+ onComplete(texture);
2396
+ });
2397
+ }
2398
+ }
2399
+ });
2400
+ return texture;
2401
+ };
2377
2402
  const sheet = props.sheet;
2378
2403
  if (sheet?.params) this.sheetParams = sheet?.params;
2379
2404
  if (sheet?.playing && this.isMounted) {
@@ -2383,13 +2408,13 @@ var CanvasSprite = class extends DisplayObject(PixiSprite) {
2383
2408
  if (props.hitbox) this.hitbox = props.hitbox;
2384
2409
  if (props.scaleMode) this.baseTexture.scaleMode = props.scaleMode;
2385
2410
  else if (props.image && this.fullProps.rectangle === void 0) {
2386
- this.texture = await Assets.load(this.fullProps.image);
2411
+ this.texture = await setTexture(this.fullProps.image);
2387
2412
  } else if (props.texture) {
2388
2413
  this.texture = props.texture;
2389
2414
  }
2390
2415
  if (props.rectangle !== void 0) {
2391
2416
  const { x, y, width, height } = props.rectangle?.value ?? props.rectangle;
2392
- const texture = await Assets.load(this.fullProps.image);
2417
+ const texture = await setTexture(this.fullProps.image);
2393
2418
  this.texture = new Texture2({
2394
2419
  source: texture.source,
2395
2420
  frame: new Rectangle2(x, y, width, height)
@@ -2530,16 +2555,108 @@ var Sprite2 = (props) => {
2530
2555
  return createComponent("Sprite", props);
2531
2556
  };
2532
2557
 
2558
+ // src/components/Video.ts
2559
+ import { effect as effect8, signal as signal5 } from "@signe/reactive";
2560
+ function Video(props) {
2561
+ const eventsMap = {
2562
+ audioprocess: null,
2563
+ canplay: null,
2564
+ canplaythrough: null,
2565
+ complete: null,
2566
+ durationchange: null,
2567
+ emptied: null,
2568
+ ended: null,
2569
+ loadeddata: null,
2570
+ loadedmetadata: null,
2571
+ pause: null,
2572
+ play: null,
2573
+ playing: null,
2574
+ progress: null,
2575
+ ratechange: null,
2576
+ seeked: null,
2577
+ seeking: null,
2578
+ stalled: null,
2579
+ suspend: null,
2580
+ timeupdate: null,
2581
+ volumechange: null,
2582
+ waiting: null
2583
+ };
2584
+ const video = signal5(null);
2585
+ const defineProps = useDefineProps(props);
2586
+ const { play, loop: loop2, muted } = defineProps({
2587
+ play: {
2588
+ type: Boolean,
2589
+ default: true
2590
+ },
2591
+ loop: {
2592
+ type: Boolean,
2593
+ default: false
2594
+ },
2595
+ muted: {
2596
+ type: Boolean,
2597
+ default: false
2598
+ }
2599
+ });
2600
+ effect8(() => {
2601
+ const _video = video();
2602
+ const state = play();
2603
+ if (_video && state !== void 0) {
2604
+ if (state) {
2605
+ _video.play();
2606
+ } else {
2607
+ _video.pause();
2608
+ }
2609
+ }
2610
+ if (_video && loop2()) {
2611
+ _video.loop = loop2();
2612
+ }
2613
+ if (_video && muted()) {
2614
+ _video.muted = muted();
2615
+ }
2616
+ });
2617
+ mount(() => {
2618
+ return () => {
2619
+ for (let event in eventsMap) {
2620
+ if (eventsMap[event]) {
2621
+ video().removeEventListener(event, eventsMap[event]);
2622
+ }
2623
+ }
2624
+ };
2625
+ });
2626
+ return h(Sprite2, {
2627
+ ...props,
2628
+ image: props.source,
2629
+ loader: {
2630
+ onComplete: (texture) => {
2631
+ const source = texture.source.resource;
2632
+ video.set(source);
2633
+ if (props?.loader?.onComplete) {
2634
+ props.loader.onComplete(texture);
2635
+ }
2636
+ for (let event in eventsMap) {
2637
+ if (props[event]) {
2638
+ const cb = (ev) => {
2639
+ props[event](ev);
2640
+ };
2641
+ eventsMap[event] = cb;
2642
+ source.addEventListener(event, cb);
2643
+ }
2644
+ }
2645
+ }
2646
+ }
2647
+ });
2648
+ }
2649
+
2533
2650
  // src/components/Text.ts
2534
2651
  import { Text as PixiText } from "pixi.js";
2535
2652
 
2536
2653
  // src/engine/trigger.ts
2537
- import { effect as effect8, signal as signal5 } from "@signe/reactive";
2654
+ import { effect as effect9, signal as signal6 } from "@signe/reactive";
2538
2655
  function isTrigger(arg) {
2539
2656
  return arg?.start && arg?.listen;
2540
2657
  }
2541
2658
  function trigger(globalConfig) {
2542
- const _signal = signal5({
2659
+ const _signal = signal6({
2543
2660
  config: globalConfig,
2544
2661
  value: 0,
2545
2662
  resolve: (value) => void 0
@@ -2569,7 +2686,7 @@ function on(triggerSignal, callback) {
2569
2686
  if (!isTrigger(triggerSignal)) {
2570
2687
  throw new Error("In 'on(arg)' must have a trigger signal type");
2571
2688
  }
2572
- effect8(() => {
2689
+ effect9(() => {
2573
2690
  const result = triggerSignal.listen();
2574
2691
  if (result?.seed.value) {
2575
2692
  const ret = callback(result?.seed.config);
@@ -2716,7 +2833,7 @@ function TilingSprite(props) {
2716
2833
 
2717
2834
  // src/components/Viewport.ts
2718
2835
  import { Viewport as PixiViewport } from "pixi-viewport";
2719
- import { effect as effect9 } from "@signe/reactive";
2836
+ import { effect as effect10 } from "@signe/reactive";
2720
2837
  var EVENTS3 = [
2721
2838
  "bounce-x-end",
2722
2839
  "bounce-x-start",
@@ -2767,7 +2884,7 @@ var CanvasViewport = class extends DisplayObject(PixiViewport) {
2767
2884
  super.onMount(element);
2768
2885
  const { tick: tick2, renderer, canvasSize } = element.props.context;
2769
2886
  let isDragging = false;
2770
- effect9(() => {
2887
+ effect10(() => {
2771
2888
  this.screenWidth = canvasSize().width;
2772
2889
  this.screenHeight = canvasSize().height;
2773
2890
  });
@@ -3016,6 +3133,7 @@ export {
3016
3133
  TilingSprite,
3017
3134
  Triangle,
3018
3135
  utils_exports as Utils,
3136
+ Video,
3019
3137
  Viewport,
3020
3138
  animatedSignal,
3021
3139
  bootstrapCanvas,