@pie-element/hotspot 9.3.4-next.3 → 10.0.0-beta.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.
Files changed (103) hide show
  1. package/configure/lib/DeleteWidget.js +30 -43
  2. package/configure/lib/DeleteWidget.js.map +1 -1
  3. package/configure/lib/button.js +26 -45
  4. package/configure/lib/button.js.map +1 -1
  5. package/configure/lib/buttons/circle.js +20 -27
  6. package/configure/lib/buttons/circle.js.map +1 -1
  7. package/configure/lib/buttons/polygon.js +26 -33
  8. package/configure/lib/buttons/polygon.js.map +1 -1
  9. package/configure/lib/buttons/rectangle.js +26 -33
  10. package/configure/lib/buttons/rectangle.js.map +1 -1
  11. package/configure/lib/defaults.js +2 -3
  12. package/configure/lib/defaults.js.map +1 -1
  13. package/configure/lib/hotspot-circle.js +132 -198
  14. package/configure/lib/hotspot-circle.js.map +1 -1
  15. package/configure/lib/hotspot-container.js +250 -355
  16. package/configure/lib/hotspot-container.js.map +1 -1
  17. package/configure/lib/hotspot-drawable.js +360 -472
  18. package/configure/lib/hotspot-drawable.js.map +1 -1
  19. package/configure/lib/hotspot-palette.js +92 -139
  20. package/configure/lib/hotspot-palette.js.map +1 -1
  21. package/configure/lib/hotspot-polygon.js +212 -317
  22. package/configure/lib/hotspot-polygon.js.map +1 -1
  23. package/configure/lib/hotspot-rectangle.js +128 -192
  24. package/configure/lib/hotspot-rectangle.js.map +1 -1
  25. package/configure/lib/icons.js.map +1 -1
  26. package/configure/lib/image-konva.js +46 -86
  27. package/configure/lib/image-konva.js.map +1 -1
  28. package/configure/lib/index.js +162 -222
  29. package/configure/lib/index.js.map +1 -1
  30. package/configure/lib/root.js +301 -393
  31. package/configure/lib/root.js.map +1 -1
  32. package/configure/lib/shapes/circle.js +69 -101
  33. package/configure/lib/shapes/circle.js.map +1 -1
  34. package/configure/lib/shapes/index.js +4 -12
  35. package/configure/lib/shapes/index.js.map +1 -1
  36. package/configure/lib/shapes/polygon.js +64 -96
  37. package/configure/lib/shapes/polygon.js.map +1 -1
  38. package/configure/lib/shapes/rectagle.js +69 -101
  39. package/configure/lib/shapes/rectagle.js.map +1 -1
  40. package/configure/lib/shapes/utils.js +2 -8
  41. package/configure/lib/shapes/utils.js.map +1 -1
  42. package/configure/lib/upload-control.js +25 -52
  43. package/configure/lib/upload-control.js.map +1 -1
  44. package/configure/lib/utils.js +84 -137
  45. package/configure/lib/utils.js.map +1 -1
  46. package/configure/package.json +11 -10
  47. package/configure/src/__tests__/hotspot-container.test.js +50 -19
  48. package/configure/src/__tests__/hotspot-drawable.test.js +55 -34
  49. package/configure/src/__tests__/index.test.js +167 -5
  50. package/configure/src/__tests__/root.test.js +89 -63
  51. package/configure/src/button.jsx +12 -20
  52. package/configure/src/hotspot-circle.jsx +5 -18
  53. package/configure/src/hotspot-container.jsx +82 -98
  54. package/configure/src/hotspot-drawable.jsx +43 -45
  55. package/configure/src/hotspot-palette.jsx +45 -37
  56. package/configure/src/hotspot-polygon.jsx +4 -20
  57. package/configure/src/hotspot-rectangle.jsx +4 -17
  58. package/configure/src/index.js +12 -2
  59. package/configure/src/root.jsx +85 -79
  60. package/configure/src/upload-control.jsx +6 -16
  61. package/controller/lib/defaults.js +2 -3
  62. package/controller/lib/defaults.js.map +1 -1
  63. package/controller/lib/index.js +151 -205
  64. package/controller/lib/index.js.map +1 -1
  65. package/controller/lib/utils.js +14 -34
  66. package/controller/lib/utils.js.map +1 -1
  67. package/controller/package.json +2 -2
  68. package/lib/hotspot/circle.js +110 -169
  69. package/lib/hotspot/circle.js.map +1 -1
  70. package/lib/hotspot/container.js +174 -260
  71. package/lib/hotspot/container.js.map +1 -1
  72. package/lib/hotspot/icons.js.map +1 -1
  73. package/lib/hotspot/image-konva-tooltip.js +65 -112
  74. package/lib/hotspot/image-konva-tooltip.js.map +1 -1
  75. package/lib/hotspot/index.js +135 -198
  76. package/lib/hotspot/index.js.map +1 -1
  77. package/lib/hotspot/polygon.js +150 -214
  78. package/lib/hotspot/polygon.js.map +1 -1
  79. package/lib/hotspot/rectangle.js +128 -185
  80. package/lib/hotspot/rectangle.js.map +1 -1
  81. package/lib/index.js +187 -256
  82. package/lib/index.js.map +1 -1
  83. package/lib/session-updater.js +12 -18
  84. package/lib/session-updater.js.map +1 -1
  85. package/package.json +14 -11
  86. package/src/__tests__/container.test.jsx +27 -175
  87. package/src/__tests__/index.test.js +70 -30
  88. package/src/hotspot/circle.jsx +2 -13
  89. package/src/hotspot/container.jsx +35 -50
  90. package/src/hotspot/index.jsx +16 -28
  91. package/src/hotspot/polygon.jsx +4 -13
  92. package/src/hotspot/rectangle.jsx +5 -15
  93. package/src/index.js +21 -12
  94. package/configure/src/__tests__/DeleteWidget.test.js +0 -64
  95. package/configure/src/__tests__/__snapshots__/hotspot-container.test.js.snap +0 -192
  96. package/configure/src/__tests__/__snapshots__/hotspot-drawable.test.js.snap +0 -562
  97. package/configure/src/__tests__/__snapshots__/root.test.js.snap +0 -469
  98. package/src/__tests__/__snapshots__/container.test.jsx.snap +0 -264
  99. package/src/__tests__/__snapshots__/index.test.js.snap +0 -81
  100. package/src/__tests__/__snapshots__/polygon.test.jsx.snap +0 -192
  101. package/src/__tests__/__snapshots__/rectangle.test.jsx.snap +0 -127
  102. package/src/__tests__/polygon.test.jsx +0 -230
  103. package/src/__tests__/rectangle.test.jsx +0 -232
package/lib/index.js CHANGED
@@ -1,282 +1,213 @@
1
1
  "use strict";
2
2
 
3
3
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
-
5
4
  Object.defineProperty(exports, "__esModule", {
6
5
  value: true
7
6
  });
8
- exports["default"] = void 0;
9
-
10
- var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
11
-
12
- var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
13
-
14
- var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
15
-
16
- var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
17
-
18
- var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
19
-
20
- var _wrapNativeSuper2 = _interopRequireDefault(require("@babel/runtime/helpers/wrapNativeSuper"));
21
-
7
+ exports.default = void 0;
22
8
  var _react = _interopRequireDefault(require("react"));
23
-
24
- var _reactDom = _interopRequireDefault(require("react-dom"));
25
-
9
+ var _client = require("react-dom/client");
26
10
  var _mathRendering = require("@pie-lib/math-rendering");
27
-
28
11
  var _renderUi = require("@pie-lib/render-ui");
29
-
30
12
  var _piePlayerEvents = require("@pie-framework/pie-player-events");
31
-
32
13
  var _hotspot = _interopRequireDefault(require("./hotspot"));
33
-
34
14
  var _sessionUpdater = require("./session-updater");
35
-
36
- function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; }
37
-
38
- function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
39
-
40
- var Hotspot = /*#__PURE__*/function (_HTMLElement) {
41
- (0, _inherits2["default"])(Hotspot, _HTMLElement);
42
-
43
- var _super = _createSuper(Hotspot);
44
-
45
- function Hotspot() {
46
- var _this;
47
-
48
- (0, _classCallCheck2["default"])(this, Hotspot);
49
- _this = _super.call(this);
50
- _this._model = null;
51
- _this._session = null;
52
- _this._audioInitialized = false;
53
- _this.audioComplete = false;
54
- return _this;
15
+ class Hotspot extends HTMLElement {
16
+ constructor() {
17
+ super();
18
+ this._model = null;
19
+ this._session = null;
20
+ this._audioInitialized = false;
21
+ this.audioComplete = false;
22
+ this._root = null;
55
23
  }
56
-
57
- (0, _createClass2["default"])(Hotspot, [{
58
- key: "model",
59
- set: function set(m) {
60
- this._model = m;
61
- this.dispatchEvent(new _piePlayerEvents.ModelSetEvent(this.tagName.toLowerCase(), this.isComplete(), !!this._model));
62
- this._audioInitialized = false;
63
-
64
- this._render();
24
+ set model(m) {
25
+ this._model = m;
26
+ this.dispatchEvent(new _piePlayerEvents.ModelSetEvent(this.tagName.toLowerCase(), this.isComplete(), !!this._model));
27
+ this._audioInitialized = false;
28
+ this._render();
29
+ }
30
+ isComplete() {
31
+ if (!this._session || !this._session.answers) {
32
+ return false;
65
33
  }
66
- }, {
67
- key: "isComplete",
68
- value: function isComplete() {
69
- if (!this._session || !this._session.answers) {
70
- return false;
71
- }
72
-
73
- var _ref = this._model || {},
74
- autoplayAudioEnabled = _ref.autoplayAudioEnabled,
75
- completeAudioEnabled = _ref.completeAudioEnabled;
76
-
77
- var elementContext = this; // check audio completion if audio settings are enabled and audio actually exists
78
-
79
- if (autoplayAudioEnabled && completeAudioEnabled && !this.audioComplete) {
80
- if (elementContext) {
81
- var audio = elementContext.querySelector('audio');
82
- var isInsidePrompt = audio && audio.closest('#preview-prompt'); // only require audio completion if audio exists and is inside the prompt
83
-
84
- if (audio && isInsidePrompt) {
85
- return false;
86
- }
34
+ const {
35
+ autoplayAudioEnabled,
36
+ completeAudioEnabled
37
+ } = this._model || {};
38
+ const elementContext = this;
39
+
40
+ // check audio completion if audio settings are enabled and audio actually exists
41
+ if (autoplayAudioEnabled && completeAudioEnabled && !this.audioComplete) {
42
+ if (elementContext) {
43
+ const audio = elementContext.querySelector('audio');
44
+ const isInsidePrompt = audio && audio.closest('#preview-prompt');
45
+
46
+ // only require audio completion if audio exists and is inside the prompt
47
+ if (audio && isInsidePrompt) {
48
+ return false;
87
49
  }
88
50
  }
89
-
90
- if (!Array.isArray(this._session.answers)) {
91
- return false;
92
- }
93
-
94
- return this._session.answers.length > 0;
95
- }
96
- }, {
97
- key: "session",
98
- get: function get() {
99
- return this._session;
100
- },
101
- set: function set(s) {
102
- if (s && !s.answers) {
103
- s.answers = [];
104
- }
105
-
106
- this._session = s;
107
-
108
- this._render();
109
51
  }
110
- }, {
111
- key: "onSelectChoice",
112
- value: function onSelectChoice(data) {
113
- (0, _sessionUpdater.updateSessionValue)(this._session, this._model, data);
114
- this.dispatchEvent(new _piePlayerEvents.SessionChangedEvent(this.tagName.toLowerCase(), this.isComplete()));
115
-
116
- this._render();
52
+ if (!Array.isArray(this._session.answers)) {
53
+ return false;
117
54
  }
118
- }, {
119
- key: "_createAudioInfoToast",
120
- value: function _createAudioInfoToast() {
121
- var info = document.createElement('div');
122
- info.id = 'play-audio-info';
123
- Object.assign(info.style, {
124
- position: 'absolute',
125
- top: 0,
126
- width: '100%',
127
- height: '100%',
128
- display: 'flex',
129
- justifyContent: 'center',
130
- alignItems: 'center',
131
- background: 'white',
132
- zIndex: '1000',
133
- cursor: 'pointer'
134
- });
135
- var img = document.createElement('img');
136
- img.src = _renderUi.EnableAudioAutoplayImage;
137
- img.alt = 'Click anywhere to enable audio autoplay';
138
- img.width = 500;
139
- img.height = 300;
140
- info.appendChild(img);
141
- return info;
55
+ return this._session.answers.length > 0;
56
+ }
57
+ set session(s) {
58
+ if (s && !s.answers) {
59
+ s.answers = [];
142
60
  }
143
- }, {
144
- key: "connectedCallback",
145
- value: function connectedCallback() {
146
- var _this2 = this;
147
-
148
- this._render(); // Observation: audio in Chrome will have the autoplay attribute,
149
- // while other browsers will not have the autoplay attribute and will need a user interaction to play the audio
150
- // This workaround fixes the issue of audio being cached and played on any user interaction in Safari and Firefox
151
-
152
-
153
- var observer = new MutationObserver(function (mutationsList, observer) {
154
- mutationsList.forEach(function (mutation) {
155
- if (mutation.type === 'childList') {
156
- if (_this2._audioInitialized) return;
157
-
158
- var audio = _this2.querySelector('audio');
159
-
160
- var isInsidePrompt = audio && audio.closest('#preview-prompt');
161
- if (!_this2._model) return;
162
- if (!_this2._model.autoplayAudioEnabled) return;
163
- if (audio && !isInsidePrompt) return;
164
- if (!audio) return;
165
-
166
- var info = _this2._createAudioInfoToast();
167
-
168
- var container = _this2.querySelector('#main-container');
169
-
170
- var enableAudio = function enableAudio() {
171
- if (_this2.querySelector('#play-audio-info')) {
172
- audio.play();
173
- container.removeChild(info);
174
- }
175
-
61
+ this._session = s;
62
+ this._render();
63
+ }
64
+ get session() {
65
+ return this._session;
66
+ }
67
+ onSelectChoice(data) {
68
+ (0, _sessionUpdater.updateSessionValue)(this._session, this._model, data);
69
+ this.dispatchEvent(new _piePlayerEvents.SessionChangedEvent(this.tagName.toLowerCase(), this.isComplete()));
70
+ this._render();
71
+ }
72
+ _createAudioInfoToast() {
73
+ const info = document.createElement('div');
74
+ info.id = 'play-audio-info';
75
+ Object.assign(info.style, {
76
+ position: 'absolute',
77
+ top: 0,
78
+ width: '100%',
79
+ height: '100%',
80
+ display: 'flex',
81
+ justifyContent: 'center',
82
+ alignItems: 'center',
83
+ background: 'white',
84
+ zIndex: '1000',
85
+ cursor: 'pointer'
86
+ });
87
+ const img = document.createElement('img');
88
+ img.src = _renderUi.EnableAudioAutoplayImage;
89
+ img.alt = 'Click anywhere to enable audio autoplay';
90
+ img.width = 500;
91
+ img.height = 300;
92
+ info.appendChild(img);
93
+ return info;
94
+ }
95
+ connectedCallback() {
96
+ this._render();
97
+
98
+ // Observation: audio in Chrome will have the autoplay attribute,
99
+ // while other browsers will not have the autoplay attribute and will need a user interaction to play the audio
100
+ // This workaround fixes the issue of audio being cached and played on any user interaction in Safari and Firefox
101
+ const observer = new MutationObserver((mutationsList, observer) => {
102
+ mutationsList.forEach(mutation => {
103
+ if (mutation.type === 'childList') {
104
+ if (this._audioInitialized) return;
105
+ const audio = this.querySelector('audio');
106
+ const isInsidePrompt = audio && audio.closest('#preview-prompt');
107
+ if (!this._model) return;
108
+ if (!this._model.autoplayAudioEnabled) return;
109
+ if (audio && !isInsidePrompt) return;
110
+ if (!audio) return;
111
+ const info = this._createAudioInfoToast();
112
+ const container = this.querySelector('#main-container');
113
+ const enableAudio = () => {
114
+ if (this.querySelector('#play-audio-info')) {
115
+ audio.play();
116
+ container.removeChild(info);
117
+ }
118
+ document.removeEventListener('click', enableAudio);
119
+ };
120
+
121
+ // if the audio is paused, it means the user has not interacted with the page yet and the audio will not play
122
+ // FIX FOR SAFARI: play with a slight delay to check if autoplay was blocked
123
+ setTimeout(() => {
124
+ if (audio.paused && !this.querySelector('#play-audio-info')) {
125
+ // add info message as a toast to enable audio playback
126
+ container.appendChild(info);
127
+ document.addEventListener('click', enableAudio);
128
+ } else {
176
129
  document.removeEventListener('click', enableAudio);
177
- }; // if the audio is paused, it means the user has not interacted with the page yet and the audio will not play
178
- // FIX FOR SAFARI: play with a slight delay to check if autoplay was blocked
179
-
180
-
181
- setTimeout(function () {
182
- if (audio.paused && !_this2.querySelector('#play-audio-info')) {
183
- // add info message as a toast to enable audio playback
184
- container.appendChild(info);
185
- document.addEventListener('click', enableAudio);
186
- } else {
187
- document.removeEventListener('click', enableAudio);
188
- }
189
- }, 500); // we need to listen for the playing event to remove the toast in case the audio plays because of re-rendering
190
-
191
- var handlePlaying = function handlePlaying() {
192
- //timestamp when auto-played audio started playing
193
- (0, _sessionUpdater.updateSessionMetadata)(_this2._session, {
194
- audioStartTime: new Date().getTime()
195
- });
196
-
197
- var info = _this2.querySelector('#play-audio-info');
198
-
199
- if (info) {
200
- container.removeChild(info);
201
- }
202
-
203
- audio.removeEventListener('playing', handlePlaying);
204
- };
205
-
206
- audio.addEventListener('playing', handlePlaying); // we need to listen for the ended event to update the isComplete state
207
-
208
- var handleEnded = function handleEnded() {
209
- //timestamp when auto-played audio completed playing
210
- (0, _sessionUpdater.updateSessionMetadata)(_this2._session, {
211
- audioEndTime: new Date().getTime()
212
- });
213
- var _this2$_session = _this2._session,
214
- audioStartTime = _this2$_session.audioStartTime,
215
- audioEndTime = _this2$_session.audioEndTime,
216
- waitTime = _this2$_session.waitTime;
217
-
218
- if (!waitTime && audioStartTime && audioEndTime) {
219
- // waitTime is elapsed time the user waited for auto-played audio to finish
220
- _this2._session.waitTime = audioEndTime - audioStartTime;
221
- }
222
-
223
- _this2.audioComplete = true;
224
-
225
- _this2.dispatchEvent(new _piePlayerEvents.SessionChangedEvent(_this2.tagName.toLowerCase(), _this2.isComplete()));
226
-
227
- audio.removeEventListener('ended', handleEnded);
228
- };
229
-
230
- audio.addEventListener('ended', handleEnded); // store references to remove later
231
-
232
- _this2._audio = audio;
233
- _this2._handlePlaying = handlePlaying;
234
- _this2._handleEnded = handleEnded;
235
- _this2._enableAudio = enableAudio; // set to true to prevent multiple initializations
236
-
237
- _this2._audioInitialized = true;
238
- observer.disconnect();
239
- }
240
- });
130
+ }
131
+ }, 500);
132
+
133
+ // we need to listen for the playing event to remove the toast in case the audio plays because of re-rendering
134
+ const handlePlaying = () => {
135
+ //timestamp when auto-played audio started playing
136
+ (0, _sessionUpdater.updateSessionMetadata)(this._session, {
137
+ audioStartTime: new Date().getTime()
138
+ });
139
+ const info = this.querySelector('#play-audio-info');
140
+ if (info) {
141
+ container.removeChild(info);
142
+ }
143
+ audio.removeEventListener('playing', handlePlaying);
144
+ };
145
+ audio.addEventListener('playing', handlePlaying);
146
+
147
+ // we need to listen for the ended event to update the isComplete state
148
+ const handleEnded = () => {
149
+ //timestamp when auto-played audio completed playing
150
+ (0, _sessionUpdater.updateSessionMetadata)(this._session, {
151
+ audioEndTime: new Date().getTime()
152
+ });
153
+ let {
154
+ audioStartTime,
155
+ audioEndTime,
156
+ waitTime
157
+ } = this._session;
158
+ if (!waitTime && audioStartTime && audioEndTime) {
159
+ // waitTime is elapsed time the user waited for auto-played audio to finish
160
+ this._session.waitTime = audioEndTime - audioStartTime;
161
+ }
162
+ this.audioComplete = true;
163
+ this.dispatchEvent(new _piePlayerEvents.SessionChangedEvent(this.tagName.toLowerCase(), this.isComplete()));
164
+ audio.removeEventListener('ended', handleEnded);
165
+ };
166
+ audio.addEventListener('ended', handleEnded);
167
+
168
+ // store references to remove later
169
+ this._audio = audio;
170
+ this._handlePlaying = handlePlaying;
171
+ this._handleEnded = handleEnded;
172
+ this._enableAudio = enableAudio;
173
+ // set to true to prevent multiple initializations
174
+ this._audioInitialized = true;
175
+ observer.disconnect();
176
+ }
241
177
  });
242
- observer.observe(this, {
243
- childList: true,
244
- subtree: true
178
+ });
179
+ observer.observe(this, {
180
+ childList: true,
181
+ subtree: true
182
+ });
183
+ }
184
+ _render() {
185
+ if (this._model && this._session) {
186
+ const el = /*#__PURE__*/_react.default.createElement(_hotspot.default, {
187
+ model: this._model,
188
+ session: this._session,
189
+ onSelectChoice: this.onSelectChoice.bind(this)
245
190
  });
246
- }
247
- }, {
248
- key: "disconnectedCallback",
249
- value: function disconnectedCallback() {
250
- document.removeEventListener('click', this._enableAudio);
251
-
252
- if (this._audio) {
253
- this._audio.removeEventListener('playing', this._handlePlaying);
254
-
255
- this._audio.removeEventListener('ended', this._handleEnded);
256
-
257
- this._audio = null;
191
+ if (!this._root) {
192
+ this._root = (0, _client.createRoot)(this);
258
193
  }
194
+ this._root.render(el);
195
+ queueMicrotask(() => {
196
+ (0, _mathRendering.renderMath)(this);
197
+ });
259
198
  }
260
- }, {
261
- key: "_render",
262
- value: function _render() {
263
- var _this3 = this;
264
-
265
- if (this._model && this._session) {
266
- var el = /*#__PURE__*/_react["default"].createElement(_hotspot["default"], {
267
- model: this._model,
268
- session: this._session,
269
- onSelectChoice: this.onSelectChoice.bind(this)
270
- });
271
-
272
- _reactDom["default"].render(el, this, function () {
273
- (0, _mathRendering.renderMath)(_this3);
274
- });
275
- }
199
+ }
200
+ disconnectedCallback() {
201
+ document.removeEventListener('click', this._enableAudio);
202
+ if (this._audio) {
203
+ this._audio.removeEventListener('playing', this._handlePlaying);
204
+ this._audio.removeEventListener('ended', this._handleEnded);
205
+ this._audio = null;
276
206
  }
277
- }]);
278
- return Hotspot;
279
- }( /*#__PURE__*/(0, _wrapNativeSuper2["default"])(HTMLElement));
280
-
281
- exports["default"] = Hotspot;
207
+ if (this._root) {
208
+ this._root.unmount();
209
+ }
210
+ }
211
+ }
212
+ exports.default = Hotspot;
282
213
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.js"],"names":["Hotspot","_model","_session","_audioInitialized","audioComplete","m","dispatchEvent","ModelSetEvent","tagName","toLowerCase","isComplete","_render","answers","autoplayAudioEnabled","completeAudioEnabled","elementContext","audio","querySelector","isInsidePrompt","closest","Array","isArray","length","s","data","SessionChangedEvent","info","document","createElement","id","Object","assign","style","position","top","width","height","display","justifyContent","alignItems","background","zIndex","cursor","img","src","EnableAudioAutoplayImage","alt","appendChild","observer","MutationObserver","mutationsList","forEach","mutation","type","_createAudioInfoToast","container","enableAudio","play","removeChild","removeEventListener","setTimeout","paused","addEventListener","handlePlaying","audioStartTime","Date","getTime","handleEnded","audioEndTime","waitTime","_audio","_handlePlaying","_handleEnded","_enableAudio","disconnect","observe","childList","subtree","el","React","HotspotComponent","model","session","onSelectChoice","bind","ReactDOM","render","HTMLElement"],"mappings":"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","sourcesContent":["import React from 'react';\nimport ReactDOM from 'react-dom';\nimport { renderMath } from '@pie-lib/math-rendering';\nimport { EnableAudioAutoplayImage } from '@pie-lib/render-ui';\nimport { SessionChangedEvent, ModelSetEvent } from '@pie-framework/pie-player-events';\n\nimport HotspotComponent from './hotspot';\nimport { updateSessionValue, updateSessionMetadata } from './session-updater';\n\nexport default class Hotspot extends HTMLElement {\n constructor() {\n super();\n this._model = null;\n this._session = null;\n this._audioInitialized = false;\n this.audioComplete = false;\n }\n\n set model(m) {\n this._model = m;\n\n this.dispatchEvent(new ModelSetEvent(this.tagName.toLowerCase(), this.isComplete(), !!this._model));\n this._audioInitialized = false;\n this._render();\n }\n\n isComplete() {\n if (!this._session || !this._session.answers) {\n return false;\n }\n\n const { autoplayAudioEnabled, completeAudioEnabled } = this._model || {};\n const elementContext = this;\n\n // check audio completion if audio settings are enabled and audio actually exists\n if (autoplayAudioEnabled && completeAudioEnabled && !this.audioComplete) {\n if (elementContext) {\n const audio = elementContext.querySelector('audio');\n const isInsidePrompt = audio && audio.closest('#preview-prompt');\n\n // only require audio completion if audio exists and is inside the prompt\n if (audio && isInsidePrompt) {\n return false;\n }\n }\n }\n\n if (!Array.isArray(this._session.answers)) {\n return false;\n }\n\n return this._session.answers.length > 0;\n }\n\n set session(s) {\n if (s && !s.answers) {\n s.answers = [];\n }\n\n this._session = s;\n this._render();\n }\n\n get session() {\n return this._session;\n }\n\n onSelectChoice(data) {\n updateSessionValue(this._session, this._model, data);\n\n this.dispatchEvent(new SessionChangedEvent(this.tagName.toLowerCase(), this.isComplete()));\n\n this._render();\n }\n\n _createAudioInfoToast() {\n const info = document.createElement('div');\n info.id = 'play-audio-info';\n\n Object.assign(info.style, {\n position: 'absolute',\n top: 0,\n width: '100%',\n height: '100%',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n background: 'white',\n zIndex: '1000',\n cursor: 'pointer',\n });\n\n const img = document.createElement('img');\n img.src = EnableAudioAutoplayImage;\n img.alt = 'Click anywhere to enable audio autoplay';\n img.width = 500;\n img.height = 300;\n\n info.appendChild(img);\n return info;\n }\n\n connectedCallback() {\n this._render();\n\n // Observation: audio in Chrome will have the autoplay attribute,\n // while other browsers will not have the autoplay attribute and will need a user interaction to play the audio\n // This workaround fixes the issue of audio being cached and played on any user interaction in Safari and Firefox\n const observer = new MutationObserver((mutationsList, observer) => {\n mutationsList.forEach((mutation) => {\n if (mutation.type === 'childList') {\n if (this._audioInitialized) return;\n const audio = this.querySelector('audio');\n const isInsidePrompt = audio && audio.closest('#preview-prompt');\n\n if (!this._model) return;\n if (!this._model.autoplayAudioEnabled) return;\n if (audio && !isInsidePrompt) return;\n if (!audio) return;\n\n const info = this._createAudioInfoToast();\n const container = this.querySelector('#main-container');\n const enableAudio = () => {\n if (this.querySelector('#play-audio-info')) {\n audio.play();\n container.removeChild(info);\n }\n\n document.removeEventListener('click', enableAudio);\n };\n\n // if the audio is paused, it means the user has not interacted with the page yet and the audio will not play\n // FIX FOR SAFARI: play with a slight delay to check if autoplay was blocked\n setTimeout(() => {\n if (audio.paused && !this.querySelector('#play-audio-info')) {\n // add info message as a toast to enable audio playback\n container.appendChild(info);\n document.addEventListener('click', enableAudio);\n } else {\n document.removeEventListener('click', enableAudio);\n }\n }, 500);\n\n // we need to listen for the playing event to remove the toast in case the audio plays because of re-rendering\n const handlePlaying = () => {\n //timestamp when auto-played audio started playing\n updateSessionMetadata(this._session, { audioStartTime: new Date().getTime() });\n\n const info = this.querySelector('#play-audio-info');\n if (info) {\n container.removeChild(info);\n }\n\n audio.removeEventListener('playing', handlePlaying);\n };\n\n audio.addEventListener('playing', handlePlaying);\n\n // we need to listen for the ended event to update the isComplete state\n const handleEnded = () => {\n //timestamp when auto-played audio completed playing\n updateSessionMetadata(this._session, { audioEndTime: new Date().getTime() });\n\n let { audioStartTime, audioEndTime, waitTime } = this._session;\n if (!waitTime && audioStartTime && audioEndTime) {\n // waitTime is elapsed time the user waited for auto-played audio to finish\n this._session.waitTime = audioEndTime - audioStartTime;\n }\n\n this.audioComplete = true;\n this.dispatchEvent(new SessionChangedEvent(this.tagName.toLowerCase(), this.isComplete()));\n\n audio.removeEventListener('ended', handleEnded);\n };\n\n audio.addEventListener('ended', handleEnded);\n\n // store references to remove later\n this._audio = audio;\n this._handlePlaying = handlePlaying;\n this._handleEnded = handleEnded;\n this._enableAudio = enableAudio;\n // set to true to prevent multiple initializations\n this._audioInitialized = true;\n\n observer.disconnect();\n }\n });\n });\n\n observer.observe(this, { childList: true, subtree: true });\n }\n\n disconnectedCallback() {\n document.removeEventListener('click', this._enableAudio);\n\n if (this._audio) {\n this._audio.removeEventListener('playing', this._handlePlaying);\n this._audio.removeEventListener('ended', this._handleEnded);\n this._audio = null;\n }\n }\n\n _render() {\n if (this._model && this._session) {\n const el = React.createElement(HotspotComponent, {\n model: this._model,\n session: this._session,\n onSelectChoice: this.onSelectChoice.bind(this),\n });\n\n ReactDOM.render(el, this, () => {\n renderMath(this);\n });\n }\n }\n}\n"],"file":"index.js"}
1
+ {"version":3,"file":"index.js","names":["_react","_interopRequireDefault","require","_client","_mathRendering","_renderUi","_piePlayerEvents","_hotspot","_sessionUpdater","Hotspot","HTMLElement","constructor","_model","_session","_audioInitialized","audioComplete","_root","model","m","dispatchEvent","ModelSetEvent","tagName","toLowerCase","isComplete","_render","answers","autoplayAudioEnabled","completeAudioEnabled","elementContext","audio","querySelector","isInsidePrompt","closest","Array","isArray","length","session","s","onSelectChoice","data","updateSessionValue","SessionChangedEvent","_createAudioInfoToast","info","document","createElement","id","Object","assign","style","position","top","width","height","display","justifyContent","alignItems","background","zIndex","cursor","img","src","EnableAudioAutoplayImage","alt","appendChild","connectedCallback","observer","MutationObserver","mutationsList","forEach","mutation","type","container","enableAudio","play","removeChild","removeEventListener","setTimeout","paused","addEventListener","handlePlaying","updateSessionMetadata","audioStartTime","Date","getTime","handleEnded","audioEndTime","waitTime","_audio","_handlePlaying","_handleEnded","_enableAudio","disconnect","observe","childList","subtree","el","React","HotspotComponent","bind","createRoot","render","queueMicrotask","renderMath","disconnectedCallback","unmount","exports","default"],"sources":["../src/index.js"],"sourcesContent":["import React from 'react';\nimport { createRoot } from 'react-dom/client';\nimport { renderMath } from '@pie-lib/math-rendering';\nimport { EnableAudioAutoplayImage } from '@pie-lib/render-ui';\nimport { SessionChangedEvent, ModelSetEvent } from '@pie-framework/pie-player-events';\n\nimport HotspotComponent from './hotspot';\nimport { updateSessionValue, updateSessionMetadata } from './session-updater';\n\nexport default class Hotspot extends HTMLElement {\n constructor() {\n super();\n this._model = null;\n this._session = null;\n this._audioInitialized = false;\n this.audioComplete = false;\n this._root = null;\n }\n\n set model(m) {\n this._model = m;\n\n this.dispatchEvent(new ModelSetEvent(this.tagName.toLowerCase(), this.isComplete(), !!this._model));\n this._audioInitialized = false;\n this._render();\n }\n\n isComplete() {\n if (!this._session || !this._session.answers) {\n return false;\n }\n\n const { autoplayAudioEnabled, completeAudioEnabled } = this._model || {};\n const elementContext = this;\n\n // check audio completion if audio settings are enabled and audio actually exists\n if (autoplayAudioEnabled && completeAudioEnabled && !this.audioComplete) {\n if (elementContext) {\n const audio = elementContext.querySelector('audio');\n const isInsidePrompt = audio && audio.closest('#preview-prompt');\n\n // only require audio completion if audio exists and is inside the prompt\n if (audio && isInsidePrompt) {\n return false;\n }\n }\n }\n\n if (!Array.isArray(this._session.answers)) {\n return false;\n }\n\n return this._session.answers.length > 0;\n }\n\n set session(s) {\n if (s && !s.answers) {\n s.answers = [];\n }\n\n this._session = s;\n this._render();\n }\n\n get session() {\n return this._session;\n }\n\n onSelectChoice(data) {\n updateSessionValue(this._session, this._model, data);\n\n this.dispatchEvent(new SessionChangedEvent(this.tagName.toLowerCase(), this.isComplete()));\n\n this._render();\n }\n\n _createAudioInfoToast() {\n const info = document.createElement('div');\n info.id = 'play-audio-info';\n\n Object.assign(info.style, {\n position: 'absolute',\n top: 0,\n width: '100%',\n height: '100%',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n background: 'white',\n zIndex: '1000',\n cursor: 'pointer',\n });\n\n const img = document.createElement('img');\n img.src = EnableAudioAutoplayImage;\n img.alt = 'Click anywhere to enable audio autoplay';\n img.width = 500;\n img.height = 300;\n\n info.appendChild(img);\n return info;\n }\n\n connectedCallback() {\n this._render();\n\n // Observation: audio in Chrome will have the autoplay attribute,\n // while other browsers will not have the autoplay attribute and will need a user interaction to play the audio\n // This workaround fixes the issue of audio being cached and played on any user interaction in Safari and Firefox\n const observer = new MutationObserver((mutationsList, observer) => {\n mutationsList.forEach((mutation) => {\n if (mutation.type === 'childList') {\n if (this._audioInitialized) return;\n const audio = this.querySelector('audio');\n const isInsidePrompt = audio && audio.closest('#preview-prompt');\n\n if (!this._model) return;\n if (!this._model.autoplayAudioEnabled) return;\n if (audio && !isInsidePrompt) return;\n if (!audio) return;\n\n const info = this._createAudioInfoToast();\n const container = this.querySelector('#main-container');\n const enableAudio = () => {\n if (this.querySelector('#play-audio-info')) {\n audio.play();\n container.removeChild(info);\n }\n\n document.removeEventListener('click', enableAudio);\n };\n\n // if the audio is paused, it means the user has not interacted with the page yet and the audio will not play\n // FIX FOR SAFARI: play with a slight delay to check if autoplay was blocked\n setTimeout(() => {\n if (audio.paused && !this.querySelector('#play-audio-info')) {\n // add info message as a toast to enable audio playback\n container.appendChild(info);\n document.addEventListener('click', enableAudio);\n } else {\n document.removeEventListener('click', enableAudio);\n }\n }, 500);\n\n // we need to listen for the playing event to remove the toast in case the audio plays because of re-rendering\n const handlePlaying = () => {\n //timestamp when auto-played audio started playing\n updateSessionMetadata(this._session, { audioStartTime: new Date().getTime() });\n\n const info = this.querySelector('#play-audio-info');\n if (info) {\n container.removeChild(info);\n }\n\n audio.removeEventListener('playing', handlePlaying);\n };\n\n audio.addEventListener('playing', handlePlaying);\n\n // we need to listen for the ended event to update the isComplete state\n const handleEnded = () => {\n //timestamp when auto-played audio completed playing\n updateSessionMetadata(this._session, { audioEndTime: new Date().getTime() });\n\n let { audioStartTime, audioEndTime, waitTime } = this._session;\n if (!waitTime && audioStartTime && audioEndTime) {\n // waitTime is elapsed time the user waited for auto-played audio to finish\n this._session.waitTime = audioEndTime - audioStartTime;\n }\n\n this.audioComplete = true;\n this.dispatchEvent(new SessionChangedEvent(this.tagName.toLowerCase(), this.isComplete()));\n\n audio.removeEventListener('ended', handleEnded);\n };\n\n audio.addEventListener('ended', handleEnded);\n\n // store references to remove later\n this._audio = audio;\n this._handlePlaying = handlePlaying;\n this._handleEnded = handleEnded;\n this._enableAudio = enableAudio;\n // set to true to prevent multiple initializations\n this._audioInitialized = true;\n\n observer.disconnect();\n }\n });\n });\n\n observer.observe(this, { childList: true, subtree: true });\n }\n\n _render() {\n if (this._model && this._session) {\n const el = React.createElement(HotspotComponent, {\n model: this._model,\n session: this._session,\n onSelectChoice: this.onSelectChoice.bind(this),\n });\n\n if (!this._root) {\n this._root = createRoot(this);\n }\n this._root.render(el);\n queueMicrotask(() => {\n renderMath(this);\n });\n }\n }\n\n disconnectedCallback() {\n document.removeEventListener('click', this._enableAudio);\n\n if (this._audio) {\n this._audio.removeEventListener('playing', this._handlePlaying);\n this._audio.removeEventListener('ended', this._handleEnded);\n this._audio = null;\n }\n\n if (this._root) {\n this._root.unmount();\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -5,39 +5,33 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.updateSessionMetadata = updateSessionMetadata;
7
7
  exports.updateSessionValue = updateSessionValue;
8
-
9
8
  function updateSessionValue(session, model, data) {
10
- var id = data.id,
11
- selected = data.selected;
12
-
13
- var _ref = model || {},
14
- multipleCorrect = _ref.multipleCorrect;
15
-
9
+ const {
10
+ id,
11
+ selected
12
+ } = data;
13
+ const {
14
+ multipleCorrect
15
+ } = model || {};
16
16
  session.answers = session.answers || [];
17
-
18
17
  if (!selected) {
19
- session.answers = session.answers.filter(function (answer) {
20
- return answer.id !== id;
21
- });
18
+ session.answers = session.answers.filter(answer => answer.id !== id);
22
19
  } else {
23
- var item = {
24
- id: id
20
+ const item = {
21
+ id
25
22
  };
26
-
27
23
  if (multipleCorrect) {
28
24
  session.answers.push(item);
29
25
  } else {
30
26
  session.answers = [item];
31
- } //update session metadata
32
-
27
+ }
33
28
 
29
+ //update session metadata
34
30
  session.selector = data.selector;
35
31
  }
36
32
  }
37
-
38
33
  function updateSessionMetadata(session, metadata) {
39
34
  session.audioStartTime = session.audioStartTime || metadata.audioStartTime; //timestamp when auto-played audio started playing
40
-
41
35
  session.audioEndTime = session.audioEndTime || metadata.audioEndTime; //timestamp when auto-played audio completed playing
42
36
 
43
37
  if (!session.waitTime && session.audioStartTime && session.audioEndTime) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/session-updater.js"],"names":["updateSessionValue","session","model","data","id","selected","multipleCorrect","answers","filter","answer","item","push","selector","updateSessionMetadata","metadata","audioStartTime","audioEndTime","waitTime"],"mappings":";;;;;;;;AAAO,SAASA,kBAAT,CAA4BC,OAA5B,EAAqCC,KAArC,EAA4CC,IAA5C,EAAkD;AACvD,MAAQC,EAAR,GAAyBD,IAAzB,CAAQC,EAAR;AAAA,MAAYC,QAAZ,GAAyBF,IAAzB,CAAYE,QAAZ;;AACA,aAA4BH,KAAK,IAAI,EAArC;AAAA,MAAQI,eAAR,QAAQA,eAAR;;AACAL,EAAAA,OAAO,CAACM,OAAR,GAAkBN,OAAO,CAACM,OAAR,IAAmB,EAArC;;AAEA,MAAI,CAACF,QAAL,EAAe;AACbJ,IAAAA,OAAO,CAACM,OAAR,GAAkBN,OAAO,CAACM,OAAR,CAAgBC,MAAhB,CAAuB,UAACC,MAAD;AAAA,aAAYA,MAAM,CAACL,EAAP,KAAcA,EAA1B;AAAA,KAAvB,CAAlB;AACD,GAFD,MAEO;AACL,QAAMM,IAAI,GAAG;AAAEN,MAAAA,EAAE,EAAFA;AAAF,KAAb;;AACA,QAAIE,eAAJ,EAAqB;AACnBL,MAAAA,OAAO,CAACM,OAAR,CAAgBI,IAAhB,CAAqBD,IAArB;AACD,KAFD,MAEO;AACLT,MAAAA,OAAO,CAACM,OAAR,GAAkB,CAACG,IAAD,CAAlB;AACD,KANI,CAQL;;;AACAT,IAAAA,OAAO,CAACW,QAAR,GAAmBT,IAAI,CAACS,QAAxB;AACD;AACF;;AAEM,SAASC,qBAAT,CAA+BZ,OAA/B,EAAwCa,QAAxC,EAAkD;AACvDb,EAAAA,OAAO,CAACc,cAAR,GAAyBd,OAAO,CAACc,cAAR,IAA0BD,QAAQ,CAACC,cAA5D,CADuD,CACqB;;AAC5Ed,EAAAA,OAAO,CAACe,YAAR,GAAuBf,OAAO,CAACe,YAAR,IAAwBF,QAAQ,CAACE,YAAxD,CAFuD,CAEe;;AAEtE,MAAI,CAACf,OAAO,CAACgB,QAAT,IAAqBhB,OAAO,CAACc,cAA7B,IAA+Cd,OAAO,CAACe,YAA3D,EAAyE;AACvE;AACAf,IAAAA,OAAO,CAACgB,QAAR,GAAmBhB,OAAO,CAACe,YAAR,GAAuBf,OAAO,CAACc,cAAlD;AACD;AACF","sourcesContent":["export function updateSessionValue(session, model, data) {\n const { id, selected } = data;\n const { multipleCorrect } = model || {};\n session.answers = session.answers || [];\n\n if (!selected) {\n session.answers = session.answers.filter((answer) => answer.id !== id);\n } else {\n const item = { id };\n if (multipleCorrect) {\n session.answers.push(item);\n } else {\n session.answers = [item];\n }\n\n //update session metadata\n session.selector = data.selector;\n }\n}\n\nexport function updateSessionMetadata(session, metadata) {\n session.audioStartTime = session.audioStartTime || metadata.audioStartTime; //timestamp when auto-played audio started playing\n session.audioEndTime = session.audioEndTime || metadata.audioEndTime; //timestamp when auto-played audio completed playing\n\n if (!session.waitTime && session.audioStartTime && session.audioEndTime) {\n // waitTime is elapsed time the user waited for auto-played audio to finish\n session.waitTime = session.audioEndTime - session.audioStartTime;\n }\n}\n"],"file":"session-updater.js"}
1
+ {"version":3,"file":"session-updater.js","names":["updateSessionValue","session","model","data","id","selected","multipleCorrect","answers","filter","answer","item","push","selector","updateSessionMetadata","metadata","audioStartTime","audioEndTime","waitTime"],"sources":["../src/session-updater.js"],"sourcesContent":["export function updateSessionValue(session, model, data) {\n const { id, selected } = data;\n const { multipleCorrect } = model || {};\n session.answers = session.answers || [];\n\n if (!selected) {\n session.answers = session.answers.filter((answer) => answer.id !== id);\n } else {\n const item = { id };\n if (multipleCorrect) {\n session.answers.push(item);\n } else {\n session.answers = [item];\n }\n\n //update session metadata\n session.selector = data.selector;\n }\n}\n\nexport function updateSessionMetadata(session, metadata) {\n session.audioStartTime = session.audioStartTime || metadata.audioStartTime; //timestamp when auto-played audio started playing\n session.audioEndTime = session.audioEndTime || metadata.audioEndTime; //timestamp when auto-played audio completed playing\n\n if (!session.waitTime && session.audioStartTime && session.audioEndTime) {\n // waitTime is elapsed time the user waited for auto-played audio to finish\n session.waitTime = session.audioEndTime - session.audioStartTime;\n }\n}\n"],"mappings":";;;;;;;AAAO,SAASA,kBAAkBA,CAACC,OAAO,EAAEC,KAAK,EAAEC,IAAI,EAAE;EACvD,MAAM;IAAEC,EAAE;IAAEC;EAAS,CAAC,GAAGF,IAAI;EAC7B,MAAM;IAAEG;EAAgB,CAAC,GAAGJ,KAAK,IAAI,CAAC,CAAC;EACvCD,OAAO,CAACM,OAAO,GAAGN,OAAO,CAACM,OAAO,IAAI,EAAE;EAEvC,IAAI,CAACF,QAAQ,EAAE;IACbJ,OAAO,CAACM,OAAO,GAAGN,OAAO,CAACM,OAAO,CAACC,MAAM,CAAEC,MAAM,IAAKA,MAAM,CAACL,EAAE,KAAKA,EAAE,CAAC;EACxE,CAAC,MAAM;IACL,MAAMM,IAAI,GAAG;MAAEN;IAAG,CAAC;IACnB,IAAIE,eAAe,EAAE;MACnBL,OAAO,CAACM,OAAO,CAACI,IAAI,CAACD,IAAI,CAAC;IAC5B,CAAC,MAAM;MACLT,OAAO,CAACM,OAAO,GAAG,CAACG,IAAI,CAAC;IAC1B;;IAEA;IACAT,OAAO,CAACW,QAAQ,GAAGT,IAAI,CAACS,QAAQ;EAClC;AACF;AAEO,SAASC,qBAAqBA,CAACZ,OAAO,EAAEa,QAAQ,EAAE;EACvDb,OAAO,CAACc,cAAc,GAAGd,OAAO,CAACc,cAAc,IAAID,QAAQ,CAACC,cAAc,CAAC,CAAC;EAC5Ed,OAAO,CAACe,YAAY,GAAGf,OAAO,CAACe,YAAY,IAAIF,QAAQ,CAACE,YAAY,CAAC,CAAC;;EAEtE,IAAI,CAACf,OAAO,CAACgB,QAAQ,IAAIhB,OAAO,CAACc,cAAc,IAAId,OAAO,CAACe,YAAY,EAAE;IACvE;IACAf,OAAO,CAACgB,QAAQ,GAAGhB,OAAO,CAACe,YAAY,GAAGf,OAAO,CAACc,cAAc;EAClE;AACF","ignoreList":[]}