@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.js CHANGED
@@ -192,7 +192,7 @@
192
192
  this.id = null;
193
193
  this.time = { start: 0.0, processed: 0.0 };
194
194
  (_b = (_a = this.options).transition) === null || _b === void 0 ? void 0 : _b.call(_a, 1.0);
195
- (_d = (_c = this.options).callback) === null || _d === void 0 ? void 0 : _d.call(_c);
195
+ (_d = (_c = this.options).timeout) === null || _d === void 0 ? void 0 : _d.call(_c);
196
196
  this.clear();
197
197
  }, this.options.duration - this.time.processed);
198
198
  this.time.start = Date.now();
@@ -519,16 +519,26 @@
519
519
  return { position };
520
520
  }
521
521
 
522
- //----------------------------------------------------------------------------------------------------
523
- // utils
524
- //----------------------------------------------------------------------------------------------------
525
522
  const SYSTEM_EVENTS = ['start', 'update', 'render', 'stop', 'finalize'];
526
523
  //----------------------------------------------------------------------------------------------------
527
524
  // unit
528
525
  //----------------------------------------------------------------------------------------------------
529
526
  class Unit {
530
- constructor(parent, target, Component, props) {
527
+ constructor(parent, ...args) {
531
528
  var _a;
529
+ let target;
530
+ let Component;
531
+ let props;
532
+ if (args[0] instanceof HTMLElement || args[0] instanceof SVGElement || typeof args[0] === 'string') {
533
+ target = args[0];
534
+ Component = args[1];
535
+ props = args[2];
536
+ }
537
+ else {
538
+ target = null;
539
+ Component = args[0];
540
+ props = args[1];
541
+ }
532
542
  const backup = Unit.currentUnit;
533
543
  Unit.currentUnit = this;
534
544
  parent === null || parent === void 0 ? void 0 : parent._.children.push(this);
@@ -650,7 +660,7 @@
650
660
  return element;
651
661
  }
652
662
  else {
653
- throw new Error(`xnew.nest: invalid html string [${target}]`);
663
+ throw new Error(`xnew.nest: invalid tag string [${target}]`);
654
664
  }
655
665
  }
656
666
  }
@@ -692,7 +702,7 @@
692
702
  Object.defineProperty(unit._.defines, key, wrapper);
693
703
  Object.defineProperty(unit, key, wrapper);
694
704
  });
695
- return defines;
705
+ return Object.assign({}, unit._.defines);
696
706
  }
697
707
  }
698
708
  static start(unit) {
@@ -729,7 +739,7 @@
729
739
  static reset() {
730
740
  var _a;
731
741
  (_a = Unit.rootUnit) === null || _a === void 0 ? void 0 : _a.finalize();
732
- Unit.currentUnit = Unit.rootUnit = new Unit(null, null);
742
+ Unit.currentUnit = Unit.rootUnit = new Unit(null);
733
743
  const ticker = new AnimationTicker(() => {
734
744
  Unit.start(Unit.rootUnit);
735
745
  Unit.update(Unit.rootUnit);
@@ -769,7 +779,7 @@
769
779
  }
770
780
  static getContext(unit, key) {
771
781
  for (let context = unit._.currentContext; context.previous !== null; context = context.previous) {
772
- if (context.value === Unit.currentUnit && key === Unit.currentUnit._.currentComponent)
782
+ if (context.value === Unit.currentUnit)
773
783
  continue;
774
784
  if (context.key === key)
775
785
  return context.value;
@@ -848,13 +858,13 @@
848
858
  // extensions
849
859
  //----------------------------------------------------------------------------------------------------
850
860
  class UnitPromise {
851
- constructor(promise, Component) {
852
- this.promise = promise;
853
- this.Component = Component;
854
- }
861
+ constructor(promise) { this.promise = promise; }
855
862
  then(callback) { return this.wrap('then', callback); }
856
863
  catch(callback) { return this.wrap('catch', callback); }
857
864
  finally(callback) { return this.wrap('finally', callback); }
865
+ static all(promises) {
866
+ return new UnitPromise(Promise.all(promises.map(p => p.promise)));
867
+ }
858
868
  wrap(key, callback) {
859
869
  const snapshot = Unit.snapshot(Unit.currentUnit);
860
870
  this.promise = this.promise[key]((...args) => Unit.scope(snapshot, callback, ...args));
@@ -872,11 +882,11 @@
872
882
  (_a = this.unit) === null || _a === void 0 ? void 0 : _a.finalize();
873
883
  this.unit = null;
874
884
  }
875
- timeout(callback, duration = 0) {
876
- return UnitTimer.execute(this, { callback, duration }, 1);
885
+ timeout(timeout, duration = 0) {
886
+ return UnitTimer.execute(this, { timeout, duration }, 1);
877
887
  }
878
- interval(callback, duration = 0, iterations = 0) {
879
- return UnitTimer.execute(this, { callback, duration }, iterations);
888
+ interval(timeout, duration = 0, iterations = 0) {
889
+ return UnitTimer.execute(this, { timeout, duration }, iterations);
880
890
  }
881
891
  transition(transition, duration = 0, easing) {
882
892
  return UnitTimer.execute(this, { transition, duration, easing }, 1);
@@ -884,7 +894,7 @@
884
894
  static execute(timer, options, iterations) {
885
895
  const props = { options, iterations, snapshot: Unit.snapshot(Unit.currentUnit) };
886
896
  if (timer.unit === null || timer.unit._.state === 'finalized') {
887
- timer.unit = new Unit(Unit.currentUnit, null, UnitTimer.Component, props);
897
+ timer.unit = new Unit(Unit.currentUnit, UnitTimer.Component, props);
888
898
  }
889
899
  else if (timer.queue.length === 0) {
890
900
  timer.queue.push(props);
@@ -897,18 +907,18 @@
897
907
  }
898
908
  static next(timer) {
899
909
  if (timer.queue.length > 0) {
900
- timer.unit = new Unit(Unit.currentUnit, null, UnitTimer.Component, timer.queue.shift());
910
+ timer.unit = new Unit(Unit.currentUnit, UnitTimer.Component, timer.queue.shift());
901
911
  timer.unit.on('finalize', () => UnitTimer.next(timer));
902
912
  }
903
913
  }
904
914
  static Component(unit, { options, iterations, snapshot }) {
905
915
  let counter = 0;
906
- let timer = new Timer({ callback, transition, duration: options.duration, easing: options.easing });
907
- function callback() {
908
- if (options.callback)
909
- Unit.scope(snapshot, options.callback);
916
+ let timer = new Timer({ timeout, transition, duration: options.duration, easing: options.easing });
917
+ function timeout() {
918
+ if (options.timeout)
919
+ Unit.scope(snapshot, options.timeout);
910
920
  if (iterations <= 0 || counter < iterations - 1) {
911
- timer = new Timer({ callback, transition, duration: options.duration, easing: options.easing });
921
+ timer = new Timer({ timeout, transition, duration: options.duration, easing: options.easing });
912
922
  }
913
923
  else {
914
924
  unit.finalize();
@@ -923,29 +933,31 @@
923
933
  }
924
934
  }
925
935
 
926
- const xnew$1 = Object.assign(function (...args) {
936
+ const xnew$1 = Object.assign(
937
+ /**
938
+ * creates a new Unit component
939
+ * xnew(Component?: Function | string, props?: Object): Unit;
940
+ * xnew(target: HTMLElement | SVGElement | string, Component?: Function | string, props?: Object): Unit;
941
+ * @param target - HTMLElement | SVGElement, or HTML tag for new element
942
+ * @param Component - component function
943
+ * @param props - properties for component function
944
+ * @returns a new Unit instance
945
+ * @example
946
+ * const unit = xnew(MyComponent, { data: 0 })
947
+ * const unit = xnew(element, MyComponent, { data: 0 })
948
+ * const unit = xnew('<div>', MyComponent, { data: 0 })
949
+ */
950
+ function (...args) {
927
951
  if (Unit.rootUnit === undefined)
928
952
  Unit.reset();
929
- let target;
930
- if (args[0] instanceof HTMLElement || args[0] instanceof SVGElement) {
931
- target = args.shift(); // an existing html element
932
- }
933
- else if (typeof args[0] === 'string' && args[0].match(/<((\w+)[^>]*?)\/?>/)) {
934
- target = args.shift();
935
- }
936
- else {
937
- target = null;
938
- }
939
- const Component = args.shift();
940
- const props = args.shift();
941
- const unit = new Unit(Unit.currentUnit, target, Component, props);
942
- return unit;
953
+ return new Unit(Unit.currentUnit, ...args);
943
954
  }, {
944
955
  /**
945
- * Creates a nested HTML/SVG element within the current component
946
- * @param target - HTML or SVG tag string (e.g., '<div class="my-class">', '<span style="color:red">', '<svg viewBox="0 0 24 24">')
947
- * @returns The created HTML/SVG element
948
- * @throws Error if called after component initialization
956
+ * Creates a child HTML/SVG element inside the current component's element.
957
+ * Must be called during component initialization (before setup completes).
958
+ * @param target - An existing HTML/SVG element, or a tag string like `'<div>'`
959
+ * @returns The provided element, or the newly created element
960
+ * @throws Error if called after the component has finished initializing
949
961
  * @example
950
962
  * const div = xnew.nest('<div>')
951
963
  * div.textContent = 'Hello'
@@ -958,7 +970,7 @@
958
970
  return Unit.nest(Unit.currentUnit, target);
959
971
  }
960
972
  catch (error) {
961
- console.error('xnew.nest(target: HTMLElement | SVGElement | string): ', error);
973
+ console.error('xnew.nest(target: UnitElement | string): ', error);
962
974
  throw error;
963
975
  }
964
976
  },
@@ -984,17 +996,25 @@
984
996
  throw error;
985
997
  }
986
998
  },
999
+ append(parent, ...args) {
1000
+ try {
1001
+ new Unit(parent, ...args);
1002
+ }
1003
+ catch (error) {
1004
+ console.error('xnew.append(parent: Unit, ...args: UnitArgs): ', error);
1005
+ throw error;
1006
+ }
1007
+ },
987
1008
  /**
988
- * Gets a context value that can be accessed in follow context
989
- * @param key - component function
990
- * @returns The context value
1009
+ * Gets the Unit instance associated with the given component in the ancestor context chain
1010
+ * @param key - component function used as context key
1011
+ * @returns The Unit instance registered with the given component, or undefined if not found
991
1012
  * @example
992
- * // Create unit
993
- * const a = xnew(A);
994
- * ------------------------------
1013
+ * // Create parent unit with component A
1014
+ * const parent = xnew(A);
995
1015
  *
996
- * // Get context in child
997
- * const a = xnew.context(A)
1016
+ * // Inside a child component, get the parent unit
1017
+ * const parentUnit = xnew.context(A)
998
1018
  */
999
1019
  context(key) {
1000
1020
  try {
@@ -1007,24 +1027,22 @@
1007
1027
  },
1008
1028
  /**
1009
1029
  * Registers a promise with the current component for lifecycle management
1010
- * @param promise - Promise to register
1030
+ * @param promise - A Promise, async function, or Unit to register
1011
1031
  * @returns UnitPromise wrapper for chaining
1012
1032
  * @example
1013
1033
  * xnew.promise(fetchData()).then(data => console.log(data))
1014
1034
  */
1015
1035
  promise(promise) {
1016
1036
  try {
1017
- const Component = Unit.currentUnit._.currentComponent;
1018
1037
  let unitPromise;
1019
1038
  if (promise instanceof Unit) {
1020
- unitPromise = new UnitPromise(Promise.all(promise._.promises.map(p => p.promise)), Component)
1021
- .then(() => promise._.results);
1039
+ unitPromise = UnitPromise.all(promise._.promises).then(() => promise._.results);
1022
1040
  }
1023
1041
  else if (promise instanceof Promise) {
1024
- unitPromise = new UnitPromise(promise, Component);
1042
+ unitPromise = new UnitPromise(promise);
1025
1043
  }
1026
1044
  else {
1027
- unitPromise = new UnitPromise(new Promise(xnew$1.scope(promise)), Component);
1045
+ unitPromise = new UnitPromise(new Promise(xnew$1.scope(promise)));
1028
1046
  }
1029
1047
  Unit.currentUnit._.promises.push(unitPromise);
1030
1048
  return unitPromise;
@@ -1044,8 +1062,7 @@
1044
1062
  then(callback) {
1045
1063
  try {
1046
1064
  const currentUnit = Unit.currentUnit;
1047
- return new UnitPromise(Promise.all(Unit.currentUnit._.promises.map(p => p.promise)), null)
1048
- .then(() => callback(currentUnit._.results));
1065
+ return UnitPromise.all(Unit.currentUnit._.promises).then(() => callback(currentUnit._.results));
1049
1066
  }
1050
1067
  catch (error) {
1051
1068
  console.error('xnew.then(callback: Function): ', error);
@@ -1061,7 +1078,7 @@
1061
1078
  */
1062
1079
  catch(callback) {
1063
1080
  try {
1064
- return new UnitPromise(Promise.all(Unit.currentUnit._.promises.map(p => p.promise)), null)
1081
+ return UnitPromise.all(Unit.currentUnit._.promises)
1065
1082
  .catch(callback);
1066
1083
  }
1067
1084
  catch (error) {
@@ -1070,35 +1087,67 @@
1070
1087
  }
1071
1088
  },
1072
1089
  /**
1073
- * Commits a value to the current unit's promise results
1074
- * @param object - object to commit to the promise
1075
- * @returns void
1090
+ * Executes callback after all registered promises settle (resolve or reject)
1091
+ * @param callback - Function to call after promises settle
1092
+ * @returns UnitPromise for chaining
1076
1093
  * @example
1077
- * xnew.commit({ data: 123});
1094
+ * xnew.finally(() => console.log('All promises settled'))
1078
1095
  */
1079
- commit(object) {
1096
+ finally(callback) {
1080
1097
  try {
1081
- Object.assign(Unit.currentUnit._.results, object);
1098
+ return UnitPromise.all(Unit.currentUnit._.promises).finally(callback);
1082
1099
  }
1083
1100
  catch (error) {
1084
- console.error('xnew.commit(object?: Record<string, any>): ', error);
1101
+ console.error('xnew.finally(callback: Function): ', error);
1085
1102
  throw error;
1086
1103
  }
1087
1104
  },
1105
+ resolvers() {
1106
+ let state = null;
1107
+ let resolve = null;
1108
+ let reject = null;
1109
+ const unitPromise = new UnitPromise(new Promise((res, rej) => {
1110
+ if (state === 'resolved') {
1111
+ res(null);
1112
+ }
1113
+ else if (state === 'rejected') {
1114
+ rej();
1115
+ }
1116
+ else {
1117
+ resolve = res;
1118
+ reject = rej;
1119
+ state = 'pending';
1120
+ }
1121
+ }));
1122
+ Unit.currentUnit._.promises.push(unitPromise);
1123
+ return {
1124
+ resolve() {
1125
+ if (state === 'pending') {
1126
+ resolve === null || resolve === void 0 ? void 0 : resolve(null);
1127
+ }
1128
+ state = 'resolved';
1129
+ },
1130
+ reject() {
1131
+ if (state === 'pending') {
1132
+ reject === null || reject === void 0 ? void 0 : reject();
1133
+ }
1134
+ state = 'rejected';
1135
+ }
1136
+ };
1137
+ },
1088
1138
  /**
1089
- * Executes callback after all registered promises settle (resolve or reject)
1090
- * @param callback - Function to call after promises settle
1091
- * @returns UnitPromise for chaining
1139
+ * Outputs a value to the current unit's promise results
1140
+ * @param object - object to output for the promise
1141
+ * @returns void
1092
1142
  * @example
1093
- * xnew.finally(() => console.log('All promises settled'))
1143
+ * xnew.output({ data: 123});
1094
1144
  */
1095
- finally(callback) {
1145
+ output(object) {
1096
1146
  try {
1097
- return new UnitPromise(Promise.all(Unit.currentUnit._.promises.map(p => p.promise)), null)
1098
- .finally(callback);
1147
+ Object.assign(Unit.currentUnit._.results, object);
1099
1148
  }
1100
1149
  catch (error) {
1101
- console.error('xnew.finally(callback: Function): ', error);
1150
+ console.error('xnew.output(object?: Record<string, any>): ', error);
1102
1151
  throw error;
1103
1152
  }
1104
1153
  },
@@ -1136,7 +1185,7 @@
1136
1185
  /**
1137
1186
  * Emits a custom event to components
1138
1187
  * @param type - Event type to emit (prefix with '+' for global events, '-' for local events)
1139
- * @param args - Additional arguments to pass to event listeners
1188
+ * @param props - Event properties object to pass to listeners
1140
1189
  * @returns void
1141
1190
  * @example
1142
1191
  * xnew.emit('+globalevent', { data: 123 }); // Global event
@@ -1153,7 +1202,7 @@
1153
1202
  },
1154
1203
  /**
1155
1204
  * Executes a callback once after a delay, managed by component lifecycle
1156
- * @param callback - Function to execute after Duration
1205
+ * @param callback - Function to execute after duration
1157
1206
  * @param duration - Duration in milliseconds
1158
1207
  * @returns Object with clear() method to cancel the timeout
1159
1208
  * @example
@@ -1262,7 +1311,8 @@
1262
1311
  });
1263
1312
  }
1264
1313
 
1265
- function Screen(unit, { aspect, fit = 'contain' } = {}) {
1314
+ function Screen(unit, { width = 800, height = 600, fit = 'contain' } = {}) {
1315
+ const aspect = width / height;
1266
1316
  xnew$1.nest('<div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; container-type: size; overflow: hidden;">');
1267
1317
  xnew$1.nest(`<div style="position: relative; aspect-ratio: ${aspect}; container-type: size; overflow: hidden;">`);
1268
1318
  if (fit === 'contain') {
@@ -1272,6 +1322,10 @@
1272
1322
  unit.element.style.flexShrink = '0';
1273
1323
  unit.element.style.width = `max(100cqw, calc(100cqh * ${aspect}))`;
1274
1324
  }
1325
+ const canvas = xnew$1(`<canvas width="${width}" height="${height}" style="width: 100%; height: 100%; vertical-align: bottom;">`);
1326
+ return {
1327
+ get canvas() { return canvas.element; },
1328
+ };
1275
1329
  }
1276
1330
 
1277
1331
  //----------------------------------------------------------------------------------------------------
@@ -1280,14 +1334,14 @@
1280
1334
  function SVGTemplate(self, { stroke = 'currentColor', strokeOpacity = 0.8, strokeWidth = 1, strokeLinejoin = 'round', fill = null, fillOpacity = 0.8 }) {
1281
1335
  xnew$1.nest(`<svg
1282
1336
  viewBox="0 0 64 64"
1283
- style="position: absolute; width: 100%; height: 100%; user-select: none;
1337
+ style="position: absolute; width: 100%; height: 100%; user-select: none; -webkit-user-select: none;
1284
1338
  stroke: ${stroke}; stroke-opacity: ${strokeOpacity}; stroke-width: ${strokeWidth}; stroke-linejoin: ${strokeLinejoin};
1285
1339
  ${fill ? `fill: ${fill}; fill-opacity: ${fillOpacity};` : ''}
1286
1340
  ">`);
1287
1341
  }
1288
1342
  function AnalogStick(unit, { stroke = 'currentColor', strokeOpacity = 0.8, strokeWidth = 1, strokeLinejoin = 'round', fill = '#FFF', fillOpacity = 0.8 } = {}) {
1289
1343
  xnew$1.nest(`<div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; container-type: size;">`);
1290
- xnew$1.nest(`<div style="width: min(100cqw, 100cqh); aspect-ratio: 1; cursor: pointer; user-select: none; pointer-events: auto; overflow: hidden;">`);
1344
+ 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;">`);
1291
1345
  xnew$1((unit) => {
1292
1346
  xnew$1.extend(SVGTemplate, { fill, fillOpacity, stroke, strokeOpacity, strokeWidth, strokeLinejoin });
1293
1347
  xnew$1('<polygon points="32 7 27 13 37 13">');
@@ -1323,7 +1377,7 @@
1323
1377
  }
1324
1378
  function DPad(unit, { diagonal = true, stroke = 'currentColor', strokeOpacity = 0.8, strokeWidth = 1, strokeLinejoin = 'round', fill = '#FFF', fillOpacity = 0.8 } = {}) {
1325
1379
  xnew$1.nest(`<div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; container-type: size;">`);
1326
- xnew$1.nest(`<div style="width: min(100cqw, 100cqh); aspect-ratio: 1; cursor: pointer; user-select: none; pointer-events: auto; overflow: hidden;">`);
1380
+ 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;">`);
1327
1381
  const polygons = [
1328
1382
  '<polygon points="32 32 23 23 23 4 24 3 40 3 41 4 41 23">',
1329
1383
  '<polygon points="32 32 23 41 23 60 24 61 40 61 41 60 41 41">',
@@ -1556,6 +1610,8 @@
1556
1610
  }
1557
1611
  }
1558
1612
 
1613
+ function Scene(unit) {
1614
+ }
1559
1615
  function Flow(unit) {
1560
1616
  let scene = null;
1561
1617
  return {
@@ -1565,15 +1621,52 @@
1565
1621
  get scene() {
1566
1622
  return scene;
1567
1623
  },
1568
- next(Component, props) {
1569
- var _a;
1570
- // scene change
1571
- (_a = unit.scene) === null || _a === void 0 ? void 0 : _a.finalize();
1572
- unit.scene = xnew$1(Component, props);
1573
- }
1624
+ next(Component, props, callback) {
1625
+ callback = callback !== null && callback !== void 0 ? callback : defaultCallback;
1626
+ callback(scene, create);
1627
+ function defaultCallback(current, create) {
1628
+ current === null || current === void 0 ? void 0 : current.finalize();
1629
+ create();
1630
+ }
1631
+ function create() {
1632
+ scene = xnew$1((unit) => {
1633
+ xnew$1.extend(Scene);
1634
+ xnew$1.extend(Component, props);
1635
+ });
1636
+ return scene;
1637
+ }
1638
+ },
1574
1639
  };
1575
1640
  }
1576
1641
 
1642
+ class XImage {
1643
+ constructor(...args) {
1644
+ if (args[0] instanceof HTMLCanvasElement) {
1645
+ this.canvas = args[0];
1646
+ }
1647
+ else {
1648
+ const canvas = document.createElement('canvas');
1649
+ canvas.width = args[0];
1650
+ canvas.height = args[1];
1651
+ this.canvas = canvas;
1652
+ }
1653
+ }
1654
+ clip(x, y, width, height) {
1655
+ var _a;
1656
+ const canvas = document.createElement('canvas');
1657
+ canvas.width = width;
1658
+ canvas.height = height;
1659
+ (_a = canvas.getContext('2d')) === null || _a === void 0 ? void 0 : _a.drawImage(this.canvas, x, y, width, height, 0, 0, width, height);
1660
+ return new XImage(canvas);
1661
+ }
1662
+ download(filename) {
1663
+ const link = document.createElement('a');
1664
+ link.download = filename;
1665
+ link.href = this.canvas.toDataURL('image/png');
1666
+ link.click();
1667
+ }
1668
+ }
1669
+
1577
1670
  const context = new window.AudioContext();
1578
1671
  const master = context.createGain();
1579
1672
  //----------------------------------------------------------------------------------------------------
@@ -1807,6 +1900,7 @@
1807
1900
  Accordion,
1808
1901
  Popup,
1809
1902
  Flow,
1903
+ Scene,
1810
1904
  };
1811
1905
  const audio = {
1812
1906
  load(path) {
@@ -1835,7 +1929,12 @@
1835
1929
  master.gain.value = value;
1836
1930
  }
1837
1931
  };
1838
- const xnew = Object.assign(xnew$1, { basics, audio });
1932
+ const image = {
1933
+ from(canvas) {
1934
+ return new XImage(canvas);
1935
+ }
1936
+ };
1937
+ const xnew = Object.assign(xnew$1, { basics, audio, image });
1839
1938
 
1840
1939
  return xnew;
1841
1940