canvasengine 2.0.0-beta.20 → 2.0.0-beta.22

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
@@ -4,7 +4,7 @@ export * from '@signe/reactive';
4
4
  import { BehaviorSubject, Subscription, Subject, Observable } from 'rxjs';
5
5
  export { isObservable } from 'rxjs';
6
6
  import * as PIXI from 'pixi.js';
7
- import { FederatedPointerEvent, ObservablePoint, Graphics as Graphics$1, Geometry, Shader, Texture, TextStyle, Application, Matrix } from 'pixi.js';
7
+ import { FederatedPointerEvent, ObservablePoint, Graphics as Graphics$1, Geometry, Shader, Texture, TextStyle, ApplicationOptions, Application, Matrix } from 'pixi.js';
8
8
  import * as howler from 'howler';
9
9
  export { howler as Howl };
10
10
  export { Howler } from 'howler';
@@ -982,6 +982,8 @@ interface NineSliceSpriteProps extends DisplayObjectProps {
982
982
  }
983
983
  declare function NineSliceSprite(props: NineSliceSpriteProps): Element<ComponentInstance>;
984
984
 
985
+ declare const DOMContainer: ComponentFunction<any>;
986
+
985
987
  interface DOMContainerProps extends DisplayObjectProps {
986
988
  element: string | {
987
989
  value: HTMLElement;
@@ -997,9 +999,9 @@ interface DOMContainerProps extends DisplayObjectProps {
997
999
  value?: string | Record<string, string | number>;
998
1000
  };
999
1001
  };
1000
- sortableChildren?: boolean;
1002
+ onBeforeDestroy?: OnHook;
1001
1003
  }
1002
- declare const DOMContainer: ComponentFunction<DOMContainerProps>;
1004
+ declare const DOMElement: ComponentFunction<DOMContainerProps>;
1003
1005
 
1004
1006
  interface Listen<T = any> {
1005
1007
  config: T | undefined;
@@ -1059,7 +1061,7 @@ declare function on(triggerSignal: any, callback: (config: any) => void | Promis
1059
1061
  * @returns A Promise that resolves to the rendered canvas element.
1060
1062
  * @throws {Error} If the provided element is not a Canvas component.
1061
1063
  */
1062
- declare const bootstrapCanvas: (rootElement: HTMLElement | null, canvas: ComponentFunction<any>) => Promise<{
1064
+ declare const bootstrapCanvas: (rootElement: HTMLElement | null, canvas: ComponentFunction<any>, options?: ApplicationOptions) => Promise<{
1063
1065
  canvasElement: Element<ComponentInstance>;
1064
1066
  app: Application<PIXI.Renderer>;
1065
1067
  }>;
@@ -1220,6 +1222,7 @@ declare function isFunction(val: unknown): boolean;
1220
1222
  * ```
1221
1223
  */
1222
1224
  declare function isObject(val: unknown): boolean;
1225
+ declare function isObservable(val: unknown): boolean;
1223
1226
  /**
1224
1227
  * Sets a value in an object using a dot notation path
1225
1228
  * @param {Record<string, any>} obj - Target object
@@ -1273,13 +1276,14 @@ declare const utils_get: typeof get;
1273
1276
  declare const utils_isBrowser: typeof isBrowser;
1274
1277
  declare const utils_isFunction: typeof isFunction;
1275
1278
  declare const utils_isObject: typeof isObject;
1279
+ declare const utils_isObservable: typeof isObservable;
1276
1280
  declare const utils_isPromise: typeof isPromise;
1277
1281
  declare const utils_log: typeof log;
1278
1282
  declare const utils_preciseNow: typeof preciseNow;
1279
1283
  declare const utils_set: typeof set;
1280
1284
  declare const utils_setObservablePoint: typeof setObservablePoint;
1281
1285
  declare namespace utils {
1282
- 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 };
1286
+ 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_isObservable as isObservable, utils_isPromise as isPromise, utils_log as log, utils_preciseNow as preciseNow, utils_set as set, utils_setObservablePoint as setObservablePoint };
1283
1287
  }
1284
1288
 
1285
- export { type AnimateOptions, type AnimatedSignal, type AnimatedState, Canvas, Circle, type ComponentFunction, type ComponentInstance, Container, DOMContainer, DisplayObject, EVENTS, Easing, type Element, Ellipse, Graphics, Mesh, NineSliceSprite, ParticlesEmitter, type Props, RadialGradient, Rect, Scene, Sprite, Svg, Text, TilingSprite, Triangle, utils as Utils, Video, Viewport, animatedSequence, animatedSignal, bootstrapCanvas, cond, createComponent, currentSubscriptionsTracker, h, isAnimatedSignal, isElement, isPrimitive, isTrigger, loop, mount, mountTracker, on, registerComponent, tick, trigger, useDefineProps, useProps };
1289
+ export { type AnimateOptions, type AnimatedSignal, type AnimatedState, Canvas, Circle, type ComponentFunction, type ComponentInstance, Container, DOMContainer, DOMElement, DisplayObject, EVENTS, Easing, type Element, Ellipse, Graphics, Mesh, NineSliceSprite, type OnHook, ParticlesEmitter, type Props, RadialGradient, Rect, Scene, Sprite, Svg, Text, TilingSprite, Triangle, utils as Utils, Video, Viewport, animatedSequence, animatedSignal, bootstrapCanvas, cond, createComponent, currentSubscriptionsTracker, h, isAnimatedSignal, isElement, isPrimitive, isTrigger, loop, mount, mountTracker, on, registerComponent, tick, trigger, useDefineProps, useProps };
package/dist/index.js CHANGED
@@ -38,12 +38,14 @@ __export(utils_exports, {
38
38
  isBrowser: () => isBrowser,
39
39
  isFunction: () => isFunction,
40
40
  isObject: () => isObject,
41
+ isObservable: () => isObservable,
41
42
  isPromise: () => isPromise,
42
43
  log: () => log,
43
44
  preciseNow: () => preciseNow,
44
45
  set: () => set,
45
46
  setObservablePoint: () => setObservablePoint
46
47
  });
48
+ import { Observable } from "rxjs";
47
49
  function isBrowser() {
48
50
  return typeof window !== "undefined";
49
51
  }
@@ -101,6 +103,9 @@ function isFunction(val) {
101
103
  function isObject(val) {
102
104
  return typeof val == "object" && val != null && !Array.isArray(val) && val.constructor === Object;
103
105
  }
106
+ function isObservable(val) {
107
+ return val instanceof Observable;
108
+ }
104
109
  function set(obj, path, value, onlyPlainObject = false) {
105
110
  if (Object(obj) !== obj) return obj;
106
111
  if (typeof path === "string") {
@@ -964,12 +969,13 @@ import { isSignal as isSignal2, signal as signal2 } from "@signe/reactive";
964
969
  // src/engine/reactive.ts
965
970
  import { isComputed, isSignal, signal } from "@signe/reactive";
966
971
  import {
967
- Observable,
972
+ Observable as Observable2,
968
973
  Subject,
969
974
  defer,
970
975
  from,
971
976
  map,
972
- of
977
+ of,
978
+ share
973
979
  } from "rxjs";
974
980
  var components = {};
975
981
  var isElement = (value) => {
@@ -989,14 +995,25 @@ function destroyElement(element) {
989
995
  if (!element) {
990
996
  return;
991
997
  }
998
+ if (element.props?.children) {
999
+ for (let child of element.props.children) {
1000
+ destroyElement(child);
1001
+ }
1002
+ }
992
1003
  for (let name in element.directives) {
993
1004
  element.directives[name].onDestroy?.(element);
994
1005
  }
995
- element.componentInstance.onDestroy(element.parent, () => {
996
- element.propSubscriptions.forEach((sub) => sub.unsubscribe());
997
- element.effectSubscriptions.forEach((sub) => sub.unsubscribe());
998
- element.effectUnmounts.forEach((fn) => fn?.());
999
- });
1006
+ if (element.componentInstance && element.componentInstance.onDestroy) {
1007
+ element.componentInstance.onDestroy(element.parent, () => {
1008
+ element.propSubscriptions?.forEach((sub) => sub.unsubscribe());
1009
+ element.effectSubscriptions?.forEach((sub) => sub.unsubscribe());
1010
+ element.effectUnmounts?.forEach((fn) => fn?.());
1011
+ });
1012
+ } else {
1013
+ element.propSubscriptions?.forEach((sub) => sub.unsubscribe());
1014
+ element.effectSubscriptions?.forEach((sub) => sub.unsubscribe());
1015
+ element.effectUnmounts?.forEach((fn) => fn?.());
1016
+ }
1000
1017
  }
1001
1018
  function createComponent(tag, props) {
1002
1019
  if (!components[tag]) {
@@ -1124,7 +1141,7 @@ function createComponent(tag, props) {
1124
1141
  if (isPromise(child)) {
1125
1142
  child = await child;
1126
1143
  }
1127
- if (child instanceof Observable) {
1144
+ if (child instanceof Observable2) {
1128
1145
  child.subscribe(
1129
1146
  ({
1130
1147
  elements: comp,
@@ -1171,7 +1188,7 @@ function loop(itemsSubject, createElementFn) {
1171
1188
  let elementMap = /* @__PURE__ */ new Map();
1172
1189
  let isFirstSubscription = true;
1173
1190
  const isArraySignal = (signal10) => Array.isArray(signal10());
1174
- return new Observable((subscriber) => {
1191
+ return new Observable2((subscriber) => {
1175
1192
  const subscription = isArraySignal(itemsSubject) ? itemsSubject.observable.subscribe((change) => {
1176
1193
  if (isFirstSubscription) {
1177
1194
  isFirstSubscription = false;
@@ -1324,7 +1341,7 @@ function cond(condition, createElementFn) {
1324
1341
  let element = null;
1325
1342
  if (isSignal(condition)) {
1326
1343
  const signalCondition = condition;
1327
- return new Observable((subscriber) => {
1344
+ return new Observable2((subscriber) => {
1328
1345
  return signalCondition.observable.subscribe((bool) => {
1329
1346
  if (bool) {
1330
1347
  let _el = createElementFn();
@@ -1354,7 +1371,7 @@ function cond(condition, createElementFn) {
1354
1371
  });
1355
1372
  }
1356
1373
  });
1357
- });
1374
+ }).pipe(share());
1358
1375
  } else {
1359
1376
  if (condition) {
1360
1377
  let _el = createElementFn();
@@ -3830,6 +3847,9 @@ function NineSliceSprite(props) {
3830
3847
 
3831
3848
  // src/components/DOMContainer.ts
3832
3849
  import { DOMContainer as PixiDOMContainer } from "pixi.js";
3850
+
3851
+ // src/components/DOMElement.ts
3852
+ import { isSignal as isSignal6 } from "@signe/reactive";
3833
3853
  var EVENTS4 = [
3834
3854
  "click",
3835
3855
  "mouseover",
@@ -3869,34 +3889,91 @@ var EVENTS4 = [
3869
3889
  "selectall",
3870
3890
  "selectnone"
3871
3891
  ];
3872
- var CanvasDOMContainer = class extends DisplayObject(PixiDOMContainer) {
3892
+ var CanvasDOMElement = class {
3873
3893
  constructor() {
3874
- super(...arguments);
3875
- this.disableLayout = true;
3876
3894
  this.eventListeners = /* @__PURE__ */ new Map();
3895
+ this.onBeforeDestroy = null;
3896
+ this.valueSignal = null;
3897
+ this.isFormElementType = false;
3898
+ }
3899
+ /**
3900
+ * Checks if the element is a form element that supports the value attribute
3901
+ * @param elementType - The element type string from props
3902
+ * @returns true if the element is a form element with value support
3903
+ */
3904
+ isFormElement(elementType) {
3905
+ const formElements = ["input", "textarea", "select"];
3906
+ return formElements.includes(elementType.toLowerCase());
3877
3907
  }
3878
3908
  onInit(props) {
3879
- super.onInit(props);
3880
- if (props.element === void 0) {
3881
- throw new Error("DOMContainer: element is required");
3882
- }
3883
3909
  if (typeof props.element === "string") {
3884
3910
  this.element = document.createElement(props.element);
3911
+ this.isFormElementType = this.isFormElement(props.element);
3885
3912
  } else {
3886
3913
  this.element = props.element.value;
3914
+ this.isFormElementType = this.isFormElement(this.element.tagName);
3915
+ }
3916
+ if (props.onBeforeDestroy || props["on-before-destroy"]) {
3917
+ this.onBeforeDestroy = props.onBeforeDestroy || props["on-before-destroy"];
3887
3918
  }
3888
3919
  for (const event of EVENTS4) {
3889
3920
  if (props.attrs?.[event]) {
3890
3921
  const eventHandler = (e) => {
3891
- props.attrs[event]?.(e);
3922
+ if (event === "submit" && this.element.tagName.toLowerCase() === "form") {
3923
+ e.preventDefault();
3924
+ const formData = new FormData(this.element);
3925
+ const formObject = {};
3926
+ formData.forEach((value, key) => {
3927
+ if (formObject[key]) {
3928
+ if (Array.isArray(formObject[key])) {
3929
+ formObject[key].push(value);
3930
+ } else {
3931
+ formObject[key] = [formObject[key], value];
3932
+ }
3933
+ } else {
3934
+ formObject[key] = value;
3935
+ }
3936
+ });
3937
+ props.attrs[event]?.(e, formObject);
3938
+ } else {
3939
+ props.attrs[event]?.(e);
3940
+ }
3892
3941
  };
3893
3942
  this.eventListeners.set(event, eventHandler);
3894
3943
  this.element.addEventListener(event, eventHandler, false);
3895
3944
  }
3896
3945
  }
3946
+ if (props.children) {
3947
+ for (const child of props.children) {
3948
+ if (isObservable(child)) {
3949
+ child.subscribe(({ elements }) => {
3950
+ for (const element of elements) {
3951
+ this.element.appendChild(element.componentInstance.element);
3952
+ }
3953
+ });
3954
+ } else {
3955
+ this.element.appendChild(child.componentInstance.element);
3956
+ }
3957
+ }
3958
+ }
3959
+ this.onUpdate(props);
3960
+ }
3961
+ onMount(context) {
3962
+ const props = context.propObservables;
3963
+ const attrs = props.attrs;
3964
+ if (this.isFormElementType && attrs?.value && isSignal6(attrs.value)) {
3965
+ this.valueSignal = attrs.value;
3966
+ this.element.value = this.valueSignal();
3967
+ const inputHandler = (e) => {
3968
+ const target = e.target;
3969
+ this.valueSignal.set(target.value);
3970
+ };
3971
+ this.eventListeners.set("input", inputHandler);
3972
+ this.element.addEventListener("input", inputHandler, false);
3973
+ }
3897
3974
  }
3898
3975
  onUpdate(props) {
3899
- super.onUpdate(props);
3976
+ if (!this.element) return;
3900
3977
  for (const [key, value] of Object.entries(props.attrs || {})) {
3901
3978
  if (key === "class") {
3902
3979
  const classList = value.items || value.value || value;
@@ -3923,6 +4000,16 @@ var CanvasDOMContainer = class extends DisplayObject(PixiDOMContainer) {
3923
4000
  }
3924
4001
  }
3925
4002
  }
4003
+ } else if (key === "value" && this.isFormElementType) {
4004
+ if (isSignal6(value)) {
4005
+ const currentValue = this.element.value;
4006
+ const signalValue = value();
4007
+ if (currentValue !== signalValue) {
4008
+ this.element.value = signalValue;
4009
+ }
4010
+ } else {
4011
+ this.element.value = value;
4012
+ }
3926
4013
  } else if (!EVENTS4.includes(key)) {
3927
4014
  this.element.setAttribute(key, value);
3928
4015
  }
@@ -3930,21 +4017,37 @@ var CanvasDOMContainer = class extends DisplayObject(PixiDOMContainer) {
3930
4017
  if (props.textContent) {
3931
4018
  this.element.textContent = props.textContent;
3932
4019
  }
3933
- if (props.sortableChildren !== void 0) {
3934
- this.sortableChildren = props.sortableChildren;
3935
- }
3936
4020
  }
3937
4021
  async onDestroy(parent, afterDestroy) {
3938
4022
  if (this.element) {
4023
+ if (this.onBeforeDestroy) {
4024
+ await this.onBeforeDestroy();
4025
+ }
3939
4026
  for (const [event, handler] of this.eventListeners) {
3940
4027
  this.element.removeEventListener(event, handler, false);
3941
4028
  }
3942
4029
  this.eventListeners.clear();
4030
+ this.element.remove();
4031
+ if (afterDestroy) {
4032
+ afterDestroy();
4033
+ }
3943
4034
  }
3944
- const _afterDestroyCallback = async () => {
3945
- afterDestroy();
3946
- };
3947
- await super.onDestroy(parent, _afterDestroyCallback);
4035
+ }
4036
+ };
4037
+ registerComponent("DOMElement", CanvasDOMElement);
4038
+ var DOMElement = (props) => {
4039
+ return createComponent("DOMElement", props);
4040
+ };
4041
+
4042
+ // src/components/DOMContainer.ts
4043
+ var CanvasDOMContainer = class extends DisplayObject(PixiDOMContainer) {
4044
+ constructor() {
4045
+ super(...arguments);
4046
+ this.disableLayout = true;
4047
+ }
4048
+ onInit(props) {
4049
+ const div = h(DOMElement, { element: "div" }, props.children);
4050
+ this.element = div.componentInstance.element;
3948
4051
  }
3949
4052
  };
3950
4053
  registerComponent("DOMContainer", CanvasDOMContainer);
@@ -3955,17 +4058,22 @@ var DOMContainer = (props) => {
3955
4058
  // src/engine/bootstrap.ts
3956
4059
  import "@pixi/layout";
3957
4060
  import { Application as Application3 } from "pixi.js";
3958
- var bootstrapCanvas = async (rootElement, canvas) => {
4061
+ var bootstrapCanvas = async (rootElement, canvas, options) => {
3959
4062
  const app = new Application3();
3960
4063
  await app.init({
3961
4064
  resizeTo: rootElement,
3962
- autoStart: false
4065
+ autoStart: false,
4066
+ ...options ?? {}
3963
4067
  });
3964
4068
  const canvasElement = await h(canvas);
3965
4069
  if (canvasElement.tag != "Canvas") {
3966
4070
  throw new Error("Canvas is required");
3967
4071
  }
3968
4072
  canvasElement.render(rootElement, app);
4073
+ const { backgroundColor } = useProps(canvasElement.props, {
4074
+ backgroundColor: "black"
4075
+ });
4076
+ app.renderer.background.color = backgroundColor();
3969
4077
  return {
3970
4078
  canvasElement,
3971
4079
  app
@@ -4097,13 +4205,14 @@ var RadialGradient = class {
4097
4205
  };
4098
4206
 
4099
4207
  // src/index.ts
4100
- import { isObservable } from "rxjs";
4208
+ import { isObservable as isObservable2 } from "rxjs";
4101
4209
  import * as Howl3 from "howler";
4102
4210
  export {
4103
4211
  Canvas2 as Canvas,
4104
4212
  Circle,
4105
4213
  Container4 as Container,
4106
4214
  DOMContainer,
4215
+ DOMElement,
4107
4216
  DisplayObject,
4108
4217
  EVENTS2 as EVENTS,
4109
4218
  Easing,
@@ -4134,7 +4243,7 @@ export {
4134
4243
  h,
4135
4244
  isAnimatedSignal,
4136
4245
  isElement,
4137
- isObservable,
4246
+ isObservable2 as isObservable,
4138
4247
  isPrimitive,
4139
4248
  isTrigger,
4140
4249
  loop,