@yoobic/yobi 7.7.41 → 7.7.42

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 (42) hide show
  1. package/dist/cjs/design-system.cjs.js +1 -1
  2. package/dist/cjs/{draggable-tags-helpers-b353ad65.js → draggable-tags-helpers-2b62a9fa.js} +2 -1
  3. package/dist/cjs/index.cjs.js +1 -1
  4. package/dist/cjs/loader.cjs.js +1 -1
  5. package/dist/cjs/yoo-form-categorize-words.cjs.entry.js +1 -1
  6. package/dist/cjs/yoo-form-choice_4.cjs.entry.js +1 -1
  7. package/dist/cjs/yoo-form-connect.cjs.entry.js +204 -323
  8. package/dist/cjs/yoo-form-image-tagging.cjs.entry.js +1 -1
  9. package/dist/cjs/yoo-form-missing-word.cjs.entry.js +1 -1
  10. package/dist/cjs/yoo-form-ranking.cjs.entry.js +1 -1
  11. package/dist/cjs/yoo-form-swipe-cards.cjs.entry.js +1 -1
  12. package/dist/collection/components/form/form-connect/form-connect.css +35 -33
  13. package/dist/collection/components/form/form-connect/form-connect.js +207 -375
  14. package/dist/collection/components/form/form-connect/types/index.js +1 -1
  15. package/dist/collection/utils/helpers/draggable-tags-helpers.js +2 -1
  16. package/dist/design-system/design-system.esm.js +1 -1
  17. package/dist/design-system/index.esm.js +1 -1
  18. package/dist/design-system/p-25ffc253.entry.js +1 -0
  19. package/dist/design-system/{p-d5b214f0.entry.js → p-37f863a9.entry.js} +1 -1
  20. package/dist/design-system/{p-adbb882f.entry.js → p-484eb9f2.entry.js} +1 -1
  21. package/dist/design-system/{p-f013d119.entry.js → p-82954c87.entry.js} +1 -1
  22. package/dist/design-system/{p-619154de.entry.js → p-a6091b4d.entry.js} +1 -1
  23. package/dist/design-system/p-f30db1be.js +1 -0
  24. package/dist/design-system/{p-800cb056.entry.js → p-f4317e29.entry.js} +1 -1
  25. package/dist/design-system/{p-47077c2f.entry.js → p-f61d59d7.entry.js} +1 -1
  26. package/dist/esm/design-system.js +1 -1
  27. package/dist/esm/{draggable-tags-helpers-e3b9cd11.js → draggable-tags-helpers-504b4b6d.js} +2 -1
  28. package/dist/esm/index.js +1 -1
  29. package/dist/esm/loader.js +1 -1
  30. package/dist/esm/yoo-form-categorize-words.entry.js +1 -1
  31. package/dist/esm/yoo-form-choice_4.entry.js +1 -1
  32. package/dist/esm/yoo-form-connect.entry.js +206 -325
  33. package/dist/esm/yoo-form-image-tagging.entry.js +1 -1
  34. package/dist/esm/yoo-form-missing-word.entry.js +1 -1
  35. package/dist/esm/yoo-form-ranking.entry.js +1 -1
  36. package/dist/esm/yoo-form-swipe-cards.entry.js +1 -1
  37. package/dist/types/components/form/form-connect/form-connect.d.ts +31 -48
  38. package/dist/types/components/form/form-connect/types/index.d.ts +4 -5
  39. package/dist/types/components.d.ts +0 -9
  40. package/package.json +1 -1
  41. package/dist/design-system/p-72fe82e5.js +0 -1
  42. package/dist/design-system/p-ab3cb64c.entry.js +0 -1
@@ -1,7 +1,8 @@
1
- import { Draggable, findParent, getCssColor, getUUID, gsapTo, isImageUrl, isNullOrUndefined, translateMulti } from '@shared/utils';
2
- import { Component, Element, Event, h, Prop, Watch } from '@stencil/core';
3
- import { setValueAndValidateInput } from '@utils';
4
- const ITEM_TYPES = ['draggable', 'connectable'];
1
+ import { Draggable, getUUID, gsapTo, isImageUrl, translateMulti } from '@shared/utils';
2
+ import { Component, Element, Event, h, Host, Prop, State, Watch } from '@stencil/core';
3
+ import { getAppContext, setValueAndValidateInput, showWarningAlert } from '@utils';
4
+ import { difference, isEqual, shuffle } from 'lodash-es';
5
+ import { CONNECT_TYPES } from './types';
5
6
  export class YooFormConnectComponent {
6
7
  constructor() {
7
8
  /**
@@ -20,391 +21,251 @@ export class YooFormConnectComponent {
20
21
  * true if component's parent slide is visible within a `yoo-form-dynamic`
21
22
  */
22
23
  this.isVisible = false;
23
- this.overlapThreshold = '65%';
24
- this.hoverColor = 'stable-light';
25
- this.subContainerElements = [];
26
24
  this.colors = ['warning', 'accent', 'royal', 'info', 'energized'];
27
- this.defaultColors = ['light-to-dark', 'dark-to-light'];
28
- this.animationDelay = this.animated ? 0.25 : 0;
29
- this.validationClasses = { valid: { icon: 'check', iconColor: 'success' }, invalid: { icon: 'cross', iconColor: 'danger' } };
30
25
  }
31
- onRequireChanged() {
32
- this.checkAnswersValidity();
26
+ onValuesChanged() {
27
+ showWarningAlert(this.host, !this.isGameMatchable, 'NOTALLPAIREDVALUES');
33
28
  }
34
- isValid() {
29
+ onValidityChanged() {
35
30
  this.validityChanged.emit(this.validity);
36
31
  }
37
- initValues() {
38
- this.dragEnded.emit(true);
39
- this.initItems();
40
- this.shuffleConnectValues();
41
- this.initUserAnswersArray();
42
- }
43
- onIsVisibleChanged(state) {
44
- if (state) {
45
- this.initConnect();
32
+ onValueChanged() {
33
+ if (!isEqual(this.value, this.userAnswers)) {
34
+ this.connectItems();
35
+ this.validateUserAnswers(this.value);
46
36
  }
47
37
  }
48
- onModalAnimationFinished(state) {
49
- if (state) {
50
- this.initConnect();
51
- }
38
+ initAnswerChanged() {
39
+ this.prepareGame();
52
40
  }
53
- componentWillLoad() {
54
- this.initValues();
55
- }
56
- componentDidLoad() {
57
- this.initConnect();
58
- this.preserveColors();
59
- this.updateDraggables();
60
- }
61
- componentDidUpdate() {
62
- if (this.livePreview) {
63
- this.initConnect();
64
- this.preserveColors();
65
- this.updateDraggables();
41
+ async onIsVisibleChanged(state) {
42
+ if (state) {
43
+ await this.scrollToRevealGame();
44
+ this.setScrollableHeight();
66
45
  }
67
46
  }
68
47
  get hasValues() {
69
- var _a;
70
- return !!(((_a = this.values) === null || _a === void 0 ? void 0 : _a.length) && (this.values[0].length || this.values[1].length));
48
+ var _a, _b, _c, _d;
49
+ return !!(((_b = (_a = this.values) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.length) || ((_d = (_c = this.values) === null || _c === void 0 ? void 0 : _c[1]) === null || _d === void 0 ? void 0 : _d.length));
71
50
  }
72
- get isConnectMatchable() {
73
- var _a, _b;
74
- return ((_a = this.draggables) === null || _a === void 0 ? void 0 : _a.length) === ((_b = this.connectables) === null || _b === void 0 ? void 0 : _b.length);
51
+ get isGameMatchable() {
52
+ var _a, _b, _c, _d;
53
+ return ((_b = (_a = this.values) === null || _a === void 0 ? void 0 : _a[0].filter(v => v)) === null || _b === void 0 ? void 0 : _b.length) === ((_d = (_c = this.values) === null || _c === void 0 ? void 0 : _c[1].filter(v => v)) === null || _d === void 0 ? void 0 : _d.length);
75
54
  }
76
- updateDraggables() {
77
- if (this.draggables) {
78
- this.draggables = this.draggables.map((draggable) => Object.assign(draggable, { draggableInstance: this.getDraggableInstance(draggable.id) }));
79
- }
55
+ get draggableElements() {
56
+ return Array.from(this.host.shadowRoot.querySelectorAll('.draggable') || []);
80
57
  }
81
- initConnect() {
82
- if (this.mainContainerElement) {
83
- this.getScrollableArea();
84
- }
58
+ get connectableElements() {
59
+ return Array.from(this.host.shadowRoot.querySelectorAll('.connectable') || []);
85
60
  }
86
- shuffleObjects(items) {
87
- if (items === null || items === void 0 ? void 0 : items.length) {
88
- const newItems = items;
89
- for (let i = items.length - 1; i > 0; i--) {
90
- const pos = Math.floor(Math.random() * (i + 1));
91
- const temp = newItems[i];
92
- newItems[i] = newItems[pos];
93
- newItems[pos] = temp;
94
- }
95
- return newItems;
96
- }
61
+ componentWillLoad() {
62
+ this.prepareGame();
97
63
  }
98
- shuffleConnectValues() {
64
+ componentWillUpdate() {
99
65
  var _a;
100
- if (((_a = this.values) === null || _a === void 0 ? void 0 : _a.length) && this.shuffled) {
101
- [this.draggables, this.connectables].forEach((items) => (items = this.shuffleObjects(items)));
66
+ if (!((_a = this.draggables) === null || _a === void 0 ? void 0 : _a.find(d => d === null || d === void 0 ? void 0 : d.draggableInstance))) {
67
+ this.initGame();
102
68
  }
103
69
  }
104
- getElement(id, container) {
105
- const containerElement = this.mainContainerElement.querySelector(`div.${container}-container`);
106
- return containerElement === null || containerElement === void 0 ? void 0 : containerElement.querySelector(`[id="${id}"]`);
70
+ componentDidLoad() {
71
+ this.initGame();
107
72
  }
108
- getConnectable(id) {
109
- var _a;
110
- return (_a = this.connectables) === null || _a === void 0 ? void 0 : _a.find((connectable) => connectable.id === id);
73
+ prepareGame() {
74
+ this.prepareItems();
75
+ this.connectItems();
76
+ this.shuffleItems();
111
77
  }
112
- getDraggable(id) {
113
- var _a;
114
- return (_a = this.draggables) === null || _a === void 0 ? void 0 : _a.find((draggable) => draggable.id === id);
115
- }
116
- getScrollableArea() {
117
- var _a, _b, _c;
118
- if (!this.readonly && this.isVisible && ((_a = this.values) === null || _a === void 0 ? void 0 : _a.length) && ((_b = this.subContainerElements) === null || _b === void 0 ? void 0 : _b.length)) {
119
- const arrAllElementLoaded = !!(this.subContainerElements[0].childElementCount === ((_c = this.values) === null || _c === void 0 ? void 0 : _c[0].length) && this.subContainerElements[1].childElementCount === this.values[1].length);
120
- if (arrAllElementLoaded) {
121
- setTimeout(() => {
122
- const absoluteConnectContainerHeight = this.subContainerElements[0].clientHeight;
123
- const pageContent = findParent(this.host, 'form');
124
- if (pageContent) {
125
- const pageContentBR = pageContent.getBoundingClientRect();
126
- const availableHeight = pageContentBR.height - (this.host.getBoundingClientRect().top - pageContentBR.top);
127
- if (availableHeight < absoluteConnectContainerHeight) {
128
- this.mainContainerElement.style.height = `${availableHeight}px`;
129
- this.mainContainerElement.style.overflowY = 'auto';
130
- this.mainContainerElement.style.overflowX = 'hidden';
131
- if (this.draggableInstances) {
132
- this.draggableInstances.forEach((draggableInstance) => (draggableInstance.autoScroll = 1));
133
- }
134
- }
135
- }
136
- }, 500);
137
- }
138
- }
78
+ async initGame() {
79
+ await this.scrollToRevealGame();
80
+ this.setScrollableHeight();
81
+ this.setDraggableObserver();
82
+ this.initDraggables();
139
83
  }
140
- preserveColors() {
84
+ initDraggables() {
141
85
  var _a;
142
- if ((_a = this.value) === null || _a === void 0 ? void 0 : _a.length) {
143
- this.value.forEach((couple) => {
144
- const [leftValue, rightValue] = couple;
145
- let draggable = this.draggables.find((drag) => drag.value === leftValue);
146
- let connectable = this.connectables.find((connect) => connect.value === rightValue);
147
- if (!draggable) {
148
- draggable = this.draggables.find((drag) => drag.value === rightValue);
149
- connectable = this.connectables.find((connect) => connect.value === leftValue);
150
- }
151
- if (draggable && connectable) {
152
- this.attachConnectable(draggable, connectable.id);
153
- this.applyColorChanges();
154
- }
155
- });
156
- }
86
+ (_a = this.draggableElements) === null || _a === void 0 ? void 0 : _a.forEach(e => this.initDraggableActions(e));
87
+ }
88
+ async scrollToRevealGame() {
89
+ const scrollElement = this.host.closest('yoo-ion-scroll');
90
+ return scrollElement && new Promise(resolve => {
91
+ setTimeout(() => {
92
+ scrollElement.scrollTo({ top: scrollElement.scrollHeight, behavior: 'smooth' });
93
+ resolve();
94
+ }, 1000);
95
+ });
157
96
  }
158
- applyCorrections(draggable, connectableId) {
159
- draggable.isCorrect = draggable.id === connectableId;
97
+ setScrollableHeight() {
98
+ var _a, _b, _c, _d, _e, _f, _g;
99
+ const GAP_PADDING = 8;
100
+ const { bottom } = this.host.getBoundingClientRect();
101
+ const numberOfItems = ((_b = (_a = this.values) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.length) || 0;
102
+ const formBounding = (_c = this.host.closest('form')) === null || _c === void 0 ? void 0 : _c.getBoundingClientRect();
103
+ const itemHeight = ((_e = (_d = this.innerContainerElement) === null || _d === void 0 ? void 0 : _d.querySelector('[id]')) === null || _e === void 0 ? void 0 : _e.clientHeight) + GAP_PADDING + GAP_PADDING / numberOfItems + 1;
104
+ if (itemHeight && formBounding && bottom > formBounding.bottom && ((_g = (_f = this.values) === null || _f === void 0 ? void 0 : _f[0]) === null || _g === void 0 ? void 0 : _g.length)) {
105
+ const maxItems = Math.floor(formBounding.height / itemHeight);
106
+ const maxHeight = maxItems * itemHeight + (maxItems + 1) * GAP_PADDING;
107
+ this.innerContainerElement.style.maxHeight = `${Math.min(formBounding.height, maxHeight + GAP_PADDING)}px`;
108
+ }
160
109
  }
161
- initUserAnswersArray() {
162
- this.userAnswers = [];
163
- if (this.values && this.values.length && Array.isArray(this.values[0])) {
164
- this.values[0].forEach((value, index) => {
165
- var _a, _b;
166
- if (value) {
167
- this.userAnswers.push([(_b = (_a = this.draggables) === null || _a === void 0 ? void 0 : _a[index]) === null || _b === void 0 ? void 0 : _b.id, '']);
110
+ setDraggableObserver() {
111
+ this.draggables = this.draggables.map(d => {
112
+ return new Proxy(d, {
113
+ set: (target, key, value) => {
114
+ if (key === 'connectableId') {
115
+ target[key] = value;
116
+ this.draggables.forEach(d => {
117
+ if (d.connectableId === value && d.id !== target.id) {
118
+ delete d.connectableId;
119
+ }
120
+ });
121
+ this.getUserAnswers();
122
+ this.validateUserAnswers();
123
+ }
124
+ return target[key] = value;
168
125
  }
169
126
  });
170
- }
171
- }
172
- initItems() {
173
- var _a, _b;
174
- const ids = [];
175
- (_b = (_a = this.values) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.forEach(() => {
176
- ids.push(getUUID());
177
127
  });
178
- ITEM_TYPES.forEach((type, index) => {
128
+ }
129
+ shuffleItems() {
130
+ this.shuffled && CONNECT_TYPES.forEach(type => this[`${type}s`] = shuffle(this[`${type}s`]));
131
+ }
132
+ prepareItems() {
133
+ CONNECT_TYPES.forEach((type, index) => {
179
134
  var _a, _b;
180
- this[`${type}s`] =
181
- ((_b = (_a = this.values) === null || _a === void 0 ? void 0 : _a[index]) === null || _b === void 0 ? void 0 : _b.map((value, valueIndex) => Object.assign({
182
- value,
183
- id: ids[valueIndex]
184
- }, !index
185
- ? {
186
- color: this.colors[valueIndex],
187
- isCorrect: false
188
- }
189
- : {
190
- isConnected: false
191
- }))) || [];
135
+ this[`${type}s`] = ((_b = (_a = this.values) === null || _a === void 0 ? void 0 : _a[index]) === null || _b === void 0 ? void 0 : _b.map((value, i) => (Object.assign({ value, id: getUUID() }, (!index && {
136
+ color: this.colors[i]
137
+ }))))) || [];
192
138
  });
193
139
  }
194
- setColor(elements, color) {
195
- const colorValue = getCssColor(this.colors.includes(color) ? this.defaultColors[0] : this.defaultColors[1]);
196
- const bgColor = getCssColor(color);
197
- this.updateColor(elements, bgColor, colorValue);
198
- }
199
- removeColor(elements) {
200
- const colorValue = getCssColor(this.defaultColors[1]);
201
- const bgColor = getCssColor(this.defaultColors[0]);
202
- const images = elements.filter((el) => el.classList.contains('image'));
203
- const el = elements.filter((val) => !(images === null || images === void 0 ? void 0 : images.includes(val)));
204
- if (images) {
205
- this.updateColor(images, 'transparent', 'transparent');
140
+ connectItems() {
141
+ if (this.value) {
142
+ this.draggables = this.draggables.map(draggable => {
143
+ var _a, _b, _c;
144
+ const [value1, value2] = ((_a = this.value) === null || _a === void 0 ? void 0 : _a.find(v => v.includes(draggable.value))) || [];
145
+ return Object.assign(Object.assign({}, draggable), (value1 && value2 && {
146
+ connectableId: (_c = (_b = this.connectables) === null || _b === void 0 ? void 0 : _b.find(c => c.value === value1 || c.value === value2)) === null || _c === void 0 ? void 0 : _c.id
147
+ }));
148
+ });
206
149
  }
207
- this.updateColor(el, bgColor, colorValue);
208
150
  }
209
- updateColor(els, bgColor, color) {
210
- els === null || els === void 0 ? void 0 : els.forEach((el) => {
211
- if (el) {
212
- el.style.backgroundColor = bgColor;
213
- el.style.color = color;
214
- }
215
- });
216
- }
217
- getDraggableInstance(id) {
218
- if (this.mainContainerElement && id) {
219
- const currentDraggable = this.getDraggable(id);
220
- const currentDragEl = this.getElement(currentDraggable.id, 'draggable');
151
+ initDraggableActions(draggableElement) {
152
+ var _a;
153
+ if (draggableElement) {
154
+ let tempConnectableElement;
155
+ const currentDraggable = (_a = this.draggables) === null || _a === void 0 ? void 0 : _a.find(d => (d === null || d === void 0 ? void 0 : d.id) === draggableElement.id);
221
156
  const onDragElement = () => {
222
- const draggedElementBR = currentDragEl.getBoundingClientRect();
223
- const connectableThreshold = this.subContainerElements[1].getBoundingClientRect().x;
224
- const isInConnectableArea = draggedElementBR.x + draggedElementBR.width >= connectableThreshold;
157
+ var _a, _b;
158
+ const overlapThreshold = '65%';
159
+ const { x, width } = draggableElement.getBoundingClientRect();
160
+ const connectableThreshold = this.innerContainerElement.querySelector('.connectables').getBoundingClientRect().x;
161
+ const isInConnectableArea = x + width >= connectableThreshold;
225
162
  if (isInConnectableArea) {
226
- this.connectables.forEach((connectable) => {
227
- const connectableEl = this.getElement(connectable.id, 'connectable');
228
- if (currentDraggable && isInConnectableArea) {
229
- if (currentDraggable.draggableInstance.hitTest(connectableEl, this.overlapThreshold)) {
230
- currentDraggable.tempConnectableId = connectable.id;
231
- this.setColor([connectableEl], this.hoverColor);
232
- }
163
+ this.connectableElements.forEach(e => {
164
+ var _a, _b;
165
+ if (((_b = (_a = currentDraggable === null || currentDraggable === void 0 ? void 0 : currentDraggable.draggableInstance) === null || _a === void 0 ? void 0 : _a.hitTest) === null || _b === void 0 ? void 0 : _b.call(_a, e, overlapThreshold)) && e.id !== currentDraggable.connectableId) {
166
+ tempConnectableElement = e;
167
+ tempConnectableElement.style.backgroundColor = 'var(--stable-light)';
233
168
  }
234
169
  });
235
170
  }
236
- const connectableEl = this.getElement(currentDraggable.tempConnectableId, 'connectable');
237
- if (currentDraggable.tempConnectableId && !currentDraggable.draggableInstance.hitTest(connectableEl, this.overlapThreshold)) {
238
- const tempItem = this.getConnectable(currentDraggable.tempConnectableId);
239
- if (!tempItem.isConnected) {
240
- this.removeColor([connectableEl]);
241
- }
242
- else {
243
- const sourceColor = this.draggables
244
- .filter((item) => item === null || item === void 0 ? void 0 : item.connectable)
245
- .find((item) => item.connectable.id === currentDraggable.tempConnectableId).color;
246
- this.setColor([connectableEl], sourceColor);
171
+ if (tempConnectableElement && !currentDraggable.draggableInstance.hitTest(tempConnectableElement, overlapThreshold)) {
172
+ ['color', 'background-color'].forEach(prop => tempConnectableElement.style.removeProperty(prop));
173
+ const connectableColor = (_b = (_a = this.draggables) === null || _a === void 0 ? void 0 : _a.find(d => (d === null || d === void 0 ? void 0 : d.connectableId) === tempConnectableElement.id)) === null || _b === void 0 ? void 0 : _b.color;
174
+ if (connectableColor) {
175
+ tempConnectableElement.style.backgroundColor = `var(--${connectableColor}`;
176
+ tempConnectableElement.style.color = 'var(--light)';
247
177
  }
248
- delete currentDraggable.tempConnectableId;
178
+ tempConnectableElement = null;
249
179
  }
250
180
  };
251
- const onReleaseElement = () => {
252
- gsapTo(currentDragEl, this.animationDelay, {
253
- x: 0,
254
- y: 0
255
- }).then(() => {
256
- if (currentDraggable === null || currentDraggable === void 0 ? void 0 : currentDraggable.tempConnectableId) {
257
- // get temp connectable
258
- const connectedElement = this.getElement(currentDraggable.tempConnectableId, 'connectable');
259
- const itemContainerElement = connectedElement.parentElement;
260
- this.setColor([itemContainerElement.firstElementChild], 'transparent');
261
- // attach temp connectable as connected
262
- this.attachConnectable(currentDraggable, currentDraggable.tempConnectableId);
263
- // check for isolated colored connectable
264
- this.removeOldConnectable();
265
- this.applyColorChanges();
266
- this.autoCompleteLastConnection();
267
- this.addAnswer(currentDraggable.id, currentDraggable.tempConnectableId);
268
- delete currentDraggable.tempConnectableId;
269
- }
270
- });
181
+ const onReleaseElement = async () => {
182
+ await gsapTo(draggableElement, this.animated ? 0.25 : 0, { x: 0, y: 0 });
183
+ if (tempConnectableElement) {
184
+ currentDraggable.connectableId = tempConnectableElement.id;
185
+ this.autoCompleteLastConnection();
186
+ }
187
+ tempConnectableElement = null;
271
188
  };
272
189
  const onCancelConnection = () => {
273
- if (currentDraggable === null || currentDraggable === void 0 ? void 0 : currentDraggable.connectable) {
274
- const connectedElement = this.getElement(currentDraggable.connectable.id, 'connectable');
275
- const clickedDraggableElement = this.getElement(currentDraggable.id, 'draggable');
276
- this.removeColor([clickedDraggableElement, connectedElement]);
277
- this.getConnectable(currentDraggable.connectable.id).isConnected = false;
278
- delete currentDraggable.connectable;
279
- this.addAnswer(currentDraggable.id, '');
280
- }
190
+ delete currentDraggable.connectableId;
191
+ this.autoEraseLastConnection();
192
+ this.getUserAnswers();
193
+ this.validateUserAnswers();
281
194
  };
282
- if (!this.readonly && this.isConnectMatchable && currentDragEl && this.mainContainerElement) {
283
- return new Draggable(currentDragEl, {
284
- bound: this.mainContainerElement,
195
+ if (!this.readonly && this.isGameMatchable && draggableElement) {
196
+ currentDraggable.draggableInstance = new Draggable(draggableElement, {
285
197
  autoScroll: 1,
198
+ bound: this.innerContainerElement,
286
199
  onDrag: onDragElement,
287
- onPress: onCancelConnection,
200
+ onClick: onCancelConnection,
288
201
  onRelease: onReleaseElement
289
202
  });
290
203
  }
291
204
  }
292
205
  }
293
- applyColorChanges() {
294
- this.draggables.forEach((draggable) => {
295
- var _a;
296
- if (draggable) {
297
- const sourceColor = draggable.color;
298
- const draggedElement = this.getElement(draggable.id, 'draggable');
299
- const connectableElement = this.getElement((_a = draggable.connectable) === null || _a === void 0 ? void 0 : _a.id, 'connectable');
300
- if (connectableElement) {
301
- if (this.readonly) {
302
- this.applyCorrections(draggable, draggable.connectable.id);
303
- for (const element of [draggedElement, connectableElement]) {
304
- const icon = element.getElementsByTagName('yoo-icon')[0];
305
- icon.name = draggable.isCorrect ? this.validationClasses.valid.icon : this.validationClasses.invalid.icon;
306
- icon.color = draggable.isCorrect ? this.validationClasses.valid.iconColor : this.validationClasses.invalid.iconColor;
307
- }
308
- }
309
- this.setColor([draggedElement, connectableElement], sourceColor);
310
- }
311
- }
312
- });
313
- }
314
- removeOldConnectable() {
315
- this.connectables.forEach((connectable) => {
316
- const isConnected = this.draggables.find((srcItem) => { var _a; return ((_a = srcItem === null || srcItem === void 0 ? void 0 : srcItem.connectable) === null || _a === void 0 ? void 0 : _a.id) === connectable.id; });
317
- if (!isConnected) {
318
- this.removeColor([this.getElement(connectable.id, 'connectable')]);
319
- }
320
- });
321
- }
322
- attachConnectable(draggableToConnect, connectableId) {
323
- const connectable = this.getConnectable(connectableId);
324
- const oldConnectedItem = this.draggables.find((dragItem) => { var _a; return ((_a = dragItem === null || dragItem === void 0 ? void 0 : dragItem.connectable) === null || _a === void 0 ? void 0 : _a.id) === connectableId; });
325
- if (oldConnectedItem && oldConnectedItem.id !== (draggableToConnect === null || draggableToConnect === void 0 ? void 0 : draggableToConnect.id)) {
326
- const oldConnectEl = this.getElement(oldConnectedItem.id, 'draggable');
327
- const oldConnectedEl = this.getElement(oldConnectedItem.connectable.id, 'connectable');
328
- this.removeColor([oldConnectEl, oldConnectedEl]);
329
- oldConnectedItem.connectable.isConnected = false;
330
- delete oldConnectedItem.connectable;
331
- }
332
- draggableToConnect.connectable = connectable;
333
- connectable.isConnected = true;
334
- }
335
- addAnswer(draggableId, connectableId) {
336
- if (draggableId && connectableId) {
337
- const answerIndex = this.userAnswers.findIndex((el) => (el === null || el === void 0 ? void 0 : el[0]) === draggableId);
338
- this.userAnswers[answerIndex] = [draggableId, connectableId];
339
- this.checkAnswersValidity();
340
- }
206
+ getUserAnswers() {
207
+ this.userAnswers = this.draggables.map(d => [d.value, d.connectableId ? this.connectables.find(c => c.id === d.connectableId).value : '']);
341
208
  }
342
- checkAnswersValidity() {
343
- var _a, _b;
344
- let _validity = false;
345
- if (((_a = this.userAnswers) === null || _a === void 0 ? void 0 : _a.length) === ((_b = this.answer) === null || _b === void 0 ? void 0 : _b.length)) {
346
- _validity = !this.userAnswers.find((gAnswer) => gAnswer[1] === '');
347
- }
348
- if (_validity !== this.validity) {
349
- this.validity = _validity;
350
- }
351
- if (_validity === true) {
352
- this.valideAnswers();
353
- }
209
+ validateUserAnswers(userAnswers = this.userAnswers) {
210
+ this.validity = !(userAnswers === null || userAnswers === void 0 ? void 0 : userAnswers.reduce((acc, v) => acc + v.filter(i => !i).length, 0));
211
+ setValueAndValidateInput(userAnswers, this);
354
212
  }
355
- valideAnswers() {
356
- if (!this.livePreview) {
357
- this.value = this.userAnswers;
358
- const answerValues = [];
359
- this.value.forEach((answers) => {
360
- const drag = this.getDraggable(answers[0]);
361
- const connect = this.getConnectable(answers[1]);
362
- if ((drag === null || drag === void 0 ? void 0 : drag.value) && (connect === null || connect === void 0 ? void 0 : connect.value)) {
363
- answerValues.push([drag.value, connect.value]);
364
- }
365
- });
366
- setValueAndValidateInput(answerValues, this);
213
+ autoEraseLastConnection() {
214
+ const connectedDraggables = this.draggables.filter(d => d.connectableId);
215
+ if ((connectedDraggables === null || connectedDraggables === void 0 ? void 0 : connectedDraggables.length) === 1) {
216
+ const lastDraggable = connectedDraggables[0];
217
+ delete lastDraggable.connectableId;
367
218
  }
368
219
  }
369
220
  autoCompleteLastConnection() {
370
- const freeDraggables = this.draggables.filter((draggable) => !draggable.connectable);
371
- const freeConnectables = this.connectables.filter((connectable) => !connectable.isConnected);
372
- if ((freeDraggables === null || freeDraggables === void 0 ? void 0 : freeDraggables.length) === 1 && (freeConnectables === null || freeConnectables === void 0 ? void 0 : freeConnectables.length) === 1) {
373
- const lastFreeDraggable = freeDraggables[0];
374
- const lastFreeConnectable = freeConnectables[0];
375
- const sourceColor = lastFreeDraggable.color;
376
- lastFreeConnectable.isConnected = true;
377
- this.setColor([this.getElement(lastFreeConnectable.id, 'connectable'), this.getElement(lastFreeDraggable.id, 'draggable')], sourceColor);
378
- lastFreeDraggable.connectable = lastFreeConnectable;
379
- this.addAnswer(lastFreeDraggable.id, lastFreeConnectable.id);
221
+ var _a;
222
+ const freeDraggables = this.draggables.filter(d => !d.connectableId);
223
+ if ((freeDraggables === null || freeDraggables === void 0 ? void 0 : freeDraggables.length) === 1) {
224
+ const lastDraggable = freeDraggables[0];
225
+ const lastConectableId = (_a = difference(this.connectables.map(c => c.id), this.draggables.map(d => d.connectableId))) === null || _a === void 0 ? void 0 : _a[0];
226
+ lastDraggable.connectableId = lastConectableId;
380
227
  }
381
228
  }
382
229
  truncateValue(valueToTruncate) {
383
230
  if (valueToTruncate) {
384
- const maxAuthorizedLength = 50;
231
+ const MAX_LENGTH = 50;
385
232
  const translatedValue = translateMulti(valueToTruncate);
386
233
  const valueLength = translatedValue.length;
387
- if (valueLength > maxAuthorizedLength) {
388
- return translatedValue.substr(0, maxAuthorizedLength).concat('...');
389
- }
390
- else {
391
- return translatedValue;
392
- }
234
+ const isTruncabled = valueLength > MAX_LENGTH;
235
+ return isTruncabled ? translatedValue.substr(0, MAX_LENGTH).concat('...') : translatedValue;
393
236
  }
394
237
  }
238
+ renderCorrectionIcon(value) {
239
+ const getCouple = (values) => values === null || values === void 0 ? void 0 : values.find(v => v.includes(value));
240
+ const isCorrect = isEqual(getCouple(this.value), getCouple(this.answer));
241
+ return h("yoo-icon", { size: "medium", name: isCorrect ? 'check' : 'cross', color: isCorrect ? 'success' : 'danger' });
242
+ }
395
243
  renderContainer(name) {
396
- const type = name === 'draggable' ? 0 : 1;
397
- const values = name === 'draggable' ? this.draggables : this.connectables;
398
- return (h("div", { class: `${name}-container`, ref: (element) => (this.subContainerElements[type] = element) }, values === null || values === void 0 ? void 0 : values.map((item) => {
399
- const hasImage = !isNullOrUndefined(item === null || item === void 0 ? void 0 : item.value) && isImageUrl(item === null || item === void 0 ? void 0 : item.value);
400
- return ((item === null || item === void 0 ? void 0 : item.value) && (h("div", { class: "item-container" },
401
- h("div", { id: item === null || item === void 0 ? void 0 : item.id, class: { [name]: true, image: hasImage, animated: this.animated } },
402
- !hasImage ? h("p", null, this.truncateValue(item.value)) : [h("yoo-img", { type: "background", src: item.value }), h("div", { class: "overlay" })],
403
- this.readonly && h("yoo-icon", { size: "medium" })))));
244
+ var _a;
245
+ return (h("section", { class: { [`${name}s`]: true } }, (_a = this[`${name}s`]) === null || _a === void 0 ? void 0 : _a.map((item) => {
246
+ var _a, _b;
247
+ const { id, value, connectableId, color } = item || {};
248
+ const isImage = !!(value && isImageUrl(value));
249
+ const isConnected = !!(connectableId || this.draggables.find(d => d.connectableId === id));
250
+ const tileColor = color || ((_b = (_a = this.draggables) === null || _a === void 0 ? void 0 : _a.find(d => d.connectableId === id)) === null || _b === void 0 ? void 0 : _b.color);
251
+ return !!value && (h("div", { class: "tile-container" },
252
+ h("div", Object.assign({}, (isConnected && {
253
+ style: {
254
+ backgroundColor: `var(--${tileColor})`,
255
+ color: 'var(--light)'
256
+ }
257
+ }), { id: id, key: id, class: { [name]: true, image: isImage, animated: this.animated } }),
258
+ !isImage ? h("p", null, this.truncateValue(value)) : [h("yoo-img", { type: "background", src: value }), h("div", { class: "overlay" })],
259
+ this.readonly && this.renderCorrectionIcon(value))));
404
260
  })));
405
261
  }
262
+ renderBanner() {
263
+ return this.livePreview && h("yoo-banner", null);
264
+ }
406
265
  render() {
407
- return this.hasValues && (h("div", { class: "connect-container", ref: (element) => (this.mainContainerElement = element) }, ITEM_TYPES.map((itemType) => this.renderContainer(itemType))));
266
+ return this.hasValues && (h(Host, { class: getAppContext(this.host) },
267
+ this.renderBanner(),
268
+ h("div", { class: "inner-container", ref: (element) => (this.innerContainerElement = element) }, CONNECT_TYPES.map(type => this.renderContainer(type)))));
408
269
  }
409
270
  static get is() { return "yoo-form-connect"; }
410
271
  static get encapsulation() { return "shadow"; }
@@ -430,21 +291,6 @@ export class YooFormConnectComponent {
430
291
  "text": "Poll of words to connect, dispatched in 2 arrays (Left and Right respectively)"
431
292
  }
432
293
  },
433
- "value": {
434
- "type": "unknown",
435
- "mutable": true,
436
- "complexType": {
437
- "original": "string[][]",
438
- "resolved": "string[][]",
439
- "references": {}
440
- },
441
- "required": false,
442
- "optional": false,
443
- "docs": {
444
- "tags": [],
445
- "text": "Value previously given by user, mostly used in read-only mode"
446
- }
447
- },
448
294
  "readonly": {
449
295
  "type": "boolean",
450
296
  "mutable": false,
@@ -550,7 +396,7 @@ export class YooFormConnectComponent {
550
396
  "attribute": "validity",
551
397
  "reflect": false
552
398
  },
553
- "answer": {
399
+ "value": {
554
400
  "type": "unknown",
555
401
  "mutable": false,
556
402
  "complexType": {
@@ -562,28 +408,25 @@ export class YooFormConnectComponent {
562
408
  "optional": false,
563
409
  "docs": {
564
410
  "tags": [],
565
- "text": "Expected answer. consisting of an array of arrays,\neach sub-array containing a pair of correctly connected words"
411
+ "text": "Value previously given by user, mostly used in read-only mode"
566
412
  }
567
413
  },
568
- "isVisible": {
569
- "type": "boolean",
414
+ "answer": {
415
+ "type": "unknown",
570
416
  "mutable": false,
571
417
  "complexType": {
572
- "original": "boolean",
573
- "resolved": "boolean",
418
+ "original": "string[][]",
419
+ "resolved": "string[][]",
574
420
  "references": {}
575
421
  },
576
422
  "required": false,
577
- "optional": true,
423
+ "optional": false,
578
424
  "docs": {
579
425
  "tags": [],
580
- "text": "true if component's parent slide is visible within a `yoo-form-dynamic`"
581
- },
582
- "attribute": "is-visible",
583
- "reflect": false,
584
- "defaultValue": "false"
426
+ "text": "Expected answer. consisting of an array of arrays,\neach sub-array containing a pair of correctly connected words"
427
+ }
585
428
  },
586
- "isAnimationFinished": {
429
+ "isVisible": {
587
430
  "type": "boolean",
588
431
  "mutable": false,
589
432
  "complexType": {
@@ -592,15 +435,19 @@ export class YooFormConnectComponent {
592
435
  "references": {}
593
436
  },
594
437
  "required": false,
595
- "optional": false,
438
+ "optional": true,
596
439
  "docs": {
597
440
  "tags": [],
598
- "text": "Used to check when modal is loaded"
441
+ "text": "true if component's parent slide is visible within a `yoo-form-dynamic`"
599
442
  },
600
- "attribute": "is-animation-finished",
601
- "reflect": false
443
+ "attribute": "is-visible",
444
+ "reflect": false,
445
+ "defaultValue": "false"
602
446
  }
603
447
  }; }
448
+ static get states() { return {
449
+ "userAnswers": {}
450
+ }; }
604
451
  static get events() { return [{
605
452
  "method": "validityChanged",
606
453
  "name": "validityChanged",
@@ -631,37 +478,22 @@ export class YooFormConnectComponent {
631
478
  "resolved": "string[]",
632
479
  "references": {}
633
480
  }
634
- }, {
635
- "method": "dragEnded",
636
- "name": "dragEnded",
637
- "bubbles": true,
638
- "cancelable": true,
639
- "composed": true,
640
- "docs": {
641
- "tags": [],
642
- "text": ""
643
- },
644
- "complexType": {
645
- "original": "boolean",
646
- "resolved": "boolean",
647
- "references": {}
648
- }
649
481
  }]; }
650
482
  static get elementRef() { return "host"; }
651
483
  static get watchers() { return [{
652
- "propName": "required",
653
- "methodName": "onRequireChanged"
484
+ "propName": "values",
485
+ "methodName": "onValuesChanged"
654
486
  }, {
655
487
  "propName": "validity",
656
- "methodName": "isValid"
488
+ "methodName": "onValidityChanged"
489
+ }, {
490
+ "propName": "value",
491
+ "methodName": "onValueChanged"
657
492
  }, {
658
493
  "propName": "answer",
659
- "methodName": "initValues"
494
+ "methodName": "initAnswerChanged"
660
495
  }, {
661
496
  "propName": "isVisible",
662
497
  "methodName": "onIsVisibleChanged"
663
- }, {
664
- "propName": "isAnimationFinished",
665
- "methodName": "onModalAnimationFinished"
666
498
  }]; }
667
499
  }