@mulsense/xnew 0.6.7 → 0.7.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/dist/xnew.mjs CHANGED
@@ -186,7 +186,7 @@ class Timer {
186
186
  this.id = null;
187
187
  this.time = { start: 0.0, processed: 0.0 };
188
188
  (_b = (_a = this.options).transition) === null || _b === void 0 ? void 0 : _b.call(_a, 1.0);
189
- (_d = (_c = this.options).callback) === null || _d === void 0 ? void 0 : _d.call(_c);
189
+ (_d = (_c = this.options).timeout) === null || _d === void 0 ? void 0 : _d.call(_c);
190
190
  this.clear();
191
191
  }, this.options.duration - this.time.processed);
192
192
  this.time.start = Date.now();
@@ -513,16 +513,26 @@ function pointer(element, event) {
513
513
  return { position };
514
514
  }
515
515
 
516
- //----------------------------------------------------------------------------------------------------
517
- // utils
518
- //----------------------------------------------------------------------------------------------------
519
516
  const SYSTEM_EVENTS = ['start', 'update', 'render', 'stop', 'finalize'];
520
517
  //----------------------------------------------------------------------------------------------------
521
518
  // unit
522
519
  //----------------------------------------------------------------------------------------------------
523
520
  class Unit {
524
- constructor(parent, target, Component, props) {
521
+ constructor(parent, ...args) {
525
522
  var _a;
523
+ let target;
524
+ let Component;
525
+ let props;
526
+ if (args[0] instanceof HTMLElement || args[0] instanceof SVGElement || typeof args[0] === 'string') {
527
+ target = args[0];
528
+ Component = args[1];
529
+ props = args[2];
530
+ }
531
+ else {
532
+ target = null;
533
+ Component = args[0];
534
+ props = args[1];
535
+ }
526
536
  const backup = Unit.currentUnit;
527
537
  Unit.currentUnit = this;
528
538
  parent === null || parent === void 0 ? void 0 : parent._.children.push(this);
@@ -644,7 +654,7 @@ class Unit {
644
654
  return element;
645
655
  }
646
656
  else {
647
- throw new Error(`xnew.nest: invalid html string [${target}]`);
657
+ throw new Error(`xnew.nest: invalid tag string [${target}]`);
648
658
  }
649
659
  }
650
660
  }
@@ -686,7 +696,7 @@ class Unit {
686
696
  Object.defineProperty(unit._.defines, key, wrapper);
687
697
  Object.defineProperty(unit, key, wrapper);
688
698
  });
689
- return defines;
699
+ return Object.assign({}, unit._.defines);
690
700
  }
691
701
  }
692
702
  static start(unit) {
@@ -723,7 +733,7 @@ class Unit {
723
733
  static reset() {
724
734
  var _a;
725
735
  (_a = Unit.rootUnit) === null || _a === void 0 ? void 0 : _a.finalize();
726
- Unit.currentUnit = Unit.rootUnit = new Unit(null, null);
736
+ Unit.currentUnit = Unit.rootUnit = new Unit(null);
727
737
  const ticker = new AnimationTicker(() => {
728
738
  Unit.start(Unit.rootUnit);
729
739
  Unit.update(Unit.rootUnit);
@@ -763,7 +773,7 @@ class Unit {
763
773
  }
764
774
  static getContext(unit, key) {
765
775
  for (let context = unit._.currentContext; context.previous !== null; context = context.previous) {
766
- if (context.value === Unit.currentUnit && key === Unit.currentUnit._.currentComponent)
776
+ if (context.value === Unit.currentUnit)
767
777
  continue;
768
778
  if (context.key === key)
769
779
  return context.value;
@@ -842,13 +852,13 @@ Unit.type2units = new MapSet();
842
852
  // extensions
843
853
  //----------------------------------------------------------------------------------------------------
844
854
  class UnitPromise {
845
- constructor(promise, Component) {
846
- this.promise = promise;
847
- this.Component = Component;
848
- }
855
+ constructor(promise) { this.promise = promise; }
849
856
  then(callback) { return this.wrap('then', callback); }
850
857
  catch(callback) { return this.wrap('catch', callback); }
851
858
  finally(callback) { return this.wrap('finally', callback); }
859
+ static all(promises) {
860
+ return new UnitPromise(Promise.all(promises.map(p => p.promise)));
861
+ }
852
862
  wrap(key, callback) {
853
863
  const snapshot = Unit.snapshot(Unit.currentUnit);
854
864
  this.promise = this.promise[key]((...args) => Unit.scope(snapshot, callback, ...args));
@@ -866,11 +876,11 @@ class UnitTimer {
866
876
  (_a = this.unit) === null || _a === void 0 ? void 0 : _a.finalize();
867
877
  this.unit = null;
868
878
  }
869
- timeout(callback, duration = 0) {
870
- return UnitTimer.execute(this, { callback, duration }, 1);
879
+ timeout(timeout, duration = 0) {
880
+ return UnitTimer.execute(this, { timeout, duration }, 1);
871
881
  }
872
- interval(callback, duration = 0, iterations = 0) {
873
- return UnitTimer.execute(this, { callback, duration }, iterations);
882
+ interval(timeout, duration = 0, iterations = 0) {
883
+ return UnitTimer.execute(this, { timeout, duration }, iterations);
874
884
  }
875
885
  transition(transition, duration = 0, easing) {
876
886
  return UnitTimer.execute(this, { transition, duration, easing }, 1);
@@ -878,7 +888,7 @@ class UnitTimer {
878
888
  static execute(timer, options, iterations) {
879
889
  const props = { options, iterations, snapshot: Unit.snapshot(Unit.currentUnit) };
880
890
  if (timer.unit === null || timer.unit._.state === 'finalized') {
881
- timer.unit = new Unit(Unit.currentUnit, null, UnitTimer.Component, props);
891
+ timer.unit = new Unit(Unit.currentUnit, UnitTimer.Component, props);
882
892
  }
883
893
  else if (timer.queue.length === 0) {
884
894
  timer.queue.push(props);
@@ -891,18 +901,18 @@ class UnitTimer {
891
901
  }
892
902
  static next(timer) {
893
903
  if (timer.queue.length > 0) {
894
- timer.unit = new Unit(Unit.currentUnit, null, UnitTimer.Component, timer.queue.shift());
904
+ timer.unit = new Unit(Unit.currentUnit, UnitTimer.Component, timer.queue.shift());
895
905
  timer.unit.on('finalize', () => UnitTimer.next(timer));
896
906
  }
897
907
  }
898
908
  static Component(unit, { options, iterations, snapshot }) {
899
909
  let counter = 0;
900
- let timer = new Timer({ callback, transition, duration: options.duration, easing: options.easing });
901
- function callback() {
902
- if (options.callback)
903
- Unit.scope(snapshot, options.callback);
910
+ let timer = new Timer({ timeout, transition, duration: options.duration, easing: options.easing });
911
+ function timeout() {
912
+ if (options.timeout)
913
+ Unit.scope(snapshot, options.timeout);
904
914
  if (iterations <= 0 || counter < iterations - 1) {
905
- timer = new Timer({ callback, transition, duration: options.duration, easing: options.easing });
915
+ timer = new Timer({ timeout, transition, duration: options.duration, easing: options.easing });
906
916
  }
907
917
  else {
908
918
  unit.finalize();
@@ -917,29 +927,31 @@ class UnitTimer {
917
927
  }
918
928
  }
919
929
 
920
- const xnew$1 = Object.assign(function (...args) {
930
+ const xnew$1 = Object.assign(
931
+ /**
932
+ * creates a new Unit component
933
+ * xnew(Component?: Function | string, props?: Object): Unit;
934
+ * xnew(target: HTMLElement | SVGElement | string, Component?: Function | string, props?: Object): Unit;
935
+ * @param target - HTMLElement | SVGElement, or HTML tag for new element
936
+ * @param Component - component function
937
+ * @param props - properties for component function
938
+ * @returns a new Unit instance
939
+ * @example
940
+ * const unit = xnew(MyComponent, { data: 0 })
941
+ * const unit = xnew(element, MyComponent, { data: 0 })
942
+ * const unit = xnew('<div>', MyComponent, { data: 0 })
943
+ */
944
+ function (...args) {
921
945
  if (Unit.rootUnit === undefined)
922
946
  Unit.reset();
923
- let target;
924
- if (args[0] instanceof HTMLElement || args[0] instanceof SVGElement) {
925
- target = args.shift(); // an existing html element
926
- }
927
- else if (typeof args[0] === 'string' && args[0].match(/<((\w+)[^>]*?)\/?>/)) {
928
- target = args.shift();
929
- }
930
- else {
931
- target = null;
932
- }
933
- const Component = args.shift();
934
- const props = args.shift();
935
- const unit = new Unit(Unit.currentUnit, target, Component, props);
936
- return unit;
947
+ return new Unit(Unit.currentUnit, ...args);
937
948
  }, {
938
949
  /**
939
- * Creates a nested HTML/SVG element within the current component
940
- * @param target - HTML or SVG tag string (e.g., '<div class="my-class">', '<span style="color:red">', '<svg viewBox="0 0 24 24">')
941
- * @returns The created HTML/SVG element
942
- * @throws Error if called after component initialization
950
+ * Creates a child HTML/SVG element inside the current component's element.
951
+ * Must be called during component initialization (before setup completes).
952
+ * @param target - An existing HTML/SVG element, or a tag string like `'<div>'`
953
+ * @returns The provided element, or the newly created element
954
+ * @throws Error if called after the component has finished initializing
943
955
  * @example
944
956
  * const div = xnew.nest('<div>')
945
957
  * div.textContent = 'Hello'
@@ -952,7 +964,7 @@ const xnew$1 = Object.assign(function (...args) {
952
964
  return Unit.nest(Unit.currentUnit, target);
953
965
  }
954
966
  catch (error) {
955
- console.error('xnew.nest(target: HTMLElement | SVGElement | string): ', error);
967
+ console.error('xnew.nest(target: UnitElement | string): ', error);
956
968
  throw error;
957
969
  }
958
970
  },
@@ -978,17 +990,25 @@ const xnew$1 = Object.assign(function (...args) {
978
990
  throw error;
979
991
  }
980
992
  },
993
+ append(parent, ...args) {
994
+ try {
995
+ new Unit(parent, ...args);
996
+ }
997
+ catch (error) {
998
+ console.error('xnew.append(parent: Unit, ...args: UnitArgs): ', error);
999
+ throw error;
1000
+ }
1001
+ },
981
1002
  /**
982
- * Gets a context value that can be accessed in follow context
983
- * @param key - component function
984
- * @returns The context value
1003
+ * Gets the Unit instance associated with the given component in the ancestor context chain
1004
+ * @param key - component function used as context key
1005
+ * @returns The Unit instance registered with the given component, or undefined if not found
985
1006
  * @example
986
- * // Create unit
987
- * const a = xnew(A);
988
- * ------------------------------
1007
+ * // Create parent unit with component A
1008
+ * const parent = xnew(A);
989
1009
  *
990
- * // Get context in child
991
- * const a = xnew.context(A)
1010
+ * // Inside a child component, get the parent unit
1011
+ * const parentUnit = xnew.context(A)
992
1012
  */
993
1013
  context(key) {
994
1014
  try {
@@ -1001,24 +1021,22 @@ const xnew$1 = Object.assign(function (...args) {
1001
1021
  },
1002
1022
  /**
1003
1023
  * Registers a promise with the current component for lifecycle management
1004
- * @param promise - Promise to register
1024
+ * @param promise - A Promise, async function, or Unit to register
1005
1025
  * @returns UnitPromise wrapper for chaining
1006
1026
  * @example
1007
1027
  * xnew.promise(fetchData()).then(data => console.log(data))
1008
1028
  */
1009
1029
  promise(promise) {
1010
1030
  try {
1011
- const Component = Unit.currentUnit._.currentComponent;
1012
1031
  let unitPromise;
1013
1032
  if (promise instanceof Unit) {
1014
- unitPromise = new UnitPromise(Promise.all(promise._.promises.map(p => p.promise)), Component)
1015
- .then(() => promise._.results);
1033
+ unitPromise = UnitPromise.all(promise._.promises).then(() => promise._.results);
1016
1034
  }
1017
1035
  else if (promise instanceof Promise) {
1018
- unitPromise = new UnitPromise(promise, Component);
1036
+ unitPromise = new UnitPromise(promise);
1019
1037
  }
1020
1038
  else {
1021
- unitPromise = new UnitPromise(new Promise(xnew$1.scope(promise)), Component);
1039
+ unitPromise = new UnitPromise(new Promise(xnew$1.scope(promise)));
1022
1040
  }
1023
1041
  Unit.currentUnit._.promises.push(unitPromise);
1024
1042
  return unitPromise;
@@ -1038,8 +1056,7 @@ const xnew$1 = Object.assign(function (...args) {
1038
1056
  then(callback) {
1039
1057
  try {
1040
1058
  const currentUnit = Unit.currentUnit;
1041
- return new UnitPromise(Promise.all(Unit.currentUnit._.promises.map(p => p.promise)), null)
1042
- .then(() => callback(currentUnit._.results));
1059
+ return UnitPromise.all(Unit.currentUnit._.promises).then(() => callback(currentUnit._.results));
1043
1060
  }
1044
1061
  catch (error) {
1045
1062
  console.error('xnew.then(callback: Function): ', error);
@@ -1055,7 +1072,7 @@ const xnew$1 = Object.assign(function (...args) {
1055
1072
  */
1056
1073
  catch(callback) {
1057
1074
  try {
1058
- return new UnitPromise(Promise.all(Unit.currentUnit._.promises.map(p => p.promise)), null)
1075
+ return UnitPromise.all(Unit.currentUnit._.promises)
1059
1076
  .catch(callback);
1060
1077
  }
1061
1078
  catch (error) {
@@ -1064,35 +1081,67 @@ const xnew$1 = Object.assign(function (...args) {
1064
1081
  }
1065
1082
  },
1066
1083
  /**
1067
- * Commits a value to the current unit's promise results
1068
- * @param object - object to commit to the promise
1069
- * @returns void
1084
+ * Executes callback after all registered promises settle (resolve or reject)
1085
+ * @param callback - Function to call after promises settle
1086
+ * @returns UnitPromise for chaining
1070
1087
  * @example
1071
- * xnew.commit({ data: 123});
1088
+ * xnew.finally(() => console.log('All promises settled'))
1072
1089
  */
1073
- commit(object) {
1090
+ finally(callback) {
1074
1091
  try {
1075
- Object.assign(Unit.currentUnit._.results, object);
1092
+ return UnitPromise.all(Unit.currentUnit._.promises).finally(callback);
1076
1093
  }
1077
1094
  catch (error) {
1078
- console.error('xnew.commit(object?: Record<string, any>): ', error);
1095
+ console.error('xnew.finally(callback: Function): ', error);
1079
1096
  throw error;
1080
1097
  }
1081
1098
  },
1099
+ resolvers() {
1100
+ let state = null;
1101
+ let resolve = null;
1102
+ let reject = null;
1103
+ const unitPromise = new UnitPromise(new Promise((res, rej) => {
1104
+ if (state === 'resolved') {
1105
+ res(null);
1106
+ }
1107
+ else if (state === 'rejected') {
1108
+ rej();
1109
+ }
1110
+ else {
1111
+ resolve = res;
1112
+ reject = rej;
1113
+ state = 'pending';
1114
+ }
1115
+ }));
1116
+ Unit.currentUnit._.promises.push(unitPromise);
1117
+ return {
1118
+ resolve() {
1119
+ if (state === 'pending') {
1120
+ resolve === null || resolve === void 0 ? void 0 : resolve(null);
1121
+ }
1122
+ state = 'resolved';
1123
+ },
1124
+ reject() {
1125
+ if (state === 'pending') {
1126
+ reject === null || reject === void 0 ? void 0 : reject();
1127
+ }
1128
+ state = 'rejected';
1129
+ }
1130
+ };
1131
+ },
1082
1132
  /**
1083
- * Executes callback after all registered promises settle (resolve or reject)
1084
- * @param callback - Function to call after promises settle
1085
- * @returns UnitPromise for chaining
1133
+ * Outputs a value to the current unit's promise results
1134
+ * @param object - object to output for the promise
1135
+ * @returns void
1086
1136
  * @example
1087
- * xnew.finally(() => console.log('All promises settled'))
1137
+ * xnew.output({ data: 123});
1088
1138
  */
1089
- finally(callback) {
1139
+ output(object) {
1090
1140
  try {
1091
- return new UnitPromise(Promise.all(Unit.currentUnit._.promises.map(p => p.promise)), null)
1092
- .finally(callback);
1141
+ Object.assign(Unit.currentUnit._.results, object);
1093
1142
  }
1094
1143
  catch (error) {
1095
- console.error('xnew.finally(callback: Function): ', error);
1144
+ console.error('xnew.output(object?: Record<string, any>): ', error);
1096
1145
  throw error;
1097
1146
  }
1098
1147
  },
@@ -1130,7 +1179,7 @@ const xnew$1 = Object.assign(function (...args) {
1130
1179
  /**
1131
1180
  * Emits a custom event to components
1132
1181
  * @param type - Event type to emit (prefix with '+' for global events, '-' for local events)
1133
- * @param args - Additional arguments to pass to event listeners
1182
+ * @param props - Event properties object to pass to listeners
1134
1183
  * @returns void
1135
1184
  * @example
1136
1185
  * xnew.emit('+globalevent', { data: 123 }); // Global event
@@ -1147,7 +1196,7 @@ const xnew$1 = Object.assign(function (...args) {
1147
1196
  },
1148
1197
  /**
1149
1198
  * Executes a callback once after a delay, managed by component lifecycle
1150
- * @param callback - Function to execute after Duration
1199
+ * @param callback - Function to execute after duration
1151
1200
  * @param duration - Duration in milliseconds
1152
1201
  * @returns Object with clear() method to cancel the timeout
1153
1202
  * @example
@@ -1256,7 +1305,8 @@ function Popup(unit) {
1256
1305
  });
1257
1306
  }
1258
1307
 
1259
- function Screen(unit, { aspect, fit = 'contain' } = {}) {
1308
+ function Screen(unit, { width = 800, height = 600, fit = 'contain' } = {}) {
1309
+ const aspect = width / height;
1260
1310
  xnew$1.nest('<div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; container-type: size; overflow: hidden;">');
1261
1311
  xnew$1.nest(`<div style="position: relative; aspect-ratio: ${aspect}; container-type: size; overflow: hidden;">`);
1262
1312
  if (fit === 'contain') {
@@ -1266,6 +1316,10 @@ function Screen(unit, { aspect, fit = 'contain' } = {}) {
1266
1316
  unit.element.style.flexShrink = '0';
1267
1317
  unit.element.style.width = `max(100cqw, calc(100cqh * ${aspect}))`;
1268
1318
  }
1319
+ const canvas = xnew$1(`<canvas width="${width}" height="${height}" style="width: 100%; height: 100%; vertical-align: bottom;">`);
1320
+ return {
1321
+ get canvas() { return canvas.element; },
1322
+ };
1269
1323
  }
1270
1324
 
1271
1325
  //----------------------------------------------------------------------------------------------------
@@ -1274,14 +1328,14 @@ function Screen(unit, { aspect, fit = 'contain' } = {}) {
1274
1328
  function SVGTemplate(self, { stroke = 'currentColor', strokeOpacity = 0.8, strokeWidth = 1, strokeLinejoin = 'round', fill = null, fillOpacity = 0.8 }) {
1275
1329
  xnew$1.nest(`<svg
1276
1330
  viewBox="0 0 64 64"
1277
- style="position: absolute; width: 100%; height: 100%; user-select: none;
1331
+ style="position: absolute; width: 100%; height: 100%; user-select: none; -webkit-user-select: none;
1278
1332
  stroke: ${stroke}; stroke-opacity: ${strokeOpacity}; stroke-width: ${strokeWidth}; stroke-linejoin: ${strokeLinejoin};
1279
1333
  ${fill ? `fill: ${fill}; fill-opacity: ${fillOpacity};` : ''}
1280
1334
  ">`);
1281
1335
  }
1282
1336
  function AnalogStick(unit, { stroke = 'currentColor', strokeOpacity = 0.8, strokeWidth = 1, strokeLinejoin = 'round', fill = '#FFF', fillOpacity = 0.8 } = {}) {
1283
1337
  xnew$1.nest(`<div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; container-type: size;">`);
1284
- xnew$1.nest(`<div style="width: min(100cqw, 100cqh); aspect-ratio: 1; cursor: pointer; user-select: none; pointer-events: auto; overflow: hidden;">`);
1338
+ xnew$1.nest(`<div style="width: min(100cqw, 100cqh); aspect-ratio: 1; cursor: pointer; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; touch-action: none; pointer-events: auto; overflow: hidden;">`);
1285
1339
  xnew$1((unit) => {
1286
1340
  xnew$1.extend(SVGTemplate, { fill, fillOpacity, stroke, strokeOpacity, strokeWidth, strokeLinejoin });
1287
1341
  xnew$1('<polygon points="32 7 27 13 37 13">');
@@ -1317,7 +1371,7 @@ function AnalogStick(unit, { stroke = 'currentColor', strokeOpacity = 0.8, strok
1317
1371
  }
1318
1372
  function DPad(unit, { diagonal = true, stroke = 'currentColor', strokeOpacity = 0.8, strokeWidth = 1, strokeLinejoin = 'round', fill = '#FFF', fillOpacity = 0.8 } = {}) {
1319
1373
  xnew$1.nest(`<div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; container-type: size;">`);
1320
- xnew$1.nest(`<div style="width: min(100cqw, 100cqh); aspect-ratio: 1; cursor: pointer; user-select: none; pointer-events: auto; overflow: hidden;">`);
1374
+ xnew$1.nest(`<div style="width: min(100cqw, 100cqh); aspect-ratio: 1; cursor: pointer; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; touch-action: none; pointer-events: auto; overflow: hidden;">`);
1321
1375
  const polygons = [
1322
1376
  '<polygon points="32 32 23 23 23 4 24 3 40 3 41 4 41 23">',
1323
1377
  '<polygon points="32 32 23 41 23 60 24 61 40 61 41 60 41 41">',
@@ -1550,6 +1604,8 @@ function Select(_, { key = '', value, items = [] } = {}) {
1550
1604
  }
1551
1605
  }
1552
1606
 
1607
+ function Scene(unit) {
1608
+ }
1553
1609
  function Flow(unit) {
1554
1610
  let scene = null;
1555
1611
  return {
@@ -1559,15 +1615,52 @@ function Flow(unit) {
1559
1615
  get scene() {
1560
1616
  return scene;
1561
1617
  },
1562
- next(Component, props) {
1563
- var _a;
1564
- // scene change
1565
- (_a = unit.scene) === null || _a === void 0 ? void 0 : _a.finalize();
1566
- unit.scene = xnew$1(Component, props);
1567
- }
1618
+ next(Component, props, callback) {
1619
+ callback = callback !== null && callback !== void 0 ? callback : defaultCallback;
1620
+ callback(scene, create);
1621
+ function defaultCallback(current, create) {
1622
+ current === null || current === void 0 ? void 0 : current.finalize();
1623
+ create();
1624
+ }
1625
+ function create() {
1626
+ scene = xnew$1((unit) => {
1627
+ xnew$1.extend(Scene);
1628
+ xnew$1.extend(Component, props);
1629
+ });
1630
+ return scene;
1631
+ }
1632
+ },
1568
1633
  };
1569
1634
  }
1570
1635
 
1636
+ class XImage {
1637
+ constructor(...args) {
1638
+ if (args[0] instanceof HTMLCanvasElement) {
1639
+ this.canvas = args[0];
1640
+ }
1641
+ else {
1642
+ const canvas = document.createElement('canvas');
1643
+ canvas.width = args[0];
1644
+ canvas.height = args[1];
1645
+ this.canvas = canvas;
1646
+ }
1647
+ }
1648
+ clip(x, y, width, height) {
1649
+ var _a;
1650
+ const canvas = document.createElement('canvas');
1651
+ canvas.width = width;
1652
+ canvas.height = height;
1653
+ (_a = canvas.getContext('2d')) === null || _a === void 0 ? void 0 : _a.drawImage(this.canvas, x, y, width, height, 0, 0, width, height);
1654
+ return new XImage(canvas);
1655
+ }
1656
+ download(filename) {
1657
+ const link = document.createElement('a');
1658
+ link.download = filename;
1659
+ link.href = this.canvas.toDataURL('image/png');
1660
+ link.click();
1661
+ }
1662
+ }
1663
+
1571
1664
  const context = new window.AudioContext();
1572
1665
  const master = context.createGain();
1573
1666
  //----------------------------------------------------------------------------------------------------
@@ -1801,6 +1894,7 @@ const basics = {
1801
1894
  Accordion,
1802
1895
  Popup,
1803
1896
  Flow,
1897
+ Scene,
1804
1898
  };
1805
1899
  const audio = {
1806
1900
  load(path) {
@@ -1829,6 +1923,11 @@ const audio = {
1829
1923
  master.gain.value = value;
1830
1924
  }
1831
1925
  };
1832
- const xnew = Object.assign(xnew$1, { basics, audio });
1926
+ const image = {
1927
+ from(canvas) {
1928
+ return new XImage(canvas);
1929
+ }
1930
+ };
1931
+ const xnew = Object.assign(xnew$1, { basics, audio, image });
1833
1932
 
1834
1933
  export { xnew as default };
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "keywords": [
5
5
  "Component-Oriented Programming"
6
6
  ],
7
- "version": "0.6.7",
7
+ "version": "0.7.0",
8
8
  "main": "dist/xnew.js",
9
9
  "module": "dist/xnew.mjs",
10
10
  "types": "dist/xnew.d.ts",