@mulsense/xnew 0.1.5 → 0.1.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.js CHANGED
@@ -223,7 +223,7 @@
223
223
  }
224
224
 
225
225
  //----------------------------------------------------------------------------------------------------
226
- // Utils
226
+ // defines
227
227
  //----------------------------------------------------------------------------------------------------
228
228
  const SYSTEM_EVENTS = ['start', 'update', 'stop', 'finalize'];
229
229
  class UnitPromise {
@@ -798,61 +798,58 @@
798
798
  Unit.current._.captures.push({ checker, execute: Unit.wrap(Unit.current, (unit) => execute(unit)) });
799
799
  };
800
800
 
801
- function UserEvent(self) {
802
- const unit = xnew$1();
803
- unit.on('pointerdown', (event) => self.emit('-pointerdown', { event, position: getPosition(self.element, event) }));
804
- unit.on('pointermove', (event) => self.emit('-pointermove', { event, position: getPosition(self.element, event) }));
805
- unit.on('pointerup', (event) => self.emit('-pointerup', { event, position: getPosition(self.element, event) }));
806
- unit.on('wheel', (event) => self.emit('-wheel', { event, delta: { x: event.wheelDeltaX, y: event.wheelDeltaY } }));
801
+ function PointerEvent(unit) {
802
+ const internal = xnew$1();
803
+ internal.on('pointerdown', (event) => unit.emit('-pointerdown', { event, position: getPosition(unit.element, event) }));
804
+ internal.on('pointermove', (event) => unit.emit('-pointermove', { event, position: getPosition(unit.element, event) }));
805
+ internal.on('pointerup', (event) => unit.emit('-pointerup', { event, position: getPosition(unit.element, event) }));
806
+ internal.on('wheel', (event) => unit.emit('-wheel', { event, delta: { x: event.wheelDeltaX, y: event.wheelDeltaY } }));
807
+ internal.on('mouseover', (event) => unit.emit('-mouseover', { event, position: getPosition(unit.element, event) }));
808
+ internal.on('mouseout', (event) => unit.emit('-mouseout', { event, position: getPosition(unit.element, event) }));
807
809
  const drag = xnew$1(DragEvent);
808
- drag.on('-dragstart', (...args) => self.emit('-dragstart', ...args));
809
- drag.on('-dragmove', (...args) => self.emit('-dragmove', ...args));
810
- drag.on('-dragend', (...args) => self.emit('-dragend', ...args));
811
- drag.on('-dragcancel', (...args) => self.emit('-dragcancel', ...args));
810
+ drag.on('-dragstart', (...args) => unit.emit('-dragstart', ...args));
811
+ drag.on('-dragmove', (...args) => unit.emit('-dragmove', ...args));
812
+ drag.on('-dragend', (...args) => unit.emit('-dragend', ...args));
813
+ drag.on('-dragcancel', (...args) => unit.emit('-dragcancel', ...args));
812
814
  const gesture = xnew$1(GestureEvent);
813
- gesture.on('-gesturestart', (...args) => self.emit('-gesturestart', ...args));
814
- gesture.on('-gesturemove', (...args) => self.emit('-gesturemove', ...args));
815
- gesture.on('-gestureend', (...args) => self.emit('-gestureend', ...args));
816
- gesture.on('-gesturecancel', (...args) => self.emit('-gesturecancel', ...args));
817
- const keyborad = xnew$1(Keyboard);
818
- keyborad.on('-keydown', (...args) => self.emit('-keydown', ...args));
819
- keyborad.on('-keyup', (...args) => self.emit('-keyup', ...args));
820
- keyborad.on('-arrowkeydown', (...args) => self.emit('-arrowkeydown', ...args));
821
- keyborad.on('-arrowkeyup', (...args) => self.emit('-arrowkeyup', ...args));
815
+ gesture.on('-gesturestart', (...args) => unit.emit('-gesturestart', ...args));
816
+ gesture.on('-gesturemove', (...args) => unit.emit('-gesturemove', ...args));
817
+ gesture.on('-gestureend', (...args) => unit.emit('-gestureend', ...args));
818
+ gesture.on('-gesturecancel', (...args) => unit.emit('-gesturecancel', ...args));
822
819
  }
823
- function DragEvent(self) {
820
+ function DragEvent(unit) {
824
821
  xnew$1().on('pointerdown', (event) => {
825
822
  const id = event.pointerId;
826
- const position = getPosition(self.element, event);
823
+ const position = getPosition(unit.element, event);
827
824
  let previous = position;
828
825
  xnew$1(() => {
829
826
  xnew$1.listener(window).on('pointermove', (event) => {
830
827
  if (event.pointerId === id) {
831
- const position = getPosition(self.element, event);
828
+ const position = getPosition(unit.element, event);
832
829
  const delta = { x: position.x - previous.x, y: position.y - previous.y };
833
- self.emit('-dragmove', { event, position, delta });
830
+ unit.emit('-dragmove', { event, position, delta });
834
831
  previous = position;
835
832
  }
836
833
  });
837
834
  xnew$1.listener(window).on('pointerup', (event) => {
838
835
  if (event.pointerId === id) {
839
- const position = getPosition(self.element, event);
840
- self.emit('-dragend', { event, position, });
836
+ const position = getPosition(unit.element, event);
837
+ unit.emit('-dragend', { event, position, });
841
838
  xnew$1.listener(window).off();
842
839
  }
843
840
  });
844
841
  xnew$1.listener(window).on('pointercancel', (event) => {
845
842
  if (event.pointerId === id) {
846
- const position = getPosition(self.element, event);
847
- self.emit('-dragcancel', { event, position, });
843
+ const position = getPosition(unit.element, event);
844
+ unit.emit('-dragcancel', { event, position, });
848
845
  xnew$1.listener(window).off();
849
846
  }
850
847
  });
851
848
  });
852
- self.emit('-dragstart', { event, position });
849
+ unit.emit('-dragstart', { event, position });
853
850
  });
854
851
  }
855
- function GestureEvent(self) {
852
+ function GestureEvent(unit) {
856
853
  const drag = xnew$1(DragEvent);
857
854
  let isActive = false;
858
855
  const map = new Map();
@@ -860,7 +857,7 @@
860
857
  map.set(event.pointerId, Object.assign({}, position));
861
858
  isActive = map.size === 2 ? true : false;
862
859
  if (isActive === true) {
863
- self.emit('-gesturestart', {});
860
+ unit.emit('-gesturestart', {});
864
861
  }
865
862
  });
866
863
  drag.on('-dragmove', ({ event, position, delta }) => {
@@ -886,20 +883,20 @@
886
883
  // rotate = sign > 0.0 ? +angle : -angle;
887
884
  // }
888
885
  // }
889
- self.emit('-gesturemove', { event, position, delta, scale });
886
+ unit.emit('-gesturemove', { event, position, delta, scale });
890
887
  }
891
888
  map.set(event.pointerId, position);
892
889
  });
893
890
  drag.on('-dragend', ({ event }) => {
894
891
  if (isActive === true) {
895
- self.emit('-gestureend', {});
892
+ unit.emit('-gestureend', {});
896
893
  }
897
894
  isActive = false;
898
895
  map.delete(event.pointerId);
899
896
  });
900
897
  drag.on('-dragcancel', ({ event }) => {
901
898
  if (isActive === true) {
902
- self.emit('-gesturecancel', { event });
899
+ unit.emit('-gesturecancel', { event });
903
900
  }
904
901
  isActive = false;
905
902
  map.delete(event.pointerId);
@@ -912,21 +909,26 @@
912
909
  return others;
913
910
  }
914
911
  }
915
- function Keyboard(self) {
912
+ function getPosition(element, event) {
913
+ const rect = element.getBoundingClientRect();
914
+ return { x: event.clientX - rect.left, y: event.clientY - rect.top };
915
+ }
916
+
917
+ function KeyboardEvent(unit) {
916
918
  const state = {};
917
919
  xnew$1.listener(window).on('keydown', (event) => {
918
920
  state[event.code] = 1;
919
- self.emit('-keydown', { event, code: event.code });
921
+ unit.emit('-keydown', { event, type: '-keydown', code: event.code });
920
922
  });
921
923
  xnew$1.listener(window).on('keyup', (event) => {
922
924
  state[event.code] = 0;
923
- self.emit('-keyup', { event, code: event.code });
925
+ unit.emit('-keyup', { event, type: '-keyup', code: event.code });
924
926
  });
925
927
  xnew$1.listener(window).on('keydown', (event) => {
926
- self.emit('-arrowkeydown', { event, code: event.code, vector: getVector() });
928
+ unit.emit('-arrowkeydown', { event, type: '-arrowkeydown', code: event.code, vector: getVector() });
927
929
  });
928
930
  xnew$1.listener(window).on('keyup', (event) => {
929
- self.emit('-arrowkeyup', { event, code: event.code, vector: getVector() });
931
+ unit.emit('-arrowkeyup', { event, type: '-arrowkeyup', code: event.code, vector: getVector() });
930
932
  });
931
933
  function getVector() {
932
934
  return {
@@ -935,16 +937,12 @@
935
937
  };
936
938
  }
937
939
  }
938
- function getPosition(element, event) {
939
- const rect = element.getBoundingClientRect();
940
- return { x: event.clientX - rect.left, y: event.clientY - rect.top };
941
- }
942
940
 
943
941
  function Screen(screen, { width = 640, height = 480, fit = 'contain' } = {}) {
944
942
  const size = { width, height };
945
943
  const wrapper = xnew$1.nest('<div style="position: relative; width: 100%; height: 100%; overflow: hidden;">');
946
944
  const absolute = xnew$1.nest('<div style="position: absolute; margin: auto;">');
947
- const canvas = xnew$1.nest(`<canvas width="${width}" height="${height}" style="width: 100%; height: 100%; vertical-align: bottom; user-select: none; user-drag: none;">`);
945
+ const canvas = xnew$1(`<canvas width="${width}" height="${height}" style="width: 100%; height: 100%; vertical-align: bottom; user-select: none; user-drag: none;">`);
948
946
  xnew$1(wrapper, ResizeEvent).on('-resize', resize);
949
947
  resize();
950
948
  function resize() {
@@ -975,24 +973,23 @@
975
973
  }
976
974
  return {
977
975
  get canvas() {
978
- return canvas;
976
+ return canvas.element;
979
977
  },
980
978
  resize(width, height) {
981
979
  size.width = width;
982
980
  size.height = height;
983
- canvas.setAttribute('width', width + 'px');
984
- canvas.setAttribute('height', height + 'px');
981
+ canvas.element.setAttribute('width', width + 'px');
982
+ canvas.element.setAttribute('height', height + 'px');
985
983
  resize();
986
984
  },
987
- get scale() {
988
- return { x: size.width / canvas.clientWidth, y: size.height / canvas.clientHeight };
989
- }
990
985
  };
991
986
  }
992
987
 
993
988
  function InputFrame(frame, {} = {}) {
994
989
  xnew$1.nest('<div>');
995
- xnew$1.capture((unit) => unit.element.tagName.toLowerCase() === 'input', (unit) => {
990
+ xnew$1.capture((unit) => {
991
+ return unit.element.tagName.toLowerCase() === 'input';
992
+ }, (unit) => {
996
993
  const element = unit.element;
997
994
  xnew$1.listener(element).on('input', (event) => {
998
995
  frame.emit('-input', { event });
@@ -1006,177 +1003,171 @@
1006
1003
  });
1007
1004
  }
1008
1005
 
1009
- function ModalFrame(frame, {} = {}) {
1010
- xnew$1.context('xnew.modalframe', frame);
1011
- xnew$1.nest('<div style="position: fixed; inset: 0; z-index: 1000;">');
1012
- xnew$1.capture((unit) => unit.components.includes(ModalContent), (unit) => {
1006
+ function ModalFrame(frame, { duration = 200, easing = 'ease' } = {}) {
1007
+ const internal = xnew$1((internal) => {
1008
+ return {};
1013
1009
  });
1014
- xnew$1().on('click', (event) => frame === null || frame === void 0 ? void 0 : frame.close());
1010
+ xnew$1.context('xnew.modalframe', internal);
1011
+ xnew$1.nest('<div style="position: fixed; inset: 0; z-index: 1000;">');
1012
+ xnew$1().on('click', (event) => frame.close());
1013
+ xnew$1.transition((x) => internal.emit('-transition', { rate: x }), duration, easing);
1015
1014
  return {
1016
1015
  close() {
1017
- frame.emit('-close');
1016
+ xnew$1.transition((x) => internal.emit('-transition', { rate: 1.0 - x }), duration, easing)
1017
+ .next(() => frame.finalize());
1018
1018
  }
1019
1019
  };
1020
1020
  }
1021
- function ModalContent(content, { duration = 200, easing = 'ease', background = 'rgba(0, 0, 0, 0.1)' } = {}) {
1022
- const frame = xnew$1.context('xnew.modalframe');
1023
- const div = xnew$1.nest('<div style="width: 100%; height: 100%; opacity: 0;">');
1024
- div.style.background = background;
1021
+ function ModalContent(content, { background = 'rgba(0, 0, 0, 0.1)' } = {}) {
1022
+ const internal = xnew$1.context('xnew.modalframe');
1023
+ xnew$1.nest(`<div style="width: 100%; height: 100%; opacity: 0; background: ${background}">`);
1025
1024
  xnew$1.nest('<div style="position: absolute; inset: 0; margin: auto; width: max-content; height: max-content;">');
1026
1025
  xnew$1().on('click', (event) => event.stopPropagation());
1027
- xnew$1.timeout(() => frame.emit('-open'));
1028
- frame.on('-open', () => {
1029
- xnew$1.transition((x) => {
1030
- div.style.opacity = x.toString();
1031
- }, duration, easing);
1032
- });
1033
- frame.on('-close', () => {
1034
- xnew$1.transition((x) => {
1035
- div.style.opacity = (1.0 - x).toString();
1036
- }, duration, easing).next(() => frame.finalize());
1026
+ internal.on('-transition', ({ rate }) => {
1027
+ content.transition({ element: content.element, rate });
1037
1028
  });
1029
+ return {
1030
+ transition({ element, rate }) {
1031
+ const wrapper = element.parentElement;
1032
+ wrapper.style.opacity = rate.toString();
1033
+ }
1034
+ };
1038
1035
  }
1039
1036
 
1040
- function TabFrame(frame, { select = 0 } = {}) {
1041
- xnew$1.context('xnew.tabframe', frame);
1042
- const buttons = [];
1043
- const contents = [];
1044
- xnew$1.capture((unit) => unit.components.includes(TabButton), (unit) => {
1045
- buttons.push(unit);
1037
+ function TabFrame(frame, { select } = {}) {
1038
+ const internal = xnew$1((internal) => {
1039
+ const buttons = new Map();
1040
+ const contents = new Map();
1041
+ return { frame, buttons, contents };
1046
1042
  });
1047
- xnew$1.capture((unit) => unit.components.includes(TabContent), (unit) => {
1048
- contents.push(unit);
1049
- });
1050
- frame.on('-click', ({ unit }) => execute(buttons.indexOf(unit)));
1051
- const timeout = xnew$1.timeout(() => execute(select));
1052
- function execute(index) {
1053
- timeout.clear();
1054
- const button = buttons[index];
1055
- const content = contents[index];
1056
- buttons.filter((item) => item !== button).forEach((item) => item.deselect());
1057
- contents.filter((item) => item !== content).forEach((item) => item.deselect());
1058
- button.select();
1059
- content.select();
1060
- }
1043
+ xnew$1.context('xnew.tabframe', internal);
1044
+ xnew$1.timeout(() => internal.emit('-select', { key: select !== null && select !== void 0 ? select : [...internal.buttons.keys()][0] }));
1061
1045
  }
1062
- function TabButton(button, {} = {}) {
1063
- const frame = xnew$1.context('xnew.tabframe');
1064
- xnew$1.nest('<div>');
1065
- button.on('click', () => frame.emit('-click', { unit: button }));
1046
+ function TabButton(button, { key } = {}) {
1047
+ const internal = xnew$1.context('xnew.tabframe');
1048
+ const div = xnew$1.nest('<div>');
1049
+ key = key !== null && key !== void 0 ? key : (internal.buttons.size).toString();
1050
+ internal.buttons.set(key, button);
1051
+ button.on('click', () => {
1052
+ internal.emit('-select', { key });
1053
+ });
1054
+ internal.on('-select', ({ key }) => {
1055
+ const select = internal.buttons.get(key);
1056
+ if (select === button) {
1057
+ button.select({ element: div });
1058
+ }
1059
+ else {
1060
+ button.deselect({ element: div });
1061
+ }
1062
+ });
1066
1063
  return {
1067
- select() {
1068
- Object.assign(button.element.style, { opacity: 1.0, cursor: 'text' });
1064
+ select({ element }) {
1065
+ Object.assign(element.style, { opacity: 1.0, cursor: 'text' });
1069
1066
  },
1070
- deselect() {
1071
- Object.assign(button.element.style, { opacity: 0.6, cursor: 'pointer' });
1067
+ deselect({ element }) {
1068
+ Object.assign(element.style, { opacity: 0.6, cursor: 'pointer' });
1072
1069
  }
1073
1070
  };
1074
1071
  }
1075
- function TabContent(self, {} = {}) {
1076
- xnew$1.context('xnew.tabframe');
1077
- xnew$1.nest('<div>');
1072
+ function TabContent(content, { key } = {}) {
1073
+ const internal = xnew$1.context('xnew.tabframe');
1074
+ const div = xnew$1.nest('<div style="display: none;">');
1075
+ key = key !== null && key !== void 0 ? key : (internal.contents.size).toString();
1076
+ internal.contents.set(key, content);
1077
+ internal.on('-select', ({ key }) => {
1078
+ const select = internal.contents.get(key);
1079
+ if (select === content) {
1080
+ content.select({ element: div });
1081
+ }
1082
+ else {
1083
+ content.deselect({ element: div });
1084
+ }
1085
+ });
1078
1086
  return {
1079
- select() {
1080
- Object.assign(self.element.style, { display: 'block' });
1087
+ select({ element }) {
1088
+ Object.assign(element.style, { display: 'block' });
1081
1089
  },
1082
- deselect() {
1083
- Object.assign(self.element.style, { display: 'none' });
1090
+ deselect({ element }) {
1091
+ Object.assign(element.style, { display: 'none' });
1084
1092
  }
1085
1093
  };
1086
1094
  }
1087
1095
 
1088
- function AccordionFrame(frame, {} = {}) {
1089
- xnew$1.context('xnew.accordionframe', frame);
1090
- let content = null;
1091
- xnew$1.capture((unit) => unit.components.includes(AccordionContent), (unit) => {
1092
- content = unit;
1096
+ function AccordionFrame(frame, { open = false, duration = 200, easing = 'ease' } = {}) {
1097
+ const internal = xnew$1((internal) => {
1098
+ return { frame, open, rate: 0.0, };
1093
1099
  });
1100
+ xnew$1.context('xnew.accordionframe', internal);
1101
+ internal.on('-transition', ({ rate }) => internal.rate = rate);
1102
+ internal.emit('-transition', { rate: open ? 1.0 : 0.0 });
1094
1103
  return {
1095
1104
  toggle() {
1096
- if ((content === null || content === void 0 ? void 0 : content.status) === 1.0) {
1097
- frame.emit('-close');
1105
+ if (internal.rate === 1.0) {
1106
+ frame.close();
1098
1107
  }
1099
- else if ((content === null || content === void 0 ? void 0 : content.status) === 0.0) {
1100
- frame.emit('-open');
1108
+ else if (internal.rate === 0.0) {
1109
+ frame.open();
1101
1110
  }
1102
1111
  },
1103
1112
  open() {
1104
- if ((content === null || content === void 0 ? void 0 : content.status) === 0.0) {
1105
- frame.emit('-open');
1113
+ if (internal.rate === 0.0) {
1114
+ xnew$1.transition((x) => internal.emit('-transition', { rate: x }), duration, easing);
1106
1115
  }
1107
1116
  },
1108
1117
  close() {
1109
- if ((content === null || content === void 0 ? void 0 : content.status) === 1.0) {
1110
- frame.emit('-close');
1118
+ if (internal.rate === 1.0) {
1119
+ xnew$1.transition((x) => internal.emit('-transition', { rate: 1.0 - x }), duration, easing);
1111
1120
  }
1112
1121
  }
1113
1122
  };
1114
1123
  }
1115
1124
  function AccordionHeader(header, {} = {}) {
1116
- const frame = xnew$1.context('xnew.accordionframe');
1125
+ const internal = xnew$1.context('xnew.accordionframe');
1117
1126
  xnew$1.nest('<button style="display: flex; align-items: center; margin: 0; padding: 0; width: 100%; text-align: left; border: none; font: inherit; color: inherit; background: none; cursor: pointer;">');
1118
- header.on('click', () => frame.toggle());
1127
+ header.on('click', () => internal.frame.toggle());
1119
1128
  }
1120
1129
  function AccordionBullet(bullet, { type = 'arrow' } = {}) {
1121
- const frame = xnew$1.context('xnew.accordionframe');
1122
- xnew$1.nest('<div style="display:inline-block; position: relative; width: 0.5em; margin: 0 0.3em;">');
1123
- frame.on('-transition', ({ status }) => { var _a; return (_a = bullet.transition) === null || _a === void 0 ? void 0 : _a.call(bullet, status); });
1130
+ const internal = xnew$1.context('xnew.accordionframe');
1131
+ xnew$1.nest('<div style="display:inline-block; position: relative; width: 0.55em; margin: 0 0.3em;">');
1124
1132
  if (type === 'arrow') {
1125
- const arrow = xnew$1(`<div style="width: 100%; height: 0.5em; border-right: 0.12em solid currentColor; border-bottom: 0.12em solid currentColor; box-sizing: border-box; transform-origin: center center;">`);
1126
- return {
1127
- transition(status) {
1128
- arrow.element.style.transform = `rotate(${status * 90 - 45}deg)`;
1129
- }
1130
- };
1133
+ const arrow = xnew$1(`<div style="width: 100%; height: 0.55em; border-right: 0.12em solid currentColor; border-bottom: 0.12em solid currentColor; box-sizing: border-box; transform-origin: center;">`);
1134
+ arrow.element.style.transform = `rotate(${internal.rate * 90 - 45}deg)`;
1135
+ internal.on('-transition', ({ rate }) => {
1136
+ arrow.element.style.transform = `rotate(${rate * 90 - 45}deg)`;
1137
+ });
1131
1138
  }
1132
1139
  else if (type === 'plusminus') {
1133
- xnew$1(`<div style="position: absolute; width: 100%; border-top: 0.06em solid currentColor; border-bottom: 0.06em solid currentColor; box-sizing: border-box; transform-origin: center center;">`);
1134
- const line2 = xnew$1(`<div style="position: absolute; width: 100%; border-top: 0.06em solid currentColor; border-bottom: 0.06em solid currentColor; box-sizing: border-box; transform-origin: center center;">`);
1140
+ const line1 = xnew$1(`<div style="position: absolute; width: 100%; border-top: 0.06em solid currentColor; border-bottom: 0.06em solid currentColor; box-sizing: border-box; transform-origin: center;">`);
1141
+ const line2 = xnew$1(`<div style="position: absolute; width: 100%; border-top: 0.06em solid currentColor; border-bottom: 0.06em solid currentColor; box-sizing: border-box; transform-origin: center;">`);
1135
1142
  line2.element.style.transform = `rotate(90deg)`;
1136
- return {
1137
- transition(status) {
1138
- line2.element.style.opacity = `${1.0 - status}`;
1139
- }
1140
- };
1143
+ line2.element.style.opacity = `${1.0 - internal.rate}`;
1144
+ internal.on('-transition', ({ rate }) => {
1145
+ line1.element.style.transform = `rotate(${90 + rate * 90}deg)`;
1146
+ line2.element.style.transform = `rotate(${rate * 180}deg)`;
1147
+ });
1141
1148
  }
1142
1149
  }
1143
- function AccordionContent(content, { open = false, duration = 200, easing = 'ease' } = {}) {
1144
- const frame = xnew$1.context('xnew.accordionframe');
1145
- const outer = xnew$1.nest('<div>');
1146
- const inner = xnew$1.nest('<div style="padding: 0; display: flex; flex-direction: column; box-sizing: border-box;">');
1147
- let status = open ? 1.0 : 0.0;
1148
- outer.style.display = status ? 'block' : 'none';
1149
- frame.emit('-transition', { status });
1150
- frame.on('-open', () => {
1151
- xnew$1.transition((x) => {
1152
- status = x;
1153
- frame.emit('-transition', { status });
1154
- content.transition(status);
1155
- }, duration, easing);
1156
- });
1157
- frame.on('-close', () => {
1158
- xnew$1.transition((x) => {
1159
- status = 1.0 - x;
1160
- frame.emit('-transition', { status });
1161
- content.transition(status);
1162
- }, duration, easing);
1150
+ function AccordionContent(content, {} = {}) {
1151
+ const internal = xnew$1.context('xnew.accordionframe');
1152
+ xnew$1.nest(`<div style="display: ${internal.open ? 'block' : 'none'};">`);
1153
+ xnew$1.nest('<div style="padding: 0; display: flex; flex-direction: column; box-sizing: border-box;">');
1154
+ internal.on('-transition', ({ rate }) => {
1155
+ content.transition({ element: content.element, rate });
1163
1156
  });
1164
1157
  return {
1165
- get status() {
1166
- return status;
1167
- },
1168
- transition(status) {
1169
- outer.style.display = 'block';
1170
- if (status === 0.0) {
1171
- outer.style.display = 'none';
1158
+ transition({ element, rate }) {
1159
+ const wrapper = element.parentElement;
1160
+ wrapper.style.display = 'block';
1161
+ if (rate === 0.0) {
1162
+ wrapper.style.display = 'none';
1172
1163
  }
1173
- else if (status < 1.0) {
1174
- Object.assign(outer.style, { height: inner.offsetHeight * status + 'px', overflow: 'hidden', opacity: status });
1164
+ else if (rate < 1.0) {
1165
+ Object.assign(wrapper.style, { height: element.offsetHeight * rate + 'px', overflow: 'hidden', opacity: rate });
1175
1166
  }
1176
1167
  else {
1177
- Object.assign(outer.style, { height: 'auto', overflow: 'visible', opacity: 1.0 });
1168
+ Object.assign(wrapper.style, { height: 'auto', overflow: 'visible', opacity: 1.0 });
1178
1169
  }
1179
- },
1170
+ }
1180
1171
  };
1181
1172
  }
1182
1173
 
@@ -1187,18 +1178,30 @@
1187
1178
  function DragTarget(target, {} = {}) {
1188
1179
  const { frame, absolute } = xnew$1.context('xnew.dragframe');
1189
1180
  xnew$1.nest('<div>');
1190
- const user = xnew$1(absolute.parentElement, UserEvent);
1181
+ const pointer = xnew$1(absolute.parentElement, PointerEvent);
1191
1182
  const current = { x: 0, y: 0 };
1192
- user.on('-dragstart', ({ event, position }) => {
1193
- current.x = parseFloat(absolute.style.left || '0') + position.x;
1194
- current.y = parseFloat(absolute.style.top || '0') + position.y;
1183
+ const offset = { x: 0, y: 0 };
1184
+ let dragged = false;
1185
+ pointer.on('-dragstart', ({ event, position }) => {
1186
+ if (target.element.contains(event.target) === false)
1187
+ return;
1188
+ dragged = true;
1189
+ offset.x = position.x - parseFloat(absolute.style.left || '0');
1190
+ offset.y = position.y - parseFloat(absolute.style.top || '0');
1191
+ current.x = position.x - offset.x;
1192
+ current.y = position.y - offset.y;
1195
1193
  });
1196
- user.on('-dragmove', ({ event, delta }) => {
1194
+ pointer.on('-dragmove', ({ event, delta }) => {
1195
+ if (dragged !== true)
1196
+ return;
1197
1197
  current.x += delta.x;
1198
1198
  current.y += delta.y;
1199
1199
  absolute.style.left = `${current.x}px`;
1200
1200
  absolute.style.top = `${current.y}px`;
1201
1201
  });
1202
+ pointer.on('-dragcancel -dragend', ({ event }) => {
1203
+ dragged = false;
1204
+ });
1202
1205
  }
1203
1206
 
1204
1207
  //----------------------------------------------------------------------------------------------------
@@ -1207,184 +1210,264 @@
1207
1210
  function SVGTemplate(self, { fill = null, fillOpacity = 0.8, stroke = null, strokeOpacity = 0.8, strokeWidth = 2, strokeLinejoin = 'round' }) {
1208
1211
  xnew$1.nest(`<svg
1209
1212
  viewBox="0 0 100 100"
1210
- style="position: absolute; width: 100%; height: 100%; user-select: none;
1213
+ style="position: absolute; width: 100%; height: 100%; pointer-select: none;
1211
1214
  ${fill ? `fill: ${fill}; fill-opacity: ${fillOpacity};` : ''}
1212
1215
  ${stroke ? `stroke: ${stroke}; stroke-opacity: ${strokeOpacity}; stroke-width: ${strokeWidth}; stroke-linejoin: ${strokeLinejoin};` : ''}
1213
1216
  ">`);
1214
1217
  }
1215
- function TouchStick(self, { size = 130, fill = '#FFF', fillOpacity = 0.8, stroke = '#000', strokeOpacity = 0.8, strokeWidth = 2, strokeLinejoin = 'round' } = {}) {
1216
- strokeWidth /= (size / 100);
1217
- xnew$1.nest(`<div style="position: relative; width: ${size}px; height: ${size}px; cursor: pointer; user-select: none; overflow: hidden;">`);
1218
- xnew$1((self) => {
1219
- xnew$1.extend(SVGTemplate, { fill, fillOpacity, stroke, strokeOpacity, strokeWidth, strokeLinejoin });
1220
- xnew$1('<polygon points="50 7 40 18 60 18">');
1221
- xnew$1('<polygon points="50 93 40 83 60 83">');
1222
- xnew$1('<polygon points=" 7 50 18 40 18 60">');
1223
- xnew$1('<polygon points="93 50 83 40 83 60">');
1224
- });
1225
- const target = xnew$1((self) => {
1226
- xnew$1.extend(SVGTemplate, { fill, fillOpacity, stroke, strokeOpacity, strokeWidth, strokeLinejoin });
1227
- xnew$1('<circle cx="50" cy="50" r="23">');
1228
- });
1229
- const user = xnew$1(UserEvent);
1230
- user.on('-dragstart', ({ event, position }) => {
1231
- const vector = getVector(position);
1232
- target.element.style.filter = 'brightness(90%)';
1233
- target.element.style.left = vector.x * size / 4 + 'px';
1234
- target.element.style.top = vector.y * size / 4 + 'px';
1235
- self.emit('-down', { vector });
1236
- });
1237
- user.on('-dragmove', ({ event, position }) => {
1238
- const vector = getVector(position);
1239
- target.element.style.filter = 'brightness(90%)';
1240
- target.element.style.left = vector.x * size / 4 + 'px';
1241
- target.element.style.top = vector.y * size / 4 + 'px';
1242
- self.emit('-move', { vector });
1243
- });
1244
- user.on('-dragend', ({ event }) => {
1245
- const vector = { x: 0, y: 0 };
1246
- target.element.style.filter = '';
1247
- target.element.style.left = vector.x * size / 4 + 'px';
1248
- target.element.style.top = vector.y * size / 4 + 'px';
1249
- self.emit('-up', { vector });
1250
- });
1251
- function getVector(position) {
1252
- const x = position.x - size / 2;
1253
- const y = position.y - size / 2;
1254
- const d = Math.min(1.0, Math.sqrt(x * x + y * y) / (size / 4));
1255
- const a = (y !== 0 || x !== 0) ? Math.atan2(y, x) : 0;
1256
- return { x: Math.cos(a) * d, y: Math.sin(a) * d };
1218
+ function AnalogStick(self, { size, fill = '#FFF', fillOpacity = 0.8, stroke = '#000', strokeOpacity = 0.8, strokeWidth = 2, strokeLinejoin = 'round' } = {}) {
1219
+ xnew$1.nest(`<div style="position: relative; width: 100%; height: 100%;">`);
1220
+ let internal;
1221
+ let newsize;
1222
+ if (size) {
1223
+ newsize = size;
1257
1224
  }
1258
- }
1259
- function TouchDPad(self, { size = 130, fill = '#FFF', fillOpacity = 0.8, stroke = '#000', strokeOpacity = 0.8, strokeWidth = 2, strokeLinejoin = 'round' } = {}) {
1260
- strokeWidth /= (size / 100);
1261
- xnew$1.nest(`<div style="position: relative; width: ${size}px; height: ${size}px; cursor: pointer; user-select: none; overflow: hidden;">`);
1262
- const polygons = [
1263
- '<polygon points="50 50 35 35 35 5 37 3 63 3 65 5 65 35">',
1264
- '<polygon points="50 50 35 65 35 95 37 97 63 97 65 95 65 65">',
1265
- '<polygon points="50 50 35 35 5 35 3 37 3 63 5 65 35 65">',
1266
- '<polygon points="50 50 65 35 95 35 97 37 97 63 95 65 65 65">'
1267
- ];
1268
- const targets = polygons.map((polygon) => {
1269
- return xnew$1((self) => {
1270
- xnew$1.extend(SVGTemplate, { fill, fillOpacity });
1271
- xnew$1(polygon);
1225
+ else {
1226
+ newsize = Math.min(self.element.clientWidth, self.element.clientHeight);
1227
+ xnew$1(self.element, ResizeEvent).on('-resize', () => {
1228
+ newsize = Math.min(self.element.clientWidth, self.element.clientHeight);
1229
+ internal === null || internal === void 0 ? void 0 : internal.reboot();
1272
1230
  });
1273
- });
1274
- xnew$1((self) => {
1275
- xnew$1.extend(SVGTemplate, { fill: 'none', stroke, strokeOpacity, strokeWidth, strokeLinejoin });
1276
- xnew$1('<polyline points="35 35 35 5 37 3 63 3 65 5 65 35">');
1277
- xnew$1('<polyline points="35 65 35 95 37 97 63 97 65 95 65 65">');
1278
- xnew$1('<polyline points="35 35 5 35 3 37 3 63 5 65 35 65">');
1279
- xnew$1('<polyline points="65 35 95 35 97 37 97 63 95 65 65 65">');
1280
- xnew$1('<polygon points="50 11 42 20 58 20">');
1281
- xnew$1('<polygon points="50 89 42 80 58 80">');
1282
- xnew$1('<polygon points="11 50 20 42 20 58">');
1283
- xnew$1('<polygon points="89 50 80 42 80 58">');
1284
- });
1285
- const user = xnew$1(UserEvent);
1286
- user.on('-dragstart', ({ event, position }) => {
1287
- const vector = getVector(position);
1288
- targets[0].element.style.filter = (vector.y < 0) ? 'brightness(90%)' : '';
1289
- targets[1].element.style.filter = (vector.y > 0) ? 'brightness(90%)' : '';
1290
- targets[2].element.style.filter = (vector.x < 0) ? 'brightness(90%)' : '';
1291
- targets[3].element.style.filter = (vector.x > 0) ? 'brightness(90%)' : '';
1292
- self.emit('-down', { vector });
1293
- });
1294
- user.on('-dragmove', ({ event, position }) => {
1295
- const vector = getVector(position);
1296
- targets[0].element.style.filter = (vector.y < 0) ? 'brightness(90%)' : '';
1297
- targets[1].element.style.filter = (vector.y > 0) ? 'brightness(90%)' : '';
1298
- targets[2].element.style.filter = (vector.x < 0) ? 'brightness(90%)' : '';
1299
- targets[3].element.style.filter = (vector.x > 0) ? 'brightness(90%)' : '';
1300
- self.emit('-move', { vector });
1301
- });
1302
- user.on('-dragend', ({ event }) => {
1303
- const vector = { x: 0, y: 0 };
1304
- targets[0].element.style.filter = '';
1305
- targets[1].element.style.filter = '';
1306
- targets[2].element.style.filter = '';
1307
- targets[3].element.style.filter = '';
1308
- self.emit('-up', { vector });
1309
- });
1310
- function getVector(position) {
1311
- const x = position.x - size / 2;
1312
- const y = position.y - size / 2;
1313
- const a = (y !== 0 || x !== 0) ? Math.atan2(y, x) : 0;
1314
- const d = Math.min(1.0, Math.sqrt(x * x + y * y) / (size / 4));
1315
- const vector = { x: Math.cos(a) * d, y: Math.sin(a) * d };
1316
- vector.x = Math.abs(vector.x) > 0.5 ? Math.sign(vector.x) : 0;
1317
- vector.y = Math.abs(vector.y) > 0.5 ? Math.sign(vector.y) : 0;
1318
- return vector;
1319
1231
  }
1232
+ internal = xnew$1(() => {
1233
+ xnew$1.nest(`<div style="position: absolute; width: ${newsize}px; height: ${newsize}px; margin: auto; inset: 0; cursor: pointer; pointer-select: none; pointer-events: auto; overflow: hidden;">`);
1234
+ xnew$1((self) => {
1235
+ xnew$1.extend(SVGTemplate, { fill, fillOpacity, stroke, strokeOpacity, strokeWidth, strokeLinejoin });
1236
+ xnew$1('<polygon points="50 7 40 18 60 18">');
1237
+ xnew$1('<polygon points="50 93 40 83 60 83">');
1238
+ xnew$1('<polygon points=" 7 50 18 40 18 60">');
1239
+ xnew$1('<polygon points="93 50 83 40 83 60">');
1240
+ });
1241
+ const target = xnew$1((self) => {
1242
+ xnew$1.extend(SVGTemplate, { fill, fillOpacity, stroke, strokeOpacity, strokeWidth, strokeLinejoin });
1243
+ xnew$1('<circle cx="50" cy="50" r="23">');
1244
+ });
1245
+ const pointer = xnew$1(PointerEvent);
1246
+ pointer.on('-dragstart', ({ event, position }) => {
1247
+ const vector = getVector(position);
1248
+ target.element.style.filter = 'brightness(90%)';
1249
+ target.element.style.left = vector.x * newsize / 4 + 'px';
1250
+ target.element.style.top = vector.y * newsize / 4 + 'px';
1251
+ self.emit('-down', { vector });
1252
+ });
1253
+ pointer.on('-dragmove', ({ event, position }) => {
1254
+ const vector = getVector(position);
1255
+ target.element.style.filter = 'brightness(90%)';
1256
+ target.element.style.left = vector.x * newsize / 4 + 'px';
1257
+ target.element.style.top = vector.y * newsize / 4 + 'px';
1258
+ self.emit('-move', { vector });
1259
+ });
1260
+ pointer.on('-dragend', ({ event }) => {
1261
+ const vector = { x: 0, y: 0 };
1262
+ target.element.style.filter = '';
1263
+ target.element.style.left = vector.x * newsize / 4 + 'px';
1264
+ target.element.style.top = vector.y * newsize / 4 + 'px';
1265
+ self.emit('-up', { vector });
1266
+ });
1267
+ function getVector(position) {
1268
+ const x = position.x - newsize / 2;
1269
+ const y = position.y - newsize / 2;
1270
+ const d = Math.min(1.0, Math.sqrt(x * x + y * y) / (newsize / 4));
1271
+ const a = (y !== 0 || x !== 0) ? Math.atan2(y, x) : 0;
1272
+ return { x: Math.cos(a) * d, y: Math.sin(a) * d };
1273
+ }
1274
+ });
1320
1275
  }
1321
- function TouchButton(self, { size = 80, fill = '#FFF', fillOpacity = 0.8, stroke = '#000', strokeOpacity = 0.8, strokeWidth = 2, strokeLinejoin = 'round' } = {}) {
1322
- strokeWidth /= (size / 100);
1323
- xnew$1.nest(`<div style="position: relative; width: ${size}px; height: ${size}px; cursor: pointer; user-select: none; overflow: hidden;">`);
1324
- const target = xnew$1((self) => {
1325
- xnew$1.extend(SVGTemplate, { fill, fillOpacity, stroke, strokeOpacity, strokeWidth, strokeLinejoin });
1326
- xnew$1('<circle cx="50" cy="50" r="40">');
1276
+ function DirectionalPad(self, { size, diagonal = true, fill = '#FFF', fillOpacity = 0.8, stroke = '#000', strokeOpacity = 0.8, strokeWidth = 2, strokeLinejoin = 'round' } = {}) {
1277
+ xnew$1.nest(`<div style="position: relative; width: 100%; height: 100%;">`);
1278
+ let internal;
1279
+ let newsize;
1280
+ if (size) {
1281
+ newsize = size;
1282
+ }
1283
+ else {
1284
+ newsize = Math.min(self.element.clientWidth, self.element.clientHeight);
1285
+ xnew$1(self.element, ResizeEvent).on('-resize', () => {
1286
+ newsize = Math.min(self.element.clientWidth, self.element.clientHeight);
1287
+ internal === null || internal === void 0 ? void 0 : internal.reboot();
1288
+ });
1289
+ }
1290
+ internal = xnew$1(() => {
1291
+ xnew$1.nest(`<div style="position: absolute; width: ${newsize}px; height: ${newsize}px; margin: auto; inset: 0; cursor: pointer; pointer-select: none; pointer-events: auto; overflow: hidden;">`);
1292
+ const polygons = [
1293
+ '<polygon points="50 50 35 35 35 5 37 3 63 3 65 5 65 35">',
1294
+ '<polygon points="50 50 35 65 35 95 37 97 63 97 65 95 65 65">',
1295
+ '<polygon points="50 50 35 35 5 35 3 37 3 63 5 65 35 65">',
1296
+ '<polygon points="50 50 65 35 95 35 97 37 97 63 95 65 65 65">'
1297
+ ];
1298
+ const targets = polygons.map((polygon) => {
1299
+ return xnew$1((self) => {
1300
+ xnew$1.extend(SVGTemplate, { fill, fillOpacity });
1301
+ xnew$1(polygon);
1302
+ });
1303
+ });
1304
+ xnew$1((self) => {
1305
+ xnew$1.extend(SVGTemplate, { fill: 'none', stroke, strokeOpacity, strokeWidth, strokeLinejoin });
1306
+ xnew$1('<polyline points="35 35 35 5 37 3 63 3 65 5 65 35">');
1307
+ xnew$1('<polyline points="35 65 35 95 37 97 63 97 65 95 65 65">');
1308
+ xnew$1('<polyline points="35 35 5 35 3 37 3 63 5 65 35 65">');
1309
+ xnew$1('<polyline points="65 35 95 35 97 37 97 63 95 65 65 65">');
1310
+ xnew$1('<polygon points="50 11 42 20 58 20">');
1311
+ xnew$1('<polygon points="50 89 42 80 58 80">');
1312
+ xnew$1('<polygon points="11 50 20 42 20 58">');
1313
+ xnew$1('<polygon points="89 50 80 42 80 58">');
1314
+ });
1315
+ const pointer = xnew$1(PointerEvent);
1316
+ pointer.on('-dragstart', ({ event, position }) => {
1317
+ const vector = getVector(position);
1318
+ targets[0].element.style.filter = (vector.y < 0) ? 'brightness(90%)' : '';
1319
+ targets[1].element.style.filter = (vector.y > 0) ? 'brightness(90%)' : '';
1320
+ targets[2].element.style.filter = (vector.x < 0) ? 'brightness(90%)' : '';
1321
+ targets[3].element.style.filter = (vector.x > 0) ? 'brightness(90%)' : '';
1322
+ self.emit('-down', { vector });
1323
+ });
1324
+ pointer.on('-dragmove', ({ event, position }) => {
1325
+ const vector = getVector(position);
1326
+ targets[0].element.style.filter = (vector.y < 0) ? 'brightness(90%)' : '';
1327
+ targets[1].element.style.filter = (vector.y > 0) ? 'brightness(90%)' : '';
1328
+ targets[2].element.style.filter = (vector.x < 0) ? 'brightness(90%)' : '';
1329
+ targets[3].element.style.filter = (vector.x > 0) ? 'brightness(90%)' : '';
1330
+ self.emit('-move', { vector });
1331
+ });
1332
+ pointer.on('-dragend', ({ event }) => {
1333
+ const vector = { x: 0, y: 0 };
1334
+ targets[0].element.style.filter = '';
1335
+ targets[1].element.style.filter = '';
1336
+ targets[2].element.style.filter = '';
1337
+ targets[3].element.style.filter = '';
1338
+ self.emit('-up', { vector });
1339
+ });
1340
+ function getVector(position) {
1341
+ const x = position.x - newsize / 2;
1342
+ const y = position.y - newsize / 2;
1343
+ const a = (y !== 0 || x !== 0) ? Math.atan2(y, x) : 0;
1344
+ const d = Math.min(1.0, Math.sqrt(x * x + y * y) / (newsize / 4));
1345
+ const vector = { x: Math.cos(a) * d, y: Math.sin(a) * d };
1346
+ if (diagonal === true) {
1347
+ vector.x = Math.abs(vector.x) > 0.5 ? Math.sign(vector.x) : 0;
1348
+ vector.y = Math.abs(vector.y) > 0.5 ? Math.sign(vector.y) : 0;
1349
+ }
1350
+ else if (Math.abs(vector.x) > Math.abs(vector.y)) {
1351
+ vector.x = Math.abs(vector.x) > 0.5 ? Math.sign(vector.x) : 0;
1352
+ vector.y = 0;
1353
+ }
1354
+ else {
1355
+ vector.x = 0;
1356
+ vector.y = Math.abs(vector.y) > 0.5 ? Math.sign(vector.y) : 0;
1357
+ }
1358
+ return vector;
1359
+ }
1327
1360
  });
1328
- const user = xnew$1(UserEvent);
1329
- user.on('-dragstart', (event) => {
1330
- target.element.style.filter = 'brightness(90%)';
1331
- self.emit('-down', event);
1361
+ }
1362
+
1363
+ const context = new AudioContext();
1364
+ const master = context.createGain();
1365
+ master.gain.value = 1.0;
1366
+ master.connect(context.destination);
1367
+ function connect(params) {
1368
+ const nodes = {};
1369
+ Object.keys(params).forEach((key) => {
1370
+ const [type, props, ...to] = params[key];
1371
+ nodes[key] = context[`create${type}`]();
1372
+ const node = nodes[key];
1373
+ Object.keys(props).forEach((name) => {
1374
+ var _a;
1375
+ if (((_a = node[name]) === null || _a === void 0 ? void 0 : _a.value) !== undefined) {
1376
+ node[name].value = props[name];
1377
+ }
1378
+ else {
1379
+ node[name] = props[name];
1380
+ }
1381
+ });
1332
1382
  });
1333
- user.on('-dragend', (event) => {
1334
- target.element.style.filter = '';
1335
- self.emit('-up', event);
1383
+ Object.keys(params).forEach((key) => {
1384
+ const [type, props, ...to] = params[key];
1385
+ to.forEach((to) => {
1386
+ let dest = null;
1387
+ if (to.indexOf('.') > 0) {
1388
+ dest = nodes[to.split('.')[0]][to.split('.')[1]];
1389
+ }
1390
+ else if (nodes[to]) {
1391
+ dest = nodes[to];
1392
+ }
1393
+ else if (to === 'master') {
1394
+ dest = master;
1395
+ }
1396
+ nodes[key].connect(dest);
1397
+ });
1336
1398
  });
1399
+ return nodes;
1337
1400
  }
1338
1401
 
1339
- class Audio {
1340
- static initialize() {
1341
- var _a;
1342
- if (typeof window !== 'undefined' && window instanceof Window) {
1343
- Audio.context = new ((_a = window.AudioContext) !== null && _a !== void 0 ? _a : window.webkitAudioContext)();
1344
- Audio.master = Audio.context.createGain();
1345
- Audio.master.gain.value = 1.0;
1346
- Audio.master.connect(Audio.context.destination);
1402
+ const store = new Map();
1403
+ function load(path) {
1404
+ return new AudioFile(path);
1405
+ }
1406
+ class AudioFile {
1407
+ constructor(path) {
1408
+ this.data = {};
1409
+ if (store.has(path)) {
1410
+ this.data = store.get(path);
1347
1411
  }
1348
- }
1349
- static connect(params) {
1350
- if (!Audio.context)
1351
- throw new Error("Audio context not initialized");
1352
- const nodes = {};
1353
- Object.keys(params).forEach((key) => {
1354
- const [type, props, ...to] = params[key];
1355
- nodes[key] = Audio.context[`create${type}`]();
1356
- Object.keys(props).forEach((name) => {
1357
- var _a;
1358
- if (((_a = nodes[key][name]) === null || _a === void 0 ? void 0 : _a.value) !== undefined) {
1359
- nodes[key][name].value = props[name];
1360
- }
1361
- else {
1362
- nodes[key][name] = props[name];
1363
- }
1364
- });
1365
- });
1366
- Object.keys(params).forEach((key) => {
1367
- const [type, props, ...to] = params[key];
1368
- to.forEach((to) => {
1369
- let dest = null;
1370
- if (to.indexOf('.') > 0) {
1371
- dest = nodes[to.split('.')[0]][to.split('.')[1]];
1372
- }
1373
- else if (nodes[to]) {
1374
- dest = nodes[to];
1375
- }
1376
- else if (to === 'master') {
1377
- dest = Audio.master;
1378
- }
1379
- nodes[key].connect(dest);
1412
+ else {
1413
+ this.data.buffer = null;
1414
+ this.data.promise = fetch(path)
1415
+ .then((response) => response.arrayBuffer())
1416
+ .then((response) => context.decodeAudioData(response))
1417
+ .then((response) => {
1418
+ this.data.buffer = response;
1419
+ this.nodes.source.buffer = this.data.buffer;
1420
+ })
1421
+ .catch(() => {
1422
+ console.warn(`"${path}" could not be loaded.`);
1380
1423
  });
1424
+ store.set(path, this.data);
1425
+ }
1426
+ this.startTime = null;
1427
+ this.nodes = connect({
1428
+ source: ['BufferSource', {}, 'volume'],
1429
+ volume: ['Gain', { gain: 1.0 }, 'master'],
1381
1430
  });
1382
- return nodes;
1431
+ }
1432
+ isReady() {
1433
+ return this.data.buffer ? true : false;
1434
+ }
1435
+ get promise() {
1436
+ return this.data.promise;
1437
+ }
1438
+ set volume(value) {
1439
+ this.nodes.volume.gain.value = value;
1440
+ }
1441
+ get volume() {
1442
+ return this.nodes.volume.gain.value;
1443
+ }
1444
+ set loop(value) {
1445
+ this.nodes.source.loop = value;
1446
+ }
1447
+ get loop() {
1448
+ return this.nodes.source.loop;
1449
+ }
1450
+ play(offset = 0) {
1451
+ if (this.startTime !== null)
1452
+ return;
1453
+ if (this.isReady()) {
1454
+ this.startTime = context.currentTime;
1455
+ this.nodes.source.playbackRate.value = 1;
1456
+ this.nodes.source.start(context.currentTime, offset / 1000);
1457
+ }
1458
+ else {
1459
+ this.promise.then(() => this.play());
1460
+ }
1461
+ }
1462
+ pause() {
1463
+ if (this.startTime === null)
1464
+ return;
1465
+ this.nodes.source.stop(context.currentTime);
1466
+ const elapsed = (context.currentTime - this.startTime) % this.data.buffer.duration * 1000;
1467
+ this.startTime = null;
1468
+ return elapsed;
1383
1469
  }
1384
1470
  }
1385
- Audio.context = null;
1386
- Audio.master = null;
1387
- Audio.initialize();
1388
1471
 
1389
1472
  function synthesizer(props, effects) {
1390
1473
  return new Synthesizer(props, effects);
@@ -1408,30 +1491,20 @@
1408
1491
  window.removeEventListener('mousedown', initialize, true);
1409
1492
  }
1410
1493
  }
1411
- constructor({ oscillator = null, filter = null, amp = null } = {}, { bmp = null, reverb = null, delay = null } = {}) {
1494
+ constructor({ oscillator = null, filter = null, amp = null } = {}, { bmp = null, reverb = null } = {}) {
1412
1495
  this.oscillator = isObject(oscillator) ? oscillator : {};
1413
1496
  this.oscillator.type = setType(this.oscillator.type, ['sine', 'triangle', 'square', 'sawtooth']);
1414
1497
  this.oscillator.envelope = setEnvelope(this.oscillator.envelope, -36, +36);
1415
1498
  this.oscillator.LFO = setLFO(this.oscillator.LFO, 36);
1416
1499
  this.filter = isObject(filter) ? filter : {};
1417
1500
  this.filter.type = setType(this.filter.type, ['lowpass', 'highpass', 'bandpass']);
1418
- this.filter.Q = isNumber(this.filter.Q) ? clamp(this.filter.Q, 0, 32) : 0;
1419
- // cutoffはundefinedを使う
1420
1501
  this.filter.cutoff = isNumber(this.filter.cutoff) ? clamp(this.filter.cutoff, 4, 8192) : undefined;
1421
- this.filter.envelope = setEnvelope(this.filter.envelope, -36, +36);
1422
- this.filter.LFO = setLFO(this.filter.LFO, 36);
1423
1502
  this.amp = isObject(amp) ? amp : {};
1424
1503
  this.amp.envelope = setEnvelope(this.amp.envelope, 0, 1);
1425
- this.amp.LFO = setLFO(this.amp.LFO, 36);
1426
1504
  this.bmp = isNumber(bmp) ? clamp(bmp, 60, 240) : 120;
1427
- this.options = { bmp: this.bmp };
1428
1505
  this.reverb = isObject(reverb) ? reverb : {};
1429
1506
  this.reverb.time = isNumber(this.reverb.time) ? clamp(this.reverb.time, 0, 2000) : 0.0;
1430
1507
  this.reverb.mix = isNumber(this.reverb.mix) ? clamp(this.reverb.mix, 0, 1.0) : 0.0;
1431
- this.delay = isObject(delay) ? delay : {};
1432
- this.delay.time = isNumber(this.delay.time) ? clamp(this.delay.time, 0, 2000) : 0.0;
1433
- this.delay.feedback = isNumber(this.delay.feedback) ? clamp(this.delay.feedback, 0.0, 0.9) : 0.0;
1434
- this.delay.mix = isNumber(this.delay.mix) ? clamp(this.delay.mix, 0.0, 1.0) : 0.0;
1435
1508
  function setType(type, list, value = 0) {
1436
1509
  return list.includes(type) ? type : list[value];
1437
1510
  }
@@ -1467,46 +1540,43 @@
1467
1540
  }
1468
1541
  press(frequency, duration = null, wait = 0.0) {
1469
1542
  frequency = typeof frequency === 'string' ? Synthesizer.keymap[frequency] : frequency;
1470
- duration = typeof duration === 'string' ? (Synthesizer.notemap[duration] * 60 / this.options.bmp) : (duration !== null ? (duration / 1000) : duration);
1471
- const start = Audio.context.currentTime + wait / 1000;
1543
+ duration = typeof duration === 'string' ? (Synthesizer.notemap[duration] * 60 / this.bmp) : (duration !== null ? (duration / 1000) : duration);
1544
+ const start = context.currentTime + wait / 1000;
1472
1545
  let stop = null;
1473
- const params = {};
1546
+ const nodes = {};
1547
+ nodes.oscillator = context.createOscillator();
1548
+ nodes.amp = context.createGain();
1549
+ nodes.amp.gain.value = 0.0;
1550
+ nodes.target = context.createGain();
1551
+ nodes.target.gain.value = 1.0;
1552
+ nodes.amp.connect(nodes.target);
1553
+ nodes.target.connect(master);
1474
1554
  if (this.filter.type && this.filter.cutoff) {
1475
- params.oscillator = ['Oscillator', {}, 'filter'];
1476
- params.filter = ['BiquadFilter', {}, 'amp'];
1555
+ nodes.filter = context.createBiquadFilter();
1556
+ nodes.oscillator.connect(nodes.filter);
1557
+ nodes.filter.connect(nodes.amp);
1477
1558
  }
1478
1559
  else {
1479
- params.oscillator = ['Oscillator', {}, 'amp'];
1560
+ nodes.oscillator.connect(nodes.amp);
1480
1561
  }
1481
- params.amp = ['Gain', { gain: 0.0 }, 'target'];
1482
- params.target = ['Gain', { gain: 1.0 }, 'master'];
1483
1562
  if (this.reverb.time > 0.0 && this.reverb.mix > 0.0) {
1484
- params.amp.push('convolver');
1485
- params.convolver = ['Convolver', { buffer: impulseResponse({ time: this.reverb.time }) }, 'convolverDepth'];
1486
- params.convolverDepth = ['Gain', { gain: 1.0 }, 'master'];
1487
- }
1488
- if (this.delay.time > 0.0 && this.delay.mix > 0.0) {
1489
- params.amp.push('delay');
1490
- params.delay = ['Delay', {}, 'delayDepth', 'delayFeedback'];
1491
- params.delayDepth = ['Gain', { gain: 1.0 }, 'master'];
1492
- params.delayFeedback = ['Gain', { gain: this.delay.feedback }, 'delay'];
1563
+ nodes.convolver = context.createConvolver();
1564
+ nodes.convolver.buffer = impulseResponse({ time: this.reverb.time });
1565
+ nodes.convolverDepth = context.createGain();
1566
+ nodes.convolverDepth.gain.value = 1.0;
1567
+ nodes.amp.connect(nodes.convolver);
1568
+ nodes.convolver.connect(nodes.convolverDepth);
1569
+ nodes.convolverDepth.connect(master);
1493
1570
  }
1494
1571
  if (this.oscillator.LFO) {
1495
- params.oscillatorLFO = ['Oscillator', {}, 'oscillatorLFODepth'];
1496
- params.oscillatorLFODepth = ['Gain', {}, 'oscillator.frequency'];
1497
- }
1498
- if (this.filter.LFO) {
1499
- params.filterLFO = ['Oscillator', {}, 'filterLFODepth'];
1500
- params.filterLFODepth = ['Gain', {}, 'filter.frequency'];
1572
+ nodes.oscillatorLFO = context.createOscillator();
1573
+ nodes.oscillatorLFODepth = context.createGain();
1574
+ nodes.oscillatorLFO.connect(nodes.oscillatorLFODepth);
1575
+ nodes.oscillatorLFODepth.connect(nodes.oscillator.frequency);
1501
1576
  }
1502
- if (this.amp.LFO) {
1503
- params.ampLFO = ['Oscillator', {}, 'ampLFODepth'];
1504
- params.ampLFODepth = ['Gain', {}, 'amp.gain'];
1505
- }
1506
- const nodes = Audio.connect(params);
1507
1577
  nodes.oscillator.type = this.oscillator.type;
1508
1578
  nodes.oscillator.frequency.value = clamp(frequency, 10.0, 5000.0);
1509
- if (this.filter.type && this.filter.cutoff) {
1579
+ if (this.filter.type && this.filter.cutoff && nodes.filter) {
1510
1580
  nodes.filter.type = this.filter.type;
1511
1581
  nodes.filter.frequency.value = this.filter.cutoff;
1512
1582
  }
@@ -1514,39 +1584,17 @@
1514
1584
  nodes.target.gain.value *= (1.0 - this.reverb.mix);
1515
1585
  nodes.convolverDepth.gain.value *= this.reverb.mix;
1516
1586
  }
1517
- if (this.delay.time > 0.0 && this.delay.mix > 0.0) {
1518
- console.log(this.delay.time / 1000);
1519
- nodes.delay.delayTime.value = this.delay.time / 1000;
1520
- nodes.target.gain.value *= (1.0 - this.delay.mix);
1521
- nodes.delayDepth.gain.value *= this.delay.mix;
1522
- }
1523
1587
  {
1524
- if (this.oscillator.LFO) {
1588
+ if (this.oscillator.LFO && nodes.oscillatorLFO && nodes.oscillatorLFODepth) {
1525
1589
  nodes.oscillatorLFODepth.gain.value = frequency * (Math.pow(2.0, this.oscillator.LFO.amount / 12.0) - 1.0);
1526
1590
  nodes.oscillatorLFO.type = this.oscillator.LFO.type;
1527
1591
  nodes.oscillatorLFO.frequency.value = this.oscillator.LFO.rate;
1528
1592
  nodes.oscillatorLFO.start(start);
1529
1593
  }
1530
- if (this.filter.LFO) {
1531
- nodes.filterLFODepth.gain.value = frequency * (Math.pow(2.0, this.filter.LFO.amount / 12.0) - 1.0);
1532
- nodes.filterLFO.type = this.filter.LFO.type;
1533
- nodes.filterLFO.frequency.value = this.filter.LFO.rate;
1534
- nodes.filterLFO.start(start);
1535
- }
1536
- if (this.amp.LFO) {
1537
- nodes.ampLFODepth.gain.value = this.amp.LFO.amount;
1538
- nodes.ampLFO.type = this.amp.LFO.type;
1539
- nodes.ampLFO.frequency.value = this.amp.LFO.rate;
1540
- nodes.ampLFO.start(start);
1541
- }
1542
1594
  if (this.oscillator.envelope) {
1543
1595
  const amount = frequency * (Math.pow(2.0, this.oscillator.envelope.amount / 12.0) - 1.0);
1544
1596
  startEnvelope(nodes.oscillator.frequency, frequency, amount, this.oscillator.envelope.ADSR);
1545
1597
  }
1546
- if (this.filter.envelope) {
1547
- const amount = this.filter.cutoff * (Math.pow(2.0, this.filter.envelope.amount / 12.0) - 1.0);
1548
- startEnvelope(nodes.filter.frequency, this.filter.cutoff, amount, this.filter.envelope.ADSR);
1549
- }
1550
1598
  if (this.amp.envelope) {
1551
1599
  startEnvelope(nodes.amp.gain, 0.0, this.amp.envelope.amount, this.amp.envelope.ADSR);
1552
1600
  }
@@ -1556,7 +1604,7 @@
1556
1604
  release.call(this);
1557
1605
  }
1558
1606
  function release() {
1559
- duration = duration !== null && duration !== void 0 ? duration : (Audio.context.currentTime - start);
1607
+ duration = duration !== null && duration !== void 0 ? duration : (context.currentTime - start);
1560
1608
  if (this.amp.envelope) {
1561
1609
  const ADSR = this.amp.envelope.ADSR;
1562
1610
  const adsr = [ADSR[0] / 1000, ADSR[1] / 1000, ADSR[2], ADSR[3] / 1000];
@@ -1566,20 +1614,13 @@
1566
1614
  else {
1567
1615
  stop = start + duration;
1568
1616
  }
1569
- if (this.oscillator.LFO) {
1617
+ if (nodes.oscillatorLFO) {
1570
1618
  nodes.oscillatorLFO.stop(stop);
1571
1619
  }
1572
- if (this.amp.LFO) {
1573
- nodes.ampLFO.stop(stop);
1574
- }
1575
1620
  if (this.oscillator.envelope) {
1576
1621
  const amount = frequency * (Math.pow(2.0, this.oscillator.envelope.amount / 12.0) - 1.0);
1577
1622
  stopEnvelope(nodes.oscillator.frequency, frequency, amount, this.oscillator.envelope.ADSR);
1578
1623
  }
1579
- if (this.filter.envelope) {
1580
- const amount = this.filter.cutoff * (Math.pow(2.0, this.filter.envelope.amount / 12.0) - 1.0);
1581
- stopEnvelope(nodes.filter.frequency, this.filter.cutoff, amount, this.filter.envelope.ADSR);
1582
- }
1583
1624
  if (this.amp.envelope) {
1584
1625
  stopEnvelope(nodes.amp.gain, 0.0, this.amp.envelope.amount, this.amp.envelope.ADSR);
1585
1626
  }
@@ -1625,8 +1666,8 @@
1625
1666
  };
1626
1667
  Synthesizer.initialize();
1627
1668
  function impulseResponse({ time, decay = 2.0 }) {
1628
- const length = Audio.context.sampleRate * time / 1000;
1629
- const impulse = Audio.context.createBuffer(2, length, Audio.context.sampleRate);
1669
+ const length = context.sampleRate * time / 1000;
1670
+ const impulse = context.createBuffer(2, length, context.sampleRate);
1630
1671
  const ch0 = impulse.getChannelData(0);
1631
1672
  const ch1 = impulse.getChannelData(1);
1632
1673
  for (let i = 0; i < length; i++) {
@@ -1638,8 +1679,9 @@
1638
1679
 
1639
1680
  const basics = {
1640
1681
  Screen,
1641
- UserEvent,
1682
+ PointerEvent,
1642
1683
  ResizeEvent,
1684
+ KeyboardEvent,
1643
1685
  ModalFrame,
1644
1686
  ModalContent,
1645
1687
  AccordionFrame,
@@ -1652,12 +1694,11 @@
1652
1694
  InputFrame,
1653
1695
  DragFrame,
1654
1696
  DragTarget,
1655
- TouchStick,
1656
- TouchDPad,
1657
- TouchButton,
1697
+ AnalogStick,
1698
+ DirectionalPad,
1658
1699
  };
1659
1700
  const audio = {
1660
- synthesizer
1701
+ synthesizer, load
1661
1702
  };
1662
1703
  const xnew = Object.assign(xnew$1, {
1663
1704
  basics,