@itfin/components 1.2.85 → 1.2.86

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 (67) hide show
  1. package/package.json +4 -3
  2. package/src/components/customize/PropertiesEditMenu.vue +53 -0
  3. package/src/components/customize/PropertiesItemsMenu.vue +33 -0
  4. package/src/components/customize/PropertiesList.vue +179 -0
  5. package/src/components/customize/PropertiesPopupMenu.vue +46 -0
  6. package/src/components/customize/PropertyInlineEdit.vue +46 -0
  7. package/src/components/customize/index.stories.js +65 -0
  8. package/src/components/dropdown/Dropdown.vue +8 -19
  9. package/src/components/icon/components/type_checkbox.vue +2 -0
  10. package/src/components/icon/components/type_date.vue +2 -0
  11. package/src/components/icon/components/type_email.vue +2 -0
  12. package/src/components/icon/components/type_file.vue +2 -0
  13. package/src/components/icon/components/type_formula.vue +2 -0
  14. package/src/components/icon/components/type_id.vue +2 -0
  15. package/src/components/icon/components/type_multiselect.vue +2 -0
  16. package/src/components/icon/components/type_number.vue +2 -0
  17. package/src/components/icon/components/type_person.vue +2 -0
  18. package/src/components/icon/components/type_phone.vue +2 -0
  19. package/src/components/icon/components/type_relation.vue +2 -0
  20. package/src/components/icon/components/type_select.vue +2 -0
  21. package/src/components/icon/components/type_status.vue +2 -0
  22. package/src/components/icon/components/type_text.vue +2 -0
  23. package/src/components/icon/components/type_time.vue +2 -0
  24. package/src/components/icon/components/type_url.vue +2 -0
  25. package/src/components/icon/components/type_user.vue +2 -0
  26. package/src/components/icon/icons/type_checkbox.svg +1 -0
  27. package/src/components/icon/icons/type_date.svg +1 -0
  28. package/src/components/icon/icons/type_email.svg +1 -0
  29. package/src/components/icon/icons/type_file.svg +1 -0
  30. package/src/components/icon/icons/type_formula.svg +1 -0
  31. package/src/components/icon/icons/type_id.svg +1 -0
  32. package/src/components/icon/icons/type_multiselect.svg +1 -0
  33. package/src/components/icon/icons/type_number.svg +1 -0
  34. package/src/components/icon/icons/type_person.svg +1 -0
  35. package/src/components/icon/icons/type_phone.svg +1 -0
  36. package/src/components/icon/icons/type_relation.svg +1 -0
  37. package/src/components/icon/icons/type_select.svg +1 -0
  38. package/src/components/icon/icons/type_status.svg +1 -0
  39. package/src/components/icon/icons/type_text.svg +1 -0
  40. package/src/components/icon/icons/type_time.svg +1 -0
  41. package/src/components/icon/icons/type_url.svg +1 -0
  42. package/src/components/icon/icons/type_user.svg +1 -0
  43. package/src/components/icon/icons.js +295 -278
  44. package/src/components/modal/DeleteConfirmModal.vue +78 -0
  45. package/src/components/modal/ItemEditor.vue +219 -0
  46. package/src/components/modal/Modal.vue +15 -13
  47. package/src/components/modal/index.stories.js +15 -10
  48. package/src/components/popover/ConfirmPopover.vue +1 -1
  49. package/src/components/popover/DeleteConfirmPopover.vue +39 -0
  50. package/src/components/popover/IconPopover.vue +136 -0
  51. package/src/components/popover/SelectPopover.vue +127 -0
  52. package/src/components/popover/index.stories.js +26 -10
  53. package/src/components/sortable/AutoScroll.vue +142 -0
  54. package/src/components/sortable/Sortable.scss +93 -0
  55. package/src/components/sortable/Sortable.vue +399 -0
  56. package/src/components/sortable/sortable-item-list/axis.js +9 -0
  57. package/src/components/sortable/sortable-item-list/mocked-sortable-item-list.js +415 -0
  58. package/src/components/sortable/sortable-item-list/original-sortable-item-list.js +105 -0
  59. package/src/components/sortable/utils/event-outside.js +30 -0
  60. package/src/components/sortable/utils/get-relative-position.js +41 -0
  61. package/src/components/sortable/utils/sort-item-list.js +13 -0
  62. package/src/components/sortable/utils/stop-event.js +16 -0
  63. package/src/components/sortable/utils/vibrate.js +18 -0
  64. package/src/components/text-field/MoneyField.vue +103 -0
  65. package/src/components/text-field/index.stories.js +53 -0
  66. package/src/directives/tooltip.js +1 -1
  67. package/src/locales/en.js +28 -0
@@ -0,0 +1,399 @@
1
+ <template>
2
+ <div
3
+ class="itf-sortable"
4
+ @keydown.enter="onKeydownEnter"
5
+ @keydown.space="onKeydownEnter"
6
+ @keydown.down="onKeydownDown"
7
+ @keydown.right="onKeydownDown"
8
+ @keydown.up="onKeydownUp"
9
+ @keydown.left="onKeydownUp"
10
+ @keydown.escape="onKeydownEscape"
11
+ @keydown.tab="onKeydownEscape"
12
+ @mousedown="onMouseDown"
13
+ @click="onMouseClick"
14
+ @dblclick="onMouseClick"
15
+ @touchstart="onTouchStart"
16
+ @touchcancel="onTouchCancel"
17
+ @mouseup="onMouseUp"
18
+ @touchend="onTouchEnd"
19
+ @mouseover="onMouseOver"
20
+ @mouseout="onMouseOut"
21
+ @mousemove="onMouseMove"
22
+ @touchmove="onTouchMove"
23
+ @dropoutside="onDropOutside"
24
+ >
25
+ <auto-scroll
26
+ ref="autoscroll"
27
+ :disabled="!isSortingInProgress || !autoScroll"
28
+ :parent-selector="autoScroll === 'window' ? null : autoScroll"
29
+ class="autoscroll"
30
+ >
31
+ <div
32
+ ref="originalList"
33
+ class="itf-sortable-list itf-sortable-list-original"
34
+ :class="listClass"
35
+ >
36
+ <!-- @slot Slot for typeahead -->
37
+ <slot />
38
+ </div>
39
+ <ul
40
+ ref="mockedList"
41
+ class="itf-sortable-list itf-sortable-list-mocked hidden"
42
+ :class="listClass"
43
+ />
44
+ </auto-scroll>
45
+ </div>
46
+ </template>
47
+ <script>
48
+ import autoScroll from './AutoScroll.vue';
49
+ import { onDropOutside } from './utils/event-outside';
50
+ import OriginalSortableItemList from './sortable-item-list/original-sortable-item-list';
51
+ import MockedSortableItemList, { ATTRIBUTE_SKIP_SORTING } from './sortable-item-list/mocked-sortable-item-list';
52
+ import sortItemList from './utils/sort-item-list';
53
+ import vibrate from './utils/vibrate';
54
+ import stopEvent from './utils/stop-event';
55
+ import { AXIS } from './sortable-item-list/axis';
56
+ import './Sortable.scss';
57
+
58
+ /**
59
+ * Sortable component to reorder LI elements in a UL item list.
60
+ * Each sortable element should have attribute sortable="true" in case
61
+ * if `require-sortable-attribute="true"` then sorted element
62
+ * or its part should have `sortable` attribute
63
+ * if `sortable-skip="true"` then sorting is ignored for that element
64
+ */
65
+ export default {
66
+ name: 'itfSortable',
67
+ components: {
68
+ autoScroll
69
+ },
70
+ props: {
71
+ /**
72
+ * Items to sort
73
+ */
74
+ value: {
75
+ type: Array,
76
+ default: /* istanbul ignore next */ () => []
77
+ },
78
+ /**
79
+ * Axis to sort: x, y, xy
80
+ */
81
+ axis: {
82
+ type: String,
83
+ default: AXIS.xy,
84
+ validator (value) {
85
+ return [AXIS.x, AXIS.y, AXIS.xy].includes(value);
86
+ }
87
+ },
88
+ /**
89
+ * Sorting is not allowed if true
90
+ */
91
+ readOnly: {
92
+ type: Boolean,
93
+ default: false
94
+ },
95
+ /**
96
+ * Auto scroll during sorting is available if set.
97
+ * Value `window` manages scrolling for window,
98
+ * else treated as an html selector for its parent to scroll.
99
+ */
100
+ autoScroll: {
101
+ type: String,
102
+ default: null
103
+ },
104
+ /**
105
+ * Sorting is allowed if an element has attribute `sortable/data-sortable` = `true`
106
+ */
107
+ requireSortableAttribute: {
108
+ type: Boolean,
109
+ default: false
110
+ },
111
+ /**
112
+ * Sortable list class name
113
+ */
114
+ listClass: {
115
+ type: String,
116
+ default: null
117
+ },
118
+ /**
119
+ * Item cursor class name
120
+ */
121
+ cursorClass: {
122
+ type: String,
123
+ default: null
124
+ },
125
+ /**
126
+ * Item cursor selector
127
+ */
128
+ cursorSelector: {
129
+ type: String,
130
+ default: null
131
+ }
132
+ },
133
+ data () {
134
+ return {
135
+ originalItemList: new OriginalSortableItemList(),
136
+ mockedItemList: new MockedSortableItemList(),
137
+ isSortingInProgress: false
138
+ };
139
+ },
140
+ watch: {
141
+ readOnly (newValue) {
142
+ if (newValue) {
143
+ this.cancelSorting(null);
144
+ }
145
+ },
146
+ axis (newValue) {
147
+ this.mockedItemList.setAxis(newValue);
148
+ }
149
+ },
150
+ mounted () {
151
+ this.originalItemList.setContainer(this.$refs.originalList);
152
+ this.mockedItemList.setContainer(this.$refs.mockedList);
153
+ this.mockedItemList.setAxis(this.axis);
154
+ this.onDropOutsideRelease = onDropOutside(this.$el, event =>
155
+ this.onDropOutside(event)
156
+ );
157
+ },
158
+ beforeDestroy () {
159
+ this.onDropOutsideRelease();
160
+ },
161
+ methods: {
162
+ onKeydownEnter (event) {
163
+ if (this.isSortingInProgress) {
164
+ this.finishSorting(true);
165
+ return stopEvent(event);
166
+ }
167
+ if (this.isSortingAvailable(event.target)) {
168
+ this.startSorting(event);
169
+ setTimeout(() => this.scrollToCursorItem(), 100);
170
+ return stopEvent(event);
171
+ }
172
+ return null;
173
+ },
174
+ onKeydownDown (event) {
175
+ if (this.isSortingInProgress) {
176
+ if (this.mockedItemList.moveDown()) {
177
+ this.scrollToCursorItem();
178
+ this.emitChangeEvent('keydown-down');
179
+ }
180
+ return stopEvent(event);
181
+ }
182
+ return null;
183
+ },
184
+ onKeydownUp (event) {
185
+ if (this.isSortingInProgress) {
186
+ this.mockedItemList.moveUp();
187
+ this.scrollToCursorItem();
188
+ this.emitChangeEvent('keydown-up');
189
+ return stopEvent(event);
190
+ }
191
+ return null;
192
+ },
193
+ onKeydownEscape (event) {
194
+ if (this.isSortingInProgress) {
195
+ this.cancelSorting(this.mockedItemList.getFromPosition());
196
+ return stopEvent(event);
197
+ }
198
+ return null;
199
+ },
200
+ onMouseDown (event) {
201
+ if (!this.isSortingInProgress && this.isSortingAvailable(event.target)) {
202
+ this.startSorting(event);
203
+ return stopEvent(event);
204
+ }
205
+ return null;
206
+ },
207
+ onMouseClick () {
208
+ this.cancelSorting(null);
209
+ },
210
+ onTouchStart (event) {
211
+ if (this.isSortingAvailable(event.target)) {
212
+ this.startSorting(event);
213
+ if (this.isSortingInProgress) {
214
+ vibrate();
215
+ return stopEvent(event);
216
+ }
217
+ }
218
+ return null;
219
+ },
220
+ onTouchCancel (event) {
221
+ if (this.isSortingInProgress) {
222
+ return stopEvent(event);
223
+ }
224
+ return null;
225
+ },
226
+ onMouseUp (event) {
227
+ if (this.isSortingInProgress) {
228
+ this.finishSorting();
229
+ return stopEvent(event);
230
+ }
231
+ return null;
232
+ },
233
+ onTouchEnd (event) {
234
+ if (this.isSortingInProgress) {
235
+ this.finishSorting();
236
+ vibrate();
237
+ return stopEvent(event);
238
+ }
239
+ return null;
240
+ },
241
+ onMouseOver (event) {
242
+ if (this.isSortingInProgress) {
243
+ return stopEvent(event);
244
+ }
245
+ return null;
246
+ },
247
+ onMouseOut (event) {
248
+ if (this.isSortingInProgress) {
249
+ return stopEvent(event);
250
+ }
251
+ return null;
252
+ },
253
+ onMouseMove (event) {
254
+ if (this.isSortingInProgress) {
255
+ this.performSorting(event);
256
+ this.emitChangeEvent('mousemove');
257
+ return stopEvent(event);
258
+ }
259
+ return null;
260
+ },
261
+ onTouchMove (event) {
262
+ if (this.isSortingInProgress) {
263
+ this.performSorting(event);
264
+ this.emitChangeEvent('touchmove');
265
+ return stopEvent(event);
266
+ }
267
+ return null;
268
+ },
269
+ onDropOutside (event) {
270
+ if (this.isSortingInProgress) {
271
+ this.cancelSorting(null);
272
+ return stopEvent(event);
273
+ }
274
+ return null;
275
+ },
276
+ scrollToCursorItem () {
277
+ this.$refs.autoscroll.autoScroll(
278
+ this.mockedItemList.getCursorPageX(),
279
+ this.mockedItemList.getCursorPageY(),
280
+ false
281
+ );
282
+ },
283
+ startSorting (event) {
284
+ const { target } = event;
285
+ this.cancelSorting(null);
286
+ if (
287
+ !this.readOnly &&
288
+ this.originalItemList.isSortable(target, this.requireSortableAttribute)
289
+ ) {
290
+ const itemElement = this.originalItemList.getSortItem(target);
291
+ const position = this.originalItemList.getItemIndexByElement(
292
+ itemElement
293
+ );
294
+ if (position >= 0) {
295
+ /**
296
+ * Start sorting
297
+ * @param {number} position Start position to sort
298
+ * @param {Event} event Event
299
+ */
300
+ this.$emit('sortable-start', position, event);
301
+ this.mockSortingList(position, event);
302
+ this.isSortingInProgress = true;
303
+ this.changeEventSign = null;
304
+ }
305
+ }
306
+ },
307
+ performSorting (event) {
308
+ if (this.isSortingInProgress) {
309
+ this.mockedItemList.move(event);
310
+ }
311
+ },
312
+ finishSorting (setFocus = false) {
313
+ if (this.isSortingInProgress) {
314
+ const from = this.mockedItemList.getFromPosition();
315
+ const to = this.mockedItemList.getToPosition();
316
+ const callback = itemList => sortItemList(itemList, from, to);
317
+ if (this.mockedItemList.isSorted()) {
318
+ this.mockedItemList.finishSorting();
319
+ const items = callback(this.value);
320
+ /**
321
+ * Change model value
322
+ */
323
+ this.$emit('input', items);
324
+ /**
325
+ * Sort happened
326
+ * @param {Function} callback Callback to sort an array with one argument.
327
+ * If sorting through v-model is not enough
328
+ * @param {number} from From position
329
+ * @param {number} to From position
330
+ */
331
+ this.$emit('sort', callback, from, to);
332
+ this.$emit('sortable-finish');
333
+ }
334
+ const focusItemPosition = setFocus ? to : null;
335
+ setTimeout(() => this.restoreOriginalList(focusItemPosition), 10);
336
+ this.isSortingInProgress = false;
337
+ }
338
+ },
339
+ mockSortingList (fromPosition, event) {
340
+ this.originalItemList.hide();
341
+ this.mockedItemList.reset();
342
+ this.originalItemList.cloneTo(this.mockedItemList.getContainer());
343
+ this.mockedItemList.createCursorItem(
344
+ fromPosition,
345
+ event,
346
+ this.cursorClass,
347
+ this.cursorSelector
348
+ );
349
+ },
350
+ restoreOriginalList (positionToFocus) {
351
+ this.originalItemList.restore(positionToFocus);
352
+ this.mockedItemList.hide();
353
+ },
354
+ cancelSorting (positionToFocus) {
355
+ if (this.isSortingInProgress) {
356
+ this.restoreOriginalList(positionToFocus);
357
+ this.isSortingInProgress = false;
358
+ /**
359
+ * Cancel sorting
360
+ */
361
+ this.$emit('sortable-cancel');
362
+ /**
363
+ * Finish sorting
364
+ */
365
+ this.$emit('sortable-finish');
366
+ }
367
+ },
368
+ emitChangeEvent (source) {
369
+ const sign = [
370
+ this.mockedItemList.getFromPosition(),
371
+ this.mockedItemList.getToPosition(),
372
+ source
373
+ ].join('!');
374
+ if (this.changeEventSign !== sign) {
375
+ /**
376
+ * Change sorting
377
+ * @param {number} from From position
378
+ * @param {number} to To position
379
+ * @param {string} source Source
380
+ */
381
+ this.$emit(
382
+ 'sortable-change',
383
+ this.mockedItemList.getFromPosition(),
384
+ this.mockedItemList.getToPosition(),
385
+ source
386
+ );
387
+ this.changeEventSign = sign;
388
+ }
389
+ },
390
+ isSortingAvailable (element) {
391
+ const sortableSkip = element.closest(`[${ATTRIBUTE_SKIP_SORTING}]`);
392
+ if (sortableSkip) {
393
+ return false;
394
+ }
395
+ return !sortableSkip || !this.mockedItemList.isToSkip(sortableSkip);
396
+ }
397
+ }
398
+ };
399
+ </script>
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Sorting directions
3
+ */
4
+ // eslint-disable-next-line import/prefer-default-export
5
+ export const AXIS = {
6
+ x: 'x',
7
+ y: 'y',
8
+ xy: 'xy'
9
+ };