ember-sortable 2.2.5 → 3.0.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 (38) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +2 -2
  2. package/.github/workflows/github_ci.yml +15 -13
  3. package/.huskyrc +0 -1
  4. package/CHANGELOG.md +234 -104
  5. package/MIGRATION_GUIDE_MODIFIERS.md +20 -13
  6. package/MIGRATION_GUIDE_V2.md +20 -8
  7. package/README.md +83 -149
  8. package/V2_MIGRATION_RFC.md +188 -222
  9. package/addon/modifiers/sortable-group.js +59 -52
  10. package/addon/modifiers/sortable-handle.js +16 -18
  11. package/addon/modifiers/sortable-item.js +124 -84
  12. package/addon/services/ember-sortable.js +3 -6
  13. package/addon/system/scroll-parent.js +1 -1
  14. package/addon/utils/coordinate.js +1 -1
  15. package/addon/utils/css-calculation.js +2 -2
  16. package/addon/utils/defaults.js +4 -3
  17. package/addon/utils/keyboard.js +3 -12
  18. package/addon-test-support/helpers/drag.js +3 -11
  19. package/addon-test-support/helpers/index.js +1 -4
  20. package/addon-test-support/helpers/reorder.js +4 -6
  21. package/addon-test-support/utils/keyboard.js +3 -12
  22. package/addon-test-support/utils/offset.js +6 -6
  23. package/config/environment.js +2 -2
  24. package/index.js +0 -20
  25. package/package.json +32 -18
  26. package/addon/components/sortable-group.js +0 -726
  27. package/addon/components/sortable-handle.js +0 -11
  28. package/addon/components/sortable-item.js +0 -753
  29. package/addon/styles/components/sortable-group.css +0 -9
  30. package/addon/templates/components/sortable-group.hbs +0 -16
  31. package/addon/templates/components/sortable-handle.hbs +0 -1
  32. package/addon/templates/components/sortable-item.hbs +0 -2
  33. package/addon/utils/transitionend.js +0 -22
  34. package/app/components/sortable-group.js +0 -3
  35. package/app/components/sortable-handle.js +0 -4
  36. package/app/components/sortable-item.js +0 -3
  37. package/jsconfig.json +0 -1
  38. package/vendor/polyfills/closest.js +0 -21
@@ -1,5 +1,7 @@
1
+ /* eslint-disable ember/no-computed-properties-in-native-classes */
2
+ /* eslint-disable ember/no-incorrect-calls-with-inline-anonymous-functions */
1
3
  import Modifier from 'ember-modifier';
2
- import {action, computed, set} from '@ember/object';
4
+ import { action, computed, set } from '@ember/object';
3
5
  import {
4
6
  isDownArrowKey,
5
7
  isEnterKey,
@@ -7,12 +9,12 @@ import {
7
9
  isLeftArrowKey,
8
10
  isRightArrowKey,
9
11
  isSpaceKey,
10
- isUpArrowKey
11
- } from "../utils/keyboard";
12
- import {ANNOUNCEMENT_ACTION_TYPES} from "../utils/constant";
13
- import { defaultA11yAnnouncementConfig } from "../utils/defaults";
14
- import { run } from '@ember/runloop';
15
- import {inject as service} from '@ember/service';
12
+ isUpArrowKey,
13
+ } from '../utils/keyboard';
14
+ import { ANNOUNCEMENT_ACTION_TYPES } from '../utils/constant';
15
+ import { defaultA11yAnnouncementConfig } from '../utils/defaults';
16
+ import { next, schedule, scheduleOnce, later } from '@ember/runloop';
17
+ import { inject as service } from '@ember/service';
16
18
 
17
19
  const NO_MODEL = {};
18
20
 
@@ -37,7 +39,6 @@ const NO_MODEL = {};
37
39
  * </ol>
38
40
  */
39
41
  export default class SortableGroupModifier extends Modifier {
40
-
41
42
  /** Primary keyboard utils */
42
43
  // Tracks the currently selected item
43
44
  _selectedItem = null;
@@ -54,6 +55,10 @@ export default class SortableGroupModifier extends Modifier {
54
55
  isRetainingFocus = false;
55
56
  /** End of keyboard utils */
56
57
 
58
+ get disabled() {
59
+ return this.args.named.disabled || false;
60
+ }
61
+
57
62
  /** Start of a11y properties */
58
63
  /**
59
64
  * @property an object containing different classes for visual indicators
@@ -87,7 +92,7 @@ export default class SortableGroupModifier extends Modifier {
87
92
  }
88
93
 
89
94
  get itemVisualClass() {
90
- return this.args.named.itemVisualClass || "is-activated";
95
+ return this.args.named.itemVisualClass || 'is-activated';
91
96
  }
92
97
 
93
98
  get a11yItemName() {
@@ -136,7 +141,7 @@ export default class SortableGroupModifier extends Modifier {
136
141
 
137
142
  this.isRetainingFocus = true;
138
143
 
139
- run.scheduleOnce('render', () => {
144
+ scheduleOnce('render', () => {
140
145
  this.element.focus();
141
146
  this.isRetainingFocus = false;
142
147
  });
@@ -175,7 +180,7 @@ export default class SortableGroupModifier extends Modifier {
175
180
 
176
181
  // switch direction values to notify sortedItems to update, so it sorts by direction.
177
182
  let value;
178
- const dimension = direction === "y" ? "height" : "width";
183
+ const dimension = direction === 'y' ? 'height' : 'width';
179
184
  // DOWN or RIGHT
180
185
  if (toIndex > fromIndex) {
181
186
  value = item[direction];
@@ -202,13 +207,13 @@ export default class SortableGroupModifier extends Modifier {
202
207
  const direction = this.direction;
203
208
  const selectedItem = this._selectedItem;
204
209
 
205
- if (direction === "y" && isDownArrowKey(event)) {
210
+ if (direction === 'y' && isDownArrowKey(event)) {
206
211
  this.moveItem(selectedItem, 1);
207
- } else if (direction === "y" && isUpArrowKey(event)) {
212
+ } else if (direction === 'y' && isUpArrowKey(event)) {
208
213
  this.moveItem(selectedItem, -1);
209
- } else if (direction === "x" && isLeftArrowKey(event)) {
214
+ } else if (direction === 'x' && isLeftArrowKey(event)) {
210
215
  this.moveItem(selectedItem, -1);
211
- } else if (direction === "x" && isRightArrowKey(event)) {
216
+ } else if (direction === 'x' && isRightArrowKey(event)) {
212
217
  this.moveItem(selectedItem, 1);
213
218
  } else if (isEnterKey(event) || isSpaceKey(event)) {
214
219
  // confirm will reset the selectedItem, so caching it here before we remove it.
@@ -217,7 +222,7 @@ export default class SortableGroupModifier extends Modifier {
217
222
  this.confirmKeyboardSelection();
218
223
 
219
224
  this.isRetainingFocus = true;
220
- run.scheduleOnce('render', () => this._focusItem(itemElement));
225
+ scheduleOnce('render', () => this._focusItem(itemElement));
221
226
  } else if (isEscapeKey(event)) {
222
227
  // cancel will reset the selectedItem, so caching it here before we remove it.
223
228
  const _selectedItemElement = selectedItem.element;
@@ -225,11 +230,11 @@ export default class SortableGroupModifier extends Modifier {
225
230
  this.cancelKeyboardSelection();
226
231
 
227
232
  this.isRetainingFocus = true;
228
- run.scheduleOnce('render', () => {
233
+ scheduleOnce('render', () => {
229
234
  const moves = this.moves;
230
235
  if (moves && moves.length > 0) {
231
236
  const sortedItems = this.sortedItems;
232
- const itemElement = sortedItems[moves[0].fromIndex].element
237
+ const itemElement = sortedItems[moves[0].fromIndex].element;
233
238
  this._focusItem(itemElement);
234
239
  } else {
235
240
  this._focusItem(_selectedItemElement);
@@ -258,7 +263,7 @@ export default class SortableGroupModifier extends Modifier {
258
263
  }
259
264
  this._announceAction(ANNOUNCEMENT_ACTION_TYPES.MOVE, delta);
260
265
  // Guarantees that the before the UI is fully rendered before we move again.
261
- run.scheduleOnce('render', () => {
266
+ scheduleOnce('render', () => {
262
267
  this._move(sortedIndex, newSortedIndex);
263
268
  this._updateHandleVisualIndicators(item, true);
264
269
 
@@ -281,7 +286,7 @@ export default class SortableGroupModifier extends Modifier {
281
286
  const moves = this.moves;
282
287
  while (moves.length > 0) {
283
288
  const move = moves.pop();
284
- this._move(move[1], move[0])
289
+ this._move(move[1], move[0]);
285
290
  }
286
291
  this._tearDownA11yApplicationContainer();
287
292
  this._updateItemVisualIndicators(_selectedItem, false);
@@ -302,7 +307,7 @@ export default class SortableGroupModifier extends Modifier {
302
307
  this.moves = [];
303
308
  this._disableKeyboardReorderMode();
304
309
  this._tearDownA11yApplicationContainer();
305
- set(_selectedItem, "wasDropped", true);
310
+ set(_selectedItem, 'wasDropped', true);
306
311
  this.commit();
307
312
  this._updateItemVisualIndicators(_selectedItem, false);
308
313
  this._updateHandleVisualIndicators(_selectedItem, false);
@@ -331,7 +336,7 @@ export default class SortableGroupModifier extends Modifier {
331
336
  const config = {
332
337
  a11yItemName,
333
338
  index: index,
334
- maxLength : sortedItems.length,
339
+ maxLength: sortedItems.length,
335
340
  direction: this.direction,
336
341
  delta,
337
342
  };
@@ -340,7 +345,7 @@ export default class SortableGroupModifier extends Modifier {
340
345
  announcer.textContent = message;
341
346
 
342
347
  // Reset the message after the message is announced.
343
- run.later(() => {
348
+ later(() => {
344
349
  announcer.textContent = '';
345
350
  }, 1000);
346
351
  }
@@ -359,7 +364,6 @@ export default class SortableGroupModifier extends Modifier {
359
364
  * @param {Boolean} isActive to activate or deactivate the class.
360
365
  */
361
366
  _updateItemVisualIndicators(item, isActive) {
362
-
363
367
  const itemVisualClass = this.itemVisualClass;
364
368
 
365
369
  if (!itemVisualClass || !item) {
@@ -393,7 +397,7 @@ export default class SortableGroupModifier extends Modifier {
393
397
  const visualHandle = handle ? handle : item.element;
394
398
  const visualKeys = direction === 'y' ? ['UP', 'DOWN'] : ['LEFT', 'RIGHT'];
395
399
 
396
- visualKeys.forEach(visualKey => {
400
+ visualKeys.forEach((visualKey) => {
397
401
  visualHandle.classList.remove(handleVisualClass[visualKey]);
398
402
  });
399
403
 
@@ -443,7 +447,7 @@ export default class SortableGroupModifier extends Modifier {
443
447
  * Sets up the group as an application and make it programmatically focusable.
444
448
  */
445
449
  _setupA11yApplicationContainer() {
446
- this.element.setAttribute("role", "application");
450
+ this.element.setAttribute('role', 'application');
447
451
  this.element.tabIndex = -1;
448
452
  }
449
453
 
@@ -451,8 +455,8 @@ export default class SortableGroupModifier extends Modifier {
451
455
  * Tears down the `role=application` container.
452
456
  */
453
457
  _tearDownA11yApplicationContainer() {
454
- this.element.removeAttribute("role");
455
- this.element.removeAttribute("tabIndex");
458
+ this.element.removeAttribute('role');
459
+ this.element.removeAttribute('tabIndex');
456
460
  }
457
461
 
458
462
  _prepareKeyboardReorderMode() {
@@ -468,7 +472,7 @@ export default class SortableGroupModifier extends Modifier {
468
472
  @default y
469
473
  */
470
474
  get direction() {
471
- return this.args.named.direction || "y";
475
+ return this.args.named.direction || 'y';
472
476
  }
473
477
 
474
478
  /**
@@ -495,7 +499,7 @@ export default class SortableGroupModifier extends Modifier {
495
499
  * @returns {*|string}
496
500
  */
497
501
  get groupName() {
498
- return this.args.named.groupName || "_EmberSortableGroup";
502
+ return this.args.named.groupName || '_EmberSortableGroup';
499
503
  }
500
504
 
501
505
  _groupDef = this.sortableService.fetchGroup(this.groupName);
@@ -526,7 +530,7 @@ export default class SortableGroupModifier extends Modifier {
526
530
  @property firstItemPosition
527
531
  @type Number
528
532
  */
529
- @computed("direction", "sortedItems")
533
+ @computed('direction', 'sortedItems')
530
534
  get firstItemPosition() {
531
535
  const direction = this.direction;
532
536
  const sortedItems = this.sortedItems;
@@ -548,7 +552,7 @@ export default class SortableGroupModifier extends Modifier {
548
552
  * Enables keyboard navigation
549
553
  */
550
554
  @action
551
- activateKeyDown(selectedItem){
555
+ activateKeyDown(selectedItem) {
552
556
  this._selectedItem = selectedItem;
553
557
  this.isKeyDownEnabled = true;
554
558
  }
@@ -612,7 +616,7 @@ export default class SortableGroupModifier extends Modifier {
612
616
  position = this.firstItemPosition;
613
617
  }
614
618
 
615
- sortedItems.forEach(item => {
619
+ sortedItems.forEach((item) => {
616
620
  let dimension;
617
621
  let direction = this.direction;
618
622
 
@@ -642,8 +646,8 @@ export default class SortableGroupModifier extends Modifier {
642
646
  @action
643
647
  commit() {
644
648
  const items = this.sortedItems;
645
- const itemModels = items.map(item => item.model);
646
- const draggedItem = items.find(item => item.wasDropped);
649
+ const itemModels = items.map((item) => item.model);
650
+ const draggedItem = items.find((item) => item.wasDropped);
647
651
  let draggedModel;
648
652
 
649
653
  if (draggedItem) {
@@ -671,17 +675,17 @@ export default class SortableGroupModifier extends Modifier {
671
675
 
672
676
  delete this._firstItemPosition;
673
677
 
674
- run.schedule('render', () => {
675
- items.forEach(item => item.freeze());
678
+ schedule('render', () => {
679
+ items.forEach((item) => item.freeze());
676
680
  });
677
681
 
678
- run.schedule('afterRender', () => {
679
- items.forEach(item => item.reset());
682
+ schedule('afterRender', () => {
683
+ items.forEach((item) => item.reset());
680
684
  });
681
685
 
682
- run.next(() => {
683
- run.schedule('render', () => {
684
- items.forEach(item => item.thaw());
686
+ next(() => {
687
+ schedule('render', () => {
688
+ items.forEach((item) => item.thaw());
685
689
  });
686
690
  });
687
691
  }
@@ -697,24 +701,28 @@ export default class SortableGroupModifier extends Modifier {
697
701
  // end of API
698
702
 
699
703
  addEventListener() {
700
- this.element.addEventListener("keydown", this.keyDown);
701
- this.element.addEventListener("focusout", this.focusOut);
704
+ this.element.addEventListener('keydown', this.keyDown);
705
+ this.element.addEventListener('focusout', this.focusOut);
702
706
  }
703
707
 
704
708
  removeEventListener() {
705
- this.element.removeEventListener("keydown", this.keyDown);
706
- this.element.removeEventListener("focusout", this.focusOut);
709
+ this.element.removeEventListener('keydown', this.keyDown);
710
+ this.element.removeEventListener('focusout', this.focusOut);
707
711
  }
708
712
 
709
713
  didReceiveArguments() {
710
- }
714
+ this.removeEventListener();
711
715
 
712
- didUpdateArguments() {
713
- }
716
+ if (this.disabled) {
717
+ return;
718
+ }
714
719
 
715
- didInstall() {
716
720
  this.addEventListener();
721
+ }
717
722
 
723
+ didUpdateArguments() {}
724
+
725
+ didInstall() {
718
726
  this.announcer = this._createAnnouncer();
719
727
  this.element.insertAdjacentElement('afterend', this.announcer);
720
728
 
@@ -723,12 +731,11 @@ export default class SortableGroupModifier extends Modifier {
723
731
 
724
732
  willRemove() {
725
733
  // todo cleanup the announcer
726
- if(this.announcer.parentNode) {
734
+ if (this.announcer.parentNode) {
727
735
  this.announcer.parentNode.removeChild(this.announcer);
728
736
  }
729
737
  this.removeEventListener();
730
738
 
731
739
  this.sortableService.deregisterGroup(this.groupName, this);
732
740
  }
733
-
734
741
  }
@@ -1,26 +1,24 @@
1
1
  import Modifier from 'ember-modifier';
2
2
 
3
3
  /**
4
- * Modifier to to mark the handle of an item. If this is not supplied the item will be the handle
5
- *
6
- * @module drag-drop/draggable-group
7
- * @example*
8
- * <ol {{sortable-group onChange=this.update a11yAnnouncementConfig=this.myA11yConfig}}>
9
- * {{#each model.items as |item|}}
10
- * <li {{sortable-item model=item}}>
11
- * {{item.name}}
12
- * <span class="handle" {{sortable-handle}}>&varr;</span>
13
- * </li>
14
- * {{/each}}
15
- * </ol>
16
- */
4
+ * Modifier to to mark the handle of an item. If this is not supplied the item will be the handle
5
+ *
6
+ * @module drag-drop/draggable-group
7
+ * @example*
8
+ * <ol {{sortable-group onChange=this.update a11yAnnouncementConfig=this.myA11yConfig}}>
9
+ * {{#each model.items as |item|}}
10
+ * <li {{sortable-item model=item}}>
11
+ * {{item.name}}
12
+ * <span class="handle" {{sortable-handle}}>&varr;</span>
13
+ * </li>
14
+ * {{/each}}
15
+ * </ol>
16
+ */
17
17
  export default class SortableHandleModifier extends Modifier {
18
-
19
18
  didInstall() {
20
19
  // take the model and look up the registered element, the tell that element you are the handle
21
- this.element.dataset.sortableHandle=true;
22
- this.element.tabIndex = "0";
23
- this.element.setAttribute("role", "button");
20
+ this.element.dataset.sortableHandle = true;
21
+ this.element.tabIndex = '0';
22
+ this.element.setAttribute('role', 'button');
24
23
  }
25
-
26
24
  }