@mulsense/xnew 0.6.5 → 0.6.7

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
@@ -517,92 +517,15 @@ function pointer(element, event) {
517
517
  // utils
518
518
  //----------------------------------------------------------------------------------------------------
519
519
  const SYSTEM_EVENTS = ['start', 'update', 'render', 'stop', 'finalize'];
520
- class UnitPromise {
521
- constructor(promise, Component) {
522
- this.promise = promise;
523
- this.Component = Component;
524
- }
525
- then(callback) { return this.wrap('then', callback); }
526
- catch(callback) { return this.wrap('catch', callback); }
527
- finally(callback) { return this.wrap('finally', callback); }
528
- wrap(key, callback) {
529
- const snapshot = Unit.snapshot(Unit.currentUnit);
530
- this.promise = this.promise[key]((...args) => Unit.scope(snapshot, callback, ...args));
531
- return this;
532
- }
533
- }
534
- class UnitTimer {
535
- constructor() {
536
- this.unit = null;
537
- this.stack = [];
538
- }
539
- clear() {
540
- var _a;
541
- this.stack = [];
542
- (_a = this.unit) === null || _a === void 0 ? void 0 : _a.finalize();
543
- this.unit = null;
544
- }
545
- timeout(callback, duration = 0) {
546
- return UnitTimer.execute(this, { callback, duration }, 1);
547
- }
548
- interval(callback, duration = 0, iterations = 0) {
549
- return UnitTimer.execute(this, { callback, duration }, iterations);
550
- }
551
- transition(transition, duration = 0, easing) {
552
- return UnitTimer.execute(this, { transition, duration, easing }, 1);
553
- }
554
- static execute(timer, options, iterations) {
555
- const props = { options, iterations, snapshot: Unit.snapshot(Unit.currentUnit) };
556
- if (timer.unit === null || timer.unit._.state === 'finalized') {
557
- timer.unit = new Unit(Unit.currentUnit, null, UnitTimer.Component, props);
558
- }
559
- else if (timer.stack.length === 0) {
560
- timer.stack.push(props);
561
- timer.unit.on('finalize', () => UnitTimer.next(timer));
562
- }
563
- else {
564
- timer.stack.push(props);
565
- }
566
- return timer;
567
- }
568
- static next(timer) {
569
- if (timer.stack.length > 0) {
570
- timer.unit = new Unit(Unit.currentUnit, null, UnitTimer.Component, timer.stack.shift());
571
- timer.unit.on('finalize', () => UnitTimer.next(timer));
572
- }
573
- }
574
- static Component(unit, { options, iterations, snapshot }) {
575
- let counter = 0;
576
- let timer = new Timer({ callback, transition, duration: options.duration, easing: options.easing });
577
- function callback() {
578
- if (options.callback)
579
- Unit.scope(snapshot, options.callback);
580
- if (iterations <= 0 || counter < iterations - 1) {
581
- timer = new Timer({ callback, transition, duration: options.duration, easing: options.easing });
582
- }
583
- else {
584
- unit.finalize();
585
- }
586
- counter++;
587
- }
588
- function transition(value) {
589
- if (options.transition)
590
- Unit.scope(snapshot, options.transition, { value });
591
- }
592
- unit.on('finalize', () => timer.clear());
593
- }
594
- }
595
- function DefaultComponent(unit, { text }) {
596
- if (text !== undefined) {
597
- unit.element.textContent = text;
598
- }
599
- }
600
520
  //----------------------------------------------------------------------------------------------------
601
521
  // unit
602
522
  //----------------------------------------------------------------------------------------------------
603
523
  class Unit {
604
- constructor(parent, target, component, props) {
524
+ constructor(parent, target, Component, props) {
605
525
  var _a;
526
+ const backup = Unit.currentUnit;
527
+ Unit.currentUnit = this;
528
+ parent === null || parent === void 0 ? void 0 : parent._.children.push(this);
606
529
  let baseElement;
607
530
  if (target instanceof HTMLElement || target instanceof SVGElement) {
608
531
  baseElement = target;
@@ -614,20 +537,45 @@ class Unit {
614
537
  baseElement = (document === null || document === void 0 ? void 0 : document.body) ? document.body : null;
615
538
  }
616
539
  let baseComponent;
617
- if (typeof component === 'function') {
618
- baseComponent = component;
540
+ if (typeof Component === 'function') {
541
+ baseComponent = Component;
619
542
  }
620
- else if (typeof component === 'string' || typeof component === 'number') {
621
- baseComponent = DefaultComponent;
622
- props = { text: component.toString() };
543
+ else if (typeof Component === 'string' || typeof Component === 'number') {
544
+ baseComponent = (unit) => { unit.element.textContent = Component.toString(); };
623
545
  }
624
546
  else {
625
- baseComponent = DefaultComponent;
547
+ baseComponent = (unit) => { };
626
548
  }
627
- const baseContext = (_a = parent === null || parent === void 0 ? void 0 : parent._.currentContext) !== null && _a !== void 0 ? _a : { stack: null };
628
- this._ = { parent, target, baseElement, baseContext, baseComponent, props };
629
- parent === null || parent === void 0 ? void 0 : parent._.children.push(this);
630
- Unit.initialize(this, null);
549
+ const baseContext = (_a = parent === null || parent === void 0 ? void 0 : parent._.currentContext) !== null && _a !== void 0 ? _a : { previous: null };
550
+ this._ = {
551
+ parent,
552
+ state: 'invoked',
553
+ tostart: true,
554
+ protected: false,
555
+ currentElement: baseElement,
556
+ currentContext: baseContext,
557
+ currentComponent: null,
558
+ ancestors: parent ? [parent, ...parent._.ancestors] : [],
559
+ children: [],
560
+ nestElements: [],
561
+ promises: [],
562
+ results: {},
563
+ Components: [],
564
+ listeners: new MapMap(),
565
+ defines: {},
566
+ systems: { start: [], update: [], render: [], stop: [], finalize: [] },
567
+ eventor: new Eventor(),
568
+ };
569
+ // nest html element
570
+ if (typeof target === 'string') {
571
+ Unit.nest(this, target);
572
+ }
573
+ // setup Component
574
+ Unit.extend(this, baseComponent, props);
575
+ if (this._.state === 'invoked') {
576
+ this._.state = 'initialized';
577
+ }
578
+ Unit.currentUnit = backup;
631
579
  }
632
580
  get element() {
633
581
  return this._.currentElement;
@@ -642,77 +590,39 @@ class Unit {
642
590
  finalize() {
643
591
  Unit.stop(this);
644
592
  Unit.finalize(this);
645
- if (this._.parent) {
646
- this._.parent._.children = this._.parent._.children.filter((unit) => unit !== this);
647
- }
648
- }
649
- reboot() {
650
- let anchor = null;
651
- if (this._.nestElements[0] && this._.nestElements[0].owned === true) {
652
- anchor = this._.nestElements[0].element.nextElementSibling;
653
- }
654
- Unit.stop(this);
655
- Unit.finalize(this);
656
- Unit.initialize(this, anchor);
657
- }
658
- static initialize(unit, anchor) {
659
- const backup = Unit.currentUnit;
660
- Unit.currentUnit = unit;
661
- const done = {
662
- promise: null,
663
- resolve: null,
664
- reject: null
665
- };
666
- done.promise = new Promise((resolve, reject) => { done.resolve = resolve; done.reject = reject; });
667
- unit._ = Object.assign(unit._, {
668
- currentElement: unit._.baseElement,
669
- currentContext: unit._.baseContext,
670
- currentComponent: null,
671
- anchor,
672
- state: 'invoked',
673
- tostart: true,
674
- protected: false,
675
- ancestors: unit._.parent ? [unit._.parent, ...unit._.parent._.ancestors] : [],
676
- children: [],
677
- nestElements: [],
678
- promises: [],
679
- done,
680
- components: [],
681
- listeners: new MapMap(),
682
- defines: {},
683
- systems: { start: [], update: [], render: [], stop: [], finalize: [] },
684
- eventor: new Eventor(),
685
- });
686
- // nest html element
687
- if (typeof unit._.target === 'string') {
688
- Unit.nest(unit, unit._.target);
689
- }
690
- // setup component
691
- Unit.extend(unit, unit._.baseComponent, unit._.props);
692
- // whether the unit promise was resolved
693
- // Promise.all(unit._.promises.map(p => p.promise)).then(() => unit._.state = 'initialized');
694
- unit._.state = 'initialized';
695
- Unit.currentUnit = backup;
696
593
  }
697
594
  static finalize(unit) {
698
595
  if (unit._.state !== 'finalized' && unit._.state !== 'finalizing') {
699
596
  unit._.state = 'finalizing';
700
- [...unit._.children].reverse().forEach((child) => child.finalize());
701
- [...unit._.systems.finalize].reverse().forEach(({ execute }) => execute());
597
+ unit._.children.reverse().forEach((child) => child.finalize());
598
+ unit._.systems.finalize.reverse().forEach(({ execute }) => execute());
702
599
  unit.off();
703
- unit._.components.forEach((component) => Unit.component2units.delete(component, unit));
704
- for (const { element, owned } of unit._.nestElements.reverse()) {
705
- if (owned === true) {
706
- element.remove();
600
+ unit._.nestElements.reverse().filter(item => item.owned).forEach(item => item.element.remove());
601
+ unit._.Components.forEach((Component) => Unit.component2units.delete(Component, unit));
602
+ // remove contexts
603
+ const contexts = Unit.unit2Contexts.get(unit);
604
+ contexts === null || contexts === void 0 ? void 0 : contexts.forEach((context) => {
605
+ let temp = context.previous;
606
+ while (temp !== null) {
607
+ if (contexts.has(temp) === false && temp.key !== undefined) {
608
+ context.previous = temp;
609
+ context.key = undefined;
610
+ context.value = undefined;
611
+ break;
612
+ }
613
+ temp = temp.previous;
707
614
  }
708
- }
709
- unit._.currentElement = unit._.baseElement;
710
- // reset defines
615
+ });
616
+ Unit.unit2Contexts.delete(unit);
617
+ unit._.currentContext = { previous: null };
711
618
  Object.keys(unit._.defines).forEach((key) => {
712
619
  delete unit[key];
713
620
  });
714
621
  unit._.defines = {};
715
622
  unit._.state = 'finalized';
623
+ if (unit._.parent) {
624
+ unit._.parent._.children = unit._.parent._.children.filter((u) => u !== unit);
625
+ }
716
626
  }
717
627
  }
718
628
  static nest(unit, target, textContent) {
@@ -724,16 +634,8 @@ class Unit {
724
634
  else {
725
635
  const match = target.match(/<((\w+)[^>]*?)\/?>/);
726
636
  if (match !== null) {
727
- let element;
728
- if (unit._.anchor !== null) {
729
- unit._.anchor.insertAdjacentHTML('beforebegin', `<${match[1]}></${match[2]}>`);
730
- element = unit._.anchor.previousElementSibling;
731
- unit._.anchor = null;
732
- }
733
- else {
734
- unit._.currentElement.insertAdjacentHTML('beforeend', `<${match[1]}></${match[2]}>`);
735
- element = unit._.currentElement.children[unit._.currentElement.children.length - 1];
736
- }
637
+ unit._.currentElement.insertAdjacentHTML('beforeend', `<${match[1]}></${match[2]}>`);
638
+ const element = unit._.currentElement.children[unit._.currentElement.children.length - 1];
737
639
  unit._.currentElement = element;
738
640
  if (textContent !== undefined) {
739
641
  element.textContent = textContent.toString();
@@ -748,25 +650,20 @@ class Unit {
748
650
  }
749
651
  static extend(unit, Component, props) {
750
652
  var _a;
751
- if (unit._.components.includes(Component) === true) {
752
- throw new Error(`The component is already extended.`);
653
+ if (unit._.Components.includes(Component) === true) {
654
+ throw new Error(`The Component is already extended.`);
753
655
  }
754
656
  else {
755
657
  const backupComponent = unit._.currentComponent;
756
658
  unit._.currentComponent = Component;
757
- const defines = (_a = Component(unit, props !== null && props !== void 0 ? props : {})) !== null && _a !== void 0 ? _a : {};
758
- if (unit._.parent && Component !== DefaultComponent) {
759
- if (Component === unit._.baseComponent) {
760
- Unit.context(unit._.parent, Component, unit);
761
- }
762
- else {
763
- Unit.context(unit, Component, unit);
764
- Unit.context(unit._.parent, Component, unit);
765
- }
659
+ if (unit._.parent !== null) {
660
+ Unit.addContext(unit._.parent, unit, Component, unit);
766
661
  }
662
+ Unit.addContext(unit, unit, Component, unit);
663
+ const defines = (_a = Component(unit, props !== null && props !== void 0 ? props : {})) !== null && _a !== void 0 ? _a : {};
767
664
  unit._.currentComponent = backupComponent;
768
665
  Unit.component2units.add(Component, unit);
769
- unit._.components.push(Component);
666
+ unit._.Components.push(Component);
770
667
  Object.keys(defines).forEach((key) => {
771
668
  if (unit[key] !== undefined && unit._.defines[key] === undefined) {
772
669
  throw new Error(`The property "${key}" already exists.`);
@@ -784,7 +681,7 @@ class Unit {
784
681
  wrapper.value = (...args) => Unit.scope(snapshot, descriptor.value, ...args);
785
682
  }
786
683
  else {
787
- throw new Error(`Only function properties can be defined as component defines. [${key}]`);
684
+ throw new Error(`Only function properties can be defined as Component defines. [${key}]`);
788
685
  }
789
686
  Object.defineProperty(unit._.defines, key, wrapper);
790
687
  Object.defineProperty(unit, key, wrapper);
@@ -844,7 +741,7 @@ class Unit {
844
741
  Unit.currentUnit = snapshot.unit;
845
742
  snapshot.unit._.currentContext = snapshot.context;
846
743
  snapshot.unit._.currentElement = snapshot.element;
847
- snapshot.unit._.currentComponent = snapshot.component;
744
+ snapshot.unit._.currentComponent = snapshot.Component;
848
745
  return func(...args);
849
746
  }
850
747
  catch (error) {
@@ -854,21 +751,22 @@ class Unit {
854
751
  Unit.currentUnit = currentUnit;
855
752
  snapshot.unit._.currentContext = backup.context;
856
753
  snapshot.unit._.currentElement = backup.element;
857
- snapshot.unit._.currentComponent = backup.component;
754
+ snapshot.unit._.currentComponent = backup.Component;
858
755
  }
859
756
  }
860
757
  static snapshot(unit) {
861
- return { unit, context: unit._.currentContext, element: unit._.currentElement, component: unit._.currentComponent };
758
+ return { unit, context: unit._.currentContext, element: unit._.currentElement, Component: unit._.currentComponent };
862
759
  }
863
- static context(unit, key, value) {
864
- if (value !== undefined) {
865
- unit._.currentContext = { stack: unit._.currentContext, key, value };
866
- }
867
- else {
868
- for (let context = unit._.currentContext; context.stack !== null; context = context.stack) {
869
- if (context.key === key)
870
- return context.value;
871
- }
760
+ static addContext(unit, orner, key, value) {
761
+ unit._.currentContext = { previous: unit._.currentContext, key, value };
762
+ Unit.unit2Contexts.add(orner, unit._.currentContext);
763
+ }
764
+ static getContext(unit, key) {
765
+ for (let context = unit._.currentContext; context.previous !== null; context = context.previous) {
766
+ if (context.value === Unit.currentUnit && key === Unit.currentUnit._.currentComponent)
767
+ continue;
768
+ if (context.key === key)
769
+ return context.value;
872
770
  }
873
771
  }
874
772
  static find(Component) {
@@ -892,7 +790,7 @@ class Unit {
892
790
  unit._.systems[type].push({ listener, execute });
893
791
  }
894
792
  if (unit._.listeners.has(type, listener) === false) {
895
- unit._.listeners.set(type, listener, { element: unit.element, component: unit._.currentComponent, execute });
793
+ unit._.listeners.set(type, listener, { element: unit.element, Component: unit._.currentComponent, execute });
896
794
  Unit.type2units.add(type, unit);
897
795
  if (/^[A-Za-z]/.test(type)) {
898
796
  unit._.eventor.add(unit.element, type, execute, options);
@@ -934,11 +832,90 @@ class Unit {
934
832
  }
935
833
  }
936
834
  Unit.currentComponent = () => { };
835
+ Unit.unit2Contexts = new MapSet();
937
836
  Unit.component2units = new MapSet();
938
837
  //----------------------------------------------------------------------------------------------------
939
838
  // event
940
839
  //----------------------------------------------------------------------------------------------------
941
840
  Unit.type2units = new MapSet();
841
+ //----------------------------------------------------------------------------------------------------
842
+ // extensions
843
+ //----------------------------------------------------------------------------------------------------
844
+ class UnitPromise {
845
+ constructor(promise, Component) {
846
+ this.promise = promise;
847
+ this.Component = Component;
848
+ }
849
+ then(callback) { return this.wrap('then', callback); }
850
+ catch(callback) { return this.wrap('catch', callback); }
851
+ finally(callback) { return this.wrap('finally', callback); }
852
+ wrap(key, callback) {
853
+ const snapshot = Unit.snapshot(Unit.currentUnit);
854
+ this.promise = this.promise[key]((...args) => Unit.scope(snapshot, callback, ...args));
855
+ return this;
856
+ }
857
+ }
858
+ class UnitTimer {
859
+ constructor() {
860
+ this.unit = null;
861
+ this.queue = [];
862
+ }
863
+ clear() {
864
+ var _a;
865
+ this.queue = [];
866
+ (_a = this.unit) === null || _a === void 0 ? void 0 : _a.finalize();
867
+ this.unit = null;
868
+ }
869
+ timeout(callback, duration = 0) {
870
+ return UnitTimer.execute(this, { callback, duration }, 1);
871
+ }
872
+ interval(callback, duration = 0, iterations = 0) {
873
+ return UnitTimer.execute(this, { callback, duration }, iterations);
874
+ }
875
+ transition(transition, duration = 0, easing) {
876
+ return UnitTimer.execute(this, { transition, duration, easing }, 1);
877
+ }
878
+ static execute(timer, options, iterations) {
879
+ const props = { options, iterations, snapshot: Unit.snapshot(Unit.currentUnit) };
880
+ if (timer.unit === null || timer.unit._.state === 'finalized') {
881
+ timer.unit = new Unit(Unit.currentUnit, null, UnitTimer.Component, props);
882
+ }
883
+ else if (timer.queue.length === 0) {
884
+ timer.queue.push(props);
885
+ timer.unit.on('finalize', () => UnitTimer.next(timer));
886
+ }
887
+ else {
888
+ timer.queue.push(props);
889
+ }
890
+ return timer;
891
+ }
892
+ static next(timer) {
893
+ if (timer.queue.length > 0) {
894
+ timer.unit = new Unit(Unit.currentUnit, null, UnitTimer.Component, timer.queue.shift());
895
+ timer.unit.on('finalize', () => UnitTimer.next(timer));
896
+ }
897
+ }
898
+ static Component(unit, { options, iterations, snapshot }) {
899
+ 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);
904
+ if (iterations <= 0 || counter < iterations - 1) {
905
+ timer = new Timer({ callback, transition, duration: options.duration, easing: options.easing });
906
+ }
907
+ else {
908
+ unit.finalize();
909
+ }
910
+ counter++;
911
+ }
912
+ function transition(value) {
913
+ if (options.transition)
914
+ Unit.scope(snapshot, options.transition, { value });
915
+ }
916
+ unit.on('finalize', () => timer.clear());
917
+ }
918
+ }
942
919
 
943
920
  const xnew$1 = Object.assign(function (...args) {
944
921
  if (Unit.rootUnit === undefined)
@@ -955,7 +932,8 @@ const xnew$1 = Object.assign(function (...args) {
955
932
  }
956
933
  const Component = args.shift();
957
934
  const props = args.shift();
958
- return new Unit(Unit.currentUnit, target, Component, props);
935
+ const unit = new Unit(Unit.currentUnit, target, Component, props);
936
+ return unit;
959
937
  }, {
960
938
  /**
961
939
  * Creates a nested HTML/SVG element within the current component
@@ -992,7 +970,8 @@ const xnew$1 = Object.assign(function (...args) {
992
970
  if (Unit.currentUnit._.state !== 'invoked') {
993
971
  throw new Error('xnew.extend can not be called after initialized.');
994
972
  }
995
- return Unit.extend(Unit.currentUnit, Component, props);
973
+ const defines = Unit.extend(Unit.currentUnit, Component, props);
974
+ return defines;
996
975
  }
997
976
  catch (error) {
998
977
  console.error('xnew.extend(component: Function, props?: Object): ', error);
@@ -1001,7 +980,7 @@ const xnew$1 = Object.assign(function (...args) {
1001
980
  },
1002
981
  /**
1003
982
  * Gets a context value that can be accessed in follow context
1004
- * @param component - component function
983
+ * @param key - component function
1005
984
  * @returns The context value
1006
985
  * @example
1007
986
  * // Create unit
@@ -1011,12 +990,12 @@ const xnew$1 = Object.assign(function (...args) {
1011
990
  * // Get context in child
1012
991
  * const a = xnew.context(A)
1013
992
  */
1014
- context(component) {
993
+ context(key) {
1015
994
  try {
1016
- return Unit.context(Unit.currentUnit, component);
995
+ return Unit.getContext(Unit.currentUnit, key);
1017
996
  }
1018
997
  catch (error) {
1019
- console.error('xnew.context(component: Function): ', error);
998
+ console.error('xnew.context(key: any): ', error);
1020
999
  throw error;
1021
1000
  }
1022
1001
  },
@@ -1029,16 +1008,17 @@ const xnew$1 = Object.assign(function (...args) {
1029
1008
  */
1030
1009
  promise(promise) {
1031
1010
  try {
1032
- const component = Unit.currentUnit._.currentComponent;
1011
+ const Component = Unit.currentUnit._.currentComponent;
1033
1012
  let unitPromise;
1034
1013
  if (promise instanceof Unit) {
1035
- unitPromise = new UnitPromise(promise._.done.promise, component);
1014
+ unitPromise = new UnitPromise(Promise.all(promise._.promises.map(p => p.promise)), Component)
1015
+ .then(() => promise._.results);
1036
1016
  }
1037
1017
  else if (promise instanceof Promise) {
1038
- unitPromise = new UnitPromise(promise, component);
1018
+ unitPromise = new UnitPromise(promise, Component);
1039
1019
  }
1040
1020
  else {
1041
- unitPromise = new UnitPromise(new Promise(xnew$1.scope(promise)), component);
1021
+ unitPromise = new UnitPromise(new Promise(xnew$1.scope(promise)), Component);
1042
1022
  }
1043
1023
  Unit.currentUnit._.promises.push(unitPromise);
1044
1024
  return unitPromise;
@@ -1057,12 +1037,9 @@ const xnew$1 = Object.assign(function (...args) {
1057
1037
  */
1058
1038
  then(callback) {
1059
1039
  try {
1060
- const Component = Unit.currentUnit._.currentComponent;
1061
- const promises = Unit.currentUnit._.promises;
1062
- return new UnitPromise(Promise.all(promises.map(p => p.promise)), null)
1063
- .then((results) => {
1064
- callback(results.filter((_, index) => promises[index].Component !== null && promises[index].Component === Component));
1065
- });
1040
+ const currentUnit = Unit.currentUnit;
1041
+ return new UnitPromise(Promise.all(Unit.currentUnit._.promises.map(p => p.promise)), null)
1042
+ .then(() => callback(currentUnit._.results));
1066
1043
  }
1067
1044
  catch (error) {
1068
1045
  console.error('xnew.then(callback: Function): ', error);
@@ -1078,8 +1055,7 @@ const xnew$1 = Object.assign(function (...args) {
1078
1055
  */
1079
1056
  catch(callback) {
1080
1057
  try {
1081
- const promises = Unit.currentUnit._.promises;
1082
- return new UnitPromise(Promise.all(promises.map(p => p.promise)), null)
1058
+ return new UnitPromise(Promise.all(Unit.currentUnit._.promises.map(p => p.promise)), null)
1083
1059
  .catch(callback);
1084
1060
  }
1085
1061
  catch (error) {
@@ -1088,36 +1064,18 @@ const xnew$1 = Object.assign(function (...args) {
1088
1064
  }
1089
1065
  },
1090
1066
  /**
1091
- * Resolves the current unit's promise with the given value
1092
- * @param value - Value to resolve the promise with
1067
+ * Commits a value to the current unit's promise results
1068
+ * @param object - object to commit to the promise
1093
1069
  * @returns void
1094
1070
  * @example
1095
- * xnew.resolve('data');
1071
+ * xnew.commit({ data: 123});
1096
1072
  */
1097
- resolve(value) {
1073
+ commit(object) {
1098
1074
  try {
1099
- const done = Unit.currentUnit._.done;
1100
- done.resolve(value);
1075
+ Object.assign(Unit.currentUnit._.results, object);
1101
1076
  }
1102
1077
  catch (error) {
1103
- console.error('xnew.resolve(value?: any): ', error);
1104
- throw error;
1105
- }
1106
- },
1107
- /**
1108
- * Rejects the current unit's promise with the given reason
1109
- * @param reason - Reason to reject the promise
1110
- * @returns void
1111
- * @example
1112
- * xnew.reject(new Error('Something went wrong'));
1113
- */
1114
- reject(reason) {
1115
- try {
1116
- const done = Unit.currentUnit._.done;
1117
- done.reject(reason);
1118
- }
1119
- catch (error) {
1120
- console.error('xnew.reject(reason?: any): ', error);
1078
+ console.error('xnew.commit(object?: Record<string, any>): ', error);
1121
1079
  throw error;
1122
1080
  }
1123
1081
  },
@@ -1130,8 +1088,7 @@ const xnew$1 = Object.assign(function (...args) {
1130
1088
  */
1131
1089
  finally(callback) {
1132
1090
  try {
1133
- const promises = Unit.currentUnit._.promises;
1134
- return new UnitPromise(Promise.all(promises.map(p => p.promise)), null)
1091
+ return new UnitPromise(Promise.all(Unit.currentUnit._.promises.map(p => p.promise)), null)
1135
1092
  .finally(callback);
1136
1093
  }
1137
1094
  catch (error) {
@@ -1154,19 +1111,19 @@ const xnew$1 = Object.assign(function (...args) {
1154
1111
  },
1155
1112
  /**
1156
1113
  * Finds all instances of a component in the component tree
1157
- * @param component - Component function to search for
1114
+ * @param Component - Component function to search for
1158
1115
  * @returns Array of Unit instances matching the component
1159
1116
  * @throws Error if component parameter is invalid
1160
1117
  * @example
1161
1118
  * const buttons = xnew.find(ButtonComponent)
1162
1119
  * buttons.forEach(btn => btn.finalize())
1163
1120
  */
1164
- find(component) {
1121
+ find(Component) {
1165
1122
  try {
1166
- return Unit.find(component);
1123
+ return Unit.find(Component);
1167
1124
  }
1168
1125
  catch (error) {
1169
- console.error('xnew.find(component: Function): ', error);
1126
+ console.error('xnew.find(Component: Function): ', error);
1170
1127
  throw error;
1171
1128
  }
1172
1129
  },
@@ -1422,13 +1379,13 @@ function DPad(unit, { diagonal = true, stroke = 'currentColor', strokeOpacity =
1422
1379
 
1423
1380
  const currentColorA = 'color-mix(in srgb, currentColor 70%, transparent)';
1424
1381
  const currentColorB = 'color-mix(in srgb, currentColor 10%, transparent)';
1425
- function Panel(unit, { name, open = false, params }) {
1382
+ function Panel(unit, { params }) {
1426
1383
  const object = params !== null && params !== void 0 ? params : {};
1427
- xnew$1.extend(Group, { name, open });
1428
1384
  return {
1429
1385
  group({ name, open, params }, inner) {
1430
1386
  const group = xnew$1((unit) => {
1431
- xnew$1.extend(Panel, { name, open, params: params !== null && params !== void 0 ? params : object });
1387
+ xnew$1.extend(Group, { name, open });
1388
+ xnew$1.extend(Panel, { params: params !== null && params !== void 0 ? params : object });
1432
1389
  inner(unit);
1433
1390
  });
1434
1391
  return group;
@@ -1437,23 +1394,23 @@ function Panel(unit, { name, open = false, params }) {
1437
1394
  const button = xnew$1(Button, { key });
1438
1395
  return button;
1439
1396
  },
1440
- select(key, { options = [] } = {}) {
1397
+ select(key, { value, items = [] } = {}) {
1441
1398
  var _a, _b;
1442
- object[key] = (_b = (_a = object[key]) !== null && _a !== void 0 ? _a : options[0]) !== null && _b !== void 0 ? _b : '';
1443
- const select = xnew$1(Select, { key, value: object[key], options });
1399
+ object[key] = (_b = (_a = value !== null && value !== void 0 ? value : object[key]) !== null && _a !== void 0 ? _a : items[0]) !== null && _b !== void 0 ? _b : '';
1400
+ const select = xnew$1(Select, { key, value: object[key], items });
1444
1401
  select.on('input', ({ value }) => object[key] = value);
1445
1402
  return select;
1446
1403
  },
1447
- range(key, options = {}) {
1448
- var _a, _b;
1449
- object[key] = (_b = (_a = object[key]) !== null && _a !== void 0 ? _a : options.min) !== null && _b !== void 0 ? _b : 0;
1450
- const number = xnew$1(Range, Object.assign({ key, value: object[key] }, options));
1404
+ range(key, { value, min = 0, max = 100, step = 1 } = {}) {
1405
+ var _a;
1406
+ object[key] = (_a = value !== null && value !== void 0 ? value : object[key]) !== null && _a !== void 0 ? _a : min;
1407
+ const number = xnew$1(Range, { key, value: object[key], min, max, step });
1451
1408
  number.on('input', ({ value }) => object[key] = value);
1452
1409
  return number;
1453
1410
  },
1454
- checkbox(key) {
1411
+ checkbox(key, { value } = {}) {
1455
1412
  var _a;
1456
- object[key] = (_a = object[key]) !== null && _a !== void 0 ? _a : false;
1413
+ object[key] = (_a = value !== null && value !== void 0 ? value : object[key]) !== null && _a !== void 0 ? _a : false;
1457
1414
  const checkbox = xnew$1(Checkbox, { key, value: object[key] });
1458
1415
  checkbox.on('input', ({ value }) => object[key] = value);
1459
1416
  return checkbox;
@@ -1470,7 +1427,7 @@ function Group(group, { name, open = false }) {
1470
1427
  unit.on('click', () => group.toggle());
1471
1428
  xnew$1('<svg viewBox="0 0 12 12" style="width: 1em; height: 1em; margin-right: 0.25em;" fill="none" stroke="currentColor">', (unit) => {
1472
1429
  xnew$1('<path d="M6 2 10 6 6 10" />');
1473
- group.on('-transition', ({ state }) => unit.element.style.transform = `rotate(${state * 90}deg)`);
1430
+ group.on('-transition', ({ value }) => unit.element.style.transform = `rotate(${value * 90}deg)`);
1474
1431
  });
1475
1432
  xnew$1('<div>', name);
1476
1433
  });
@@ -1537,14 +1494,14 @@ function Checkbox(unit, { key = '', value } = {}) {
1537
1494
  update(value);
1538
1495
  });
1539
1496
  }
1540
- function Select(_, { key = '', value, options = [] } = {}) {
1497
+ function Select(_, { key = '', value, items = [] } = {}) {
1541
1498
  var _a;
1542
- const initial = (_a = value !== null && value !== void 0 ? value : options[0]) !== null && _a !== void 0 ? _a : '';
1499
+ const initial = (_a = value !== null && value !== void 0 ? value : items[0]) !== null && _a !== void 0 ? _a : '';
1543
1500
  xnew$1.nest(`<div style="position: relative; height: 2em; margin: 0.125em 0; padding: 0 0.5em; display: flex; align-items: center;">`);
1544
1501
  xnew$1('<div style="flex: 1;">', key);
1545
1502
  const native = xnew$1(`<select name="${key}" style="display: none;">`, () => {
1546
- for (const option of options) {
1547
- xnew$1(`<option value="${option}" ${option === initial ? 'selected' : ''}>`, option);
1503
+ for (const item of items) {
1504
+ xnew$1(`<option value="${item}" ${item === initial ? 'selected' : ''}>`, item);
1548
1505
  }
1549
1506
  });
1550
1507
  const button = xnew$1(`<div style="height: 2em; padding: 0 1.5em 0 0.5em; display: flex; align-items: center; border: 1px solid ${currentColorA}; border-radius: 0.25em; cursor: pointer; user-select: none; min-width: 3em; white-space: nowrap;">`, initial);
@@ -1564,13 +1521,13 @@ function Select(_, { key = '', value, options = [] } = {}) {
1564
1521
  });
1565
1522
  xnew$1.extend(Accordion);
1566
1523
  xnew$1.nest(`<div style="position: relative; border: 1px solid ${currentColorA}; border-radius: 0.25em; overflow: hidden;">`);
1567
- for (const option of options) {
1568
- const item = xnew$1(`<div style="height: 2em; padding: 0 0.5em; display: flex; align-items: center; cursor: pointer; user-select: none;">`, option);
1569
- item.on('pointerover', () => item.element.style.background = currentColorB);
1570
- item.on('pointerout', () => item.element.style.background = '');
1571
- item.on('click', () => {
1572
- button.element.textContent = option;
1573
- native.element.value = option;
1524
+ for (const item of items) {
1525
+ const div = xnew$1(`<div style="height: 2em; padding: 0 0.5em; display: flex; align-items: center; cursor: pointer; user-select: none;">`, item);
1526
+ div.on('pointerover', () => div.element.style.background = currentColorB);
1527
+ div.on('pointerout', () => div.element.style.background = '');
1528
+ div.on('click', () => {
1529
+ button.element.textContent = item;
1530
+ native.element.value = item;
1574
1531
  native.element.dispatchEvent(new Event('input', { bubbles: false }));
1575
1532
  list.finalize();
1576
1533
  });
@@ -1593,6 +1550,24 @@ function Select(_, { key = '', value, options = [] } = {}) {
1593
1550
  }
1594
1551
  }
1595
1552
 
1553
+ function Flow(unit) {
1554
+ let scene = null;
1555
+ return {
1556
+ set scene(value) {
1557
+ scene = value;
1558
+ },
1559
+ get scene() {
1560
+ return scene;
1561
+ },
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
+ }
1568
+ };
1569
+ }
1570
+
1596
1571
  const context = new window.AudioContext();
1597
1572
  const master = context.createGain();
1598
1573
  //----------------------------------------------------------------------------------------------------
@@ -1825,6 +1800,7 @@ const basics = {
1825
1800
  Panel,
1826
1801
  Accordion,
1827
1802
  Popup,
1803
+ Flow,
1828
1804
  };
1829
1805
  const audio = {
1830
1806
  load(path) {