ember-sortable 2.4.0 → 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 (36) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +2 -2
  2. package/.github/workflows/github_ci.yml +15 -13
  3. package/CHANGELOG.md +203 -108
  4. package/MIGRATION_GUIDE_MODIFIERS.md +20 -13
  5. package/MIGRATION_GUIDE_V2.md +20 -8
  6. package/README.md +74 -151
  7. package/V2_MIGRATION_RFC.md +188 -222
  8. package/addon/modifiers/sortable-group.js +38 -40
  9. package/addon/modifiers/sortable-handle.js +16 -18
  10. package/addon/modifiers/sortable-item.js +101 -74
  11. package/addon/services/ember-sortable.js +3 -6
  12. package/addon/system/scroll-parent.js +1 -1
  13. package/addon/utils/coordinate.js +1 -1
  14. package/addon/utils/css-calculation.js +2 -2
  15. package/addon/utils/defaults.js +4 -3
  16. package/addon/utils/keyboard.js +3 -12
  17. package/addon-test-support/helpers/drag.js +3 -11
  18. package/addon-test-support/helpers/index.js +1 -4
  19. package/addon-test-support/helpers/reorder.js +4 -6
  20. package/addon-test-support/utils/keyboard.js +3 -12
  21. package/addon-test-support/utils/offset.js +6 -6
  22. package/config/environment.js +2 -2
  23. package/index.js +0 -20
  24. package/package.json +31 -17
  25. package/addon/components/sortable-group.js +0 -741
  26. package/addon/components/sortable-handle.js +0 -30
  27. package/addon/components/sortable-item.js +0 -770
  28. package/addon/styles/components/sortable-group.css +0 -9
  29. package/addon/templates/components/sortable-group.hbs +0 -16
  30. package/addon/templates/components/sortable-handle.hbs +0 -1
  31. package/addon/templates/components/sortable-item.hbs +0 -2
  32. package/addon/utils/transitionend.js +0 -22
  33. package/app/components/sortable-group.js +0 -3
  34. package/app/components/sortable-handle.js +0 -4
  35. package/app/components/sortable-item.js +0 -3
  36. package/vendor/polyfills/closest.js +0 -21
@@ -1,15 +1,18 @@
1
- # Ember Sortable V2 Migration RFC #
1
+ # Ember Sortable V2 Migration RFC
2
+
3
+ ## Author
2
4
 
3
- ## Author ##
4
5
  [ygongdev](https://github.com/ygongdev)
5
6
 
6
- ## Credits ##
7
- * [jgwhite](https://github.com/jgwhite)
8
- * [H1D](https://github.com/H1D)
9
- * [chriskrycho](https://github.com/chriskrycho)
10
- * [Andrew Lee](https://github.com/drewlee)
7
+ ## Credits
8
+
9
+ - [jgwhite](https://github.com/jgwhite)
10
+ - [H1D](https://github.com/H1D)
11
+ - [chriskrycho](https://github.com/chriskrycho)
12
+ - [Andrew Lee](https://github.com/drewlee)
13
+
14
+ ## Table of Content
11
15
 
12
- ## Table of Content ##
13
16
  1. [Problem Statement](#problem-statement)
14
17
  2. [Features](#features)
15
18
  3. [Design/Architecture](#designarchitecture)
@@ -18,51 +21,61 @@
18
21
  6. [Release Plan](#release-plan)
19
22
  7. [Questions to be addressed](#questions-to-be-addressed)
20
23
 
21
- ## Problem Statement ##
24
+ ## Problem Statement
25
+
22
26
  `ember-sortable` has been falling behind in the adoption of the on-going `Ember` upgrades. It is currently not in the right condition, in which we can upgrade the `addon` without many blockers.
23
27
 
24
28
  This RFC is meant to describe a high level overview of a new `ember-sortable`, which will help push us adopt many of the new `Ember` features.
25
29
 
26
30
  This RFC is **NOT** meant to show the final implementation details as implementation will be re-iterated and improved over time.
27
31
 
28
- ## Features ##
29
- * Baked in accessibility support
30
- * Up/down and left/right keyboard navigation
31
- * Screen reader announcement
32
- * Focus management
33
- * Visual indicators
34
- * Direction-agnostic (in terms of mouse drag)
35
- * Keyboard navigation is limited to up/down/left/right
36
- * Allows nested sortable elements
37
- * Adoption of modern Ember testing infrastructure
38
- * Animation
39
- * Built with composability and customizability in mind
40
-
41
- ## Design/Architecture ##
42
- ### 1. Contextual Components ###
32
+ ## Features
33
+
34
+ - Baked in accessibility support
35
+ - Up/down and left/right keyboard navigation
36
+ - Screen reader announcement
37
+ - Focus management
38
+ - Visual indicators
39
+ - Direction-agnostic (in terms of mouse drag)
40
+ - Keyboard navigation is limited to up/down/left/right
41
+ - Allows nested sortable elements
42
+ - Adoption of modern Ember testing infrastructure
43
+ - Animation
44
+ - Built with composability and customizability in mind
45
+
46
+ ## Design/Architecture
47
+
48
+ ### 1. Contextual Components
49
+
43
50
  The new ember sortable will be designed using contextual components.
44
51
  It will be made up of 3 main components:
45
52
 
46
- #### Sortable-group ###
53
+ #### Sortable-group
54
+
47
55
  Represents the entire sortable component.
48
- * requires a group of models to sort. The model will be a shallow copy and will not modify the given group of models.
49
- * contains all of main logic that makes `ember-sortable` work.
50
- * yields `sortable-item` and other properties as needed.
51
56
 
52
- #### Sortable-item ####
57
+ - requires a group of models to sort. The model will be a shallow copy and will not modify the given group of models.
58
+ - contains all of main logic that makes `ember-sortable` work.
59
+ - yields `sortable-item` and other properties as needed.
60
+
61
+ #### Sortable-item
62
+
53
63
  Represents the individual `model` of the group of models.
54
- * yields `sortable-handle` and other properties as needed.
55
64
 
56
- #### Sortable-handle ####
65
+ - yields `sortable-handle` and other properties as needed.
66
+
67
+ #### Sortable-handle
68
+
57
69
  Represents the handle of each `sortable-item`.
58
70
 
59
71
  This is the bread and butter of the entire component because it is the entrypoint that allows us to start sorting.
60
72
 
61
73
  This component hooks up your custom handle to the mainframe, `sortable-group`.
62
74
 
63
- * yields other properties as needed.
75
+ - yields other properties as needed.
76
+
77
+ #### Conceptual Example
64
78
 
65
- #### Conceptual Example ####
66
79
  ```javascript
67
80
  {{#ember-sortable::sortable-group
68
81
  modelGroup=modelGroup
@@ -87,73 +100,91 @@ This component hooks up your custom handle to the mainframe, `sortable-group`.
87
100
  {{/ember-sortable::sortable-group}}
88
101
  ```
89
102
 
90
- ### 2. Event driven ###
103
+ ### 2. Event driven
104
+
91
105
  Similar to the current `ember-sortable`, the sorting behavior is going to be mainly based on `events`. `Animation` might be an exception.
92
106
  We will utilize the [Drag and Drop API](https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API), [Keyboard Event API](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent), and/or [Mouse Event API](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent).
93
107
 
94
- ### 3. Animation ###
108
+ ### 3. Animation
109
+
95
110
  For `animation`, we can explore different methods, e.g custom implementation, external animation library. However, the final decision will hopefully satisify the following:
96
- * minimize expensive DOM operations, e.g `getComputedStyle`, `Ember runloop scheduling`.
97
- * If we want to test animations, the `animation` have to be deterministic enough for us to test reliably.
98
111
 
99
- ### 4. Accessibility ###
112
+ - minimize expensive DOM operations, e.g `getComputedStyle`, `Ember runloop scheduling`.
113
+ - If we want to test animations, the `animation` have to be deterministic enough for us to test reliably.
114
+
115
+ ### 4. Accessibility
116
+
100
117
  This section provides a high level overview of how we will address the issue of `accessibility`.
101
118
 
102
119
  **The accessibility solutions described are directly referenced from this awesome [codepen demo](https://codepen.io/drewlee/project/full/XWNLeE) made by Andrew Lee.**
103
120
 
104
- #### Keyboard Navigation ####
121
+ #### Keyboard Navigation
122
+
105
123
  **1. Keyboard Reorder Mode**
106
- * To initiate `keyboardReorderMode`, a `sortable-handle` must be `focused` and an `Enter/Space` must be pressed.
107
- * This operation selects `sortable-item` parent of the `sortable-handle` and enable sorting the `sortable-item` within the `sortable-group` via up/down/left/right arrow keys.
108
- * We will set `sortable-group` as a dedicated `container` by adding `role` attribute and programmatically set the `focus` onto it.
109
- * We will create a `visual color indicator` around the selected `sortable-item`. A screen reader announcement will also be made to inform the user that the `sortable-item` has been selected and `sorting` has been enabled.
110
- * To create `visual indicators`, `sortable-item` will append some `classes`, which by default tries to create `arrow` visual indcators around `sortable-item`. However, consumers are free to override the `class` to customize their own. `Visual indicators` will move as the`sortable-item` moves.
124
+
125
+ - To initiate `keyboardReorderMode`, a `sortable-handle` must be `focused` and an `Enter/Space` must be pressed.
126
+ - This operation selects `sortable-item` parent of the `sortable-handle` and enable sorting the `sortable-item` within the `sortable-group` via up/down/left/right arrow keys.
127
+ - We will set `sortable-group` as a dedicated `container` by adding `role` attribute and programmatically set the `focus` onto it.
128
+ - We will create a `visual color indicator` around the selected `sortable-item`. A screen reader announcement will also be made to inform the user that the `sortable-item` has been selected and `sorting` has been enabled.
129
+ - To create `visual indicators`, `sortable-item` will append some `classes`, which by default tries to create `arrow` visual indcators around `sortable-item`. However, consumers are free to override the `class` to customize their own. `Visual indicators` will move as the`sortable-item` moves.
111
130
 
112
131
  **2. Commit**
113
- * Every navigation will reorder the components in the UI. However, the reorder will not be `committed` until an `Enter/Space` key has been pressed. If committed, the `focus` will move from the `sortable-group` back to the `sortable-handle`. `role` will be removed.
132
+
133
+ - Every navigation will reorder the components in the UI. However, the reorder will not be `committed` until an `Enter/Space` key has been pressed. If committed, the `focus` will move from the `sortable-group` back to the `sortable-handle`. `role` will be removed.
114
134
 
115
135
  **3. Reset**
116
- * The user can also exit `keyboardReorderMode` via `Escape` key or on focus lost. This will reset the reordering back to its initial state and `focus` is retained on the `sortable-handle`. `role` will be removed.
117
- * We should not need animation for this.
118
136
 
119
- #### Drag Drop ####
137
+ - The user can also exit `keyboardReorderMode` via `Escape` key or on focus lost. This will reset the reordering back to its initial state and `focus` is retained on the `sortable-handle`. `role` will be removed.
138
+ - We should not need animation for this.
139
+
140
+ #### Drag Drop
141
+
120
142
  Drag drop will retain the same behavior as the current `ember-sortable`.
121
143
 
122
- #### Screen Reader Announcements #####
123
- * Internally, we can use a `announceActionConfig` object to map an `action` to a `text`. We can have some default texts.
124
- * To support `i18n`, the consumer can supply their own `announceActionConfig` with their translated strings.
144
+ #### Screen Reader Announcements
145
+
146
+ - Internally, we can use a `announceActionConfig` object to map an `action` to a `text`. We can have some default texts.
147
+ - To support `i18n`, the consumer can supply their own `announceActionConfig` with their translated strings.
148
+
149
+ ### 5. Utility Classes and Functions
125
150
 
126
- ### 5. Utility Classes and Functions ###
127
151
  We should create a utility class to abstract as much work as we can from the components.
128
152
 
129
153
  For example, a `keyboardManager` class can be used to maintain a history of our operations as well as provide the functionalities to perform the reordering logic during `keyboard navigation`.
130
154
 
131
- ### 6. Testing ###
155
+ ### 6. Testing
156
+
132
157
  The current `ember-sortable` implements two test helpers
133
- * reorder
134
- * drag
158
+
159
+ - reorder
160
+ - drag
135
161
 
136
162
  Both are heavily DOM calculation driven and can sometimes be hard and unreliable to use.
137
163
 
138
164
  I propose new `event driven` test helpers and perhaps remove `reorder` as it is just a combination of `drag`. Internally, these would be just triggering `events`, which should be determinstic to test.
139
- * drag (for mouse)
140
- * move (for keyboard)
141
- * reorder?
165
+
166
+ - drag (for mouse)
167
+ - move (for keyboard)
168
+ - reorder?
142
169
 
143
170
  We can implement another `drag` that is dedicated to testing `animation`.
144
171
 
145
- ## API ###
172
+ ## API
173
+
146
174
  TBD
147
175
 
148
- ## Implementation ##
176
+ ## Implementation
177
+
149
178
  **NOTE**
150
179
  This is an example to help give an idea of what it could look like.
151
180
  This is **NOT** meant to be the final implementation.
152
181
  This example does **NOT** contain how we would handle animation and horizontal keyboard sorting.
153
182
  While creating this, I used the name `draggable` instead of `ember-sortable`.
154
183
 
155
- ### draggable-group ###
156
- #### hbs ####
184
+ ### draggable-group
185
+
186
+ #### hbs
187
+
157
188
  ```javascript
158
189
  {{yield
159
190
  (hash
@@ -172,7 +203,8 @@ While creating this, I used the name `draggable` instead of `ember-sortable`.
172
203
  }}
173
204
  ```
174
205
 
175
- #### js ####
206
+ #### js
207
+
176
208
  ```javascript
177
209
  /**
178
210
  * This component supports re-ordering items in a group via drag-drop and keyboard navigation.
@@ -210,11 +242,7 @@ While creating this, I used the name `draggable` instead of `ember-sortable`.
210
242
  */
211
243
  export default Component.extend({
212
244
  layout,
213
- attributeBindings: [
214
- 'tabindex',
215
- 'role',
216
- 'dataTestDragDropDraggableGroup:data-test-drag-drop-draggable-group',
217
- ],
245
+ attributeBindings: ['tabindex', 'role', 'dataTestDragDropDraggableGroup:data-test-drag-drop-draggable-group'],
218
246
  // data-test selector
219
247
  dataTestDragDropDraggableGroup: true,
220
248
  /**
@@ -264,10 +292,7 @@ export default Component.extend({
264
292
  * @param {Event} evt a HTML event
265
293
  */
266
294
  keyDown(evt) {
267
- const isKeyboardReorderModeEnabled = get(
268
- this,
269
- 'isKeyboardReorderModeEnabled'
270
- );
295
+ const isKeyboardReorderModeEnabled = get(this, 'isKeyboardReorderModeEnabled');
271
296
 
272
297
  if (!isKeyboardReorderModeEnabled && (isEnterKey(evt) || isSpaceKey(evt))) {
273
298
  this._enableKeyboardReorderMode();
@@ -286,11 +311,7 @@ export default Component.extend({
286
311
  }
287
312
 
288
313
  if (isKeyboardReorderModeEnabled) {
289
- const { selectedModelIndex, maxIndex } = getProperties(
290
- this,
291
- 'selectedModelIndex',
292
- 'maxIndex'
293
- );
314
+ const { selectedModelIndex, maxIndex } = getProperties(this, 'selectedModelIndex', 'maxIndex');
294
315
  if (isDownArrowKey(evt)) {
295
316
  const newIndex = Math.min(selectedModelIndex + 1, maxIndex - 1);
296
317
  this._moveItem(selectedModelIndex, newIndex);
@@ -321,9 +342,7 @@ export default Component.extend({
321
342
 
322
343
  readDOM(() => {
323
344
  if (IS_BROWSER) {
324
- this.element
325
- .querySelectorAll(`[${DRAGGABLE_HANDLE_ATTRIBUTE}]`)
326
- [selectedModelIndex].focus();
345
+ this.element.querySelectorAll(`[${DRAGGABLE_HANDLE_ATTRIBUTE}]`)[selectedModelIndex].focus();
327
346
  set(this, 'isRetainingFocus', false);
328
347
  }
329
348
  });
@@ -339,9 +358,7 @@ export default Component.extend({
339
358
 
340
359
  readDOM(() => {
341
360
  if (IS_BROWSER) {
342
- this.element
343
- .querySelectorAll(`[${DRAGGABLE_HANDLE_ATTRIBUTE}]`)
344
- [lastIndex].focus();
361
+ this.element.querySelectorAll(`[${DRAGGABLE_HANDLE_ATTRIBUTE}]`)[lastIndex].focus();
345
362
  set(this, 'isRetainingFocus', false);
346
363
  }
347
364
  });
@@ -357,11 +374,7 @@ export default Component.extend({
357
374
  * If focus management is not finished and the current focused element is not the handle or descendant of the handle: Cancel
358
375
  */
359
376
  focusOut(evt) {
360
- if (
361
- IS_BROWSER &&
362
- !get(this, 'isRetainingFocus') &&
363
- !this._isElementWithinHandle(document.activeElement)
364
- ) {
377
+ if (IS_BROWSER && !get(this, 'isRetainingFocus') && !this._isElementWithinHandle(document.activeElement)) {
365
378
  this._cancelKeyboardSelection();
366
379
  }
367
380
  evt.stopPropagation();
@@ -414,27 +427,17 @@ export default Component.extend({
414
427
  const dropTarget = evt.target;
415
428
  evt.preventDefault();
416
429
  if (this._isElementWithinDrop(dropTarget)) {
417
- const {
418
- keyboardReorderManager,
419
- selectedModel,
420
- selectedModelIndex,
421
- targetModel,
422
- targetModelIndex,
423
- } = getProperties(
424
- this,
425
- 'keyboardReorderManager',
426
- 'selectedModel',
427
- 'selectedModelIndex',
428
- 'targetModel',
429
- 'targetModelIndex'
430
- );
430
+ const { keyboardReorderManager, selectedModel, selectedModelIndex, targetModel, targetModelIndex } =
431
+ getProperties(
432
+ this,
433
+ 'keyboardReorderManager',
434
+ 'selectedModel',
435
+ 'selectedModelIndex',
436
+ 'targetModel',
437
+ 'targetModelIndex'
438
+ );
431
439
  this._moveItem(selectedModelIndex, targetModelIndex);
432
- tryInvoke(this, 'onSubmit', [
433
- selectedModel,
434
- selectedModelIndex,
435
- targetModel,
436
- targetModelIndex,
437
- ]);
440
+ tryInvoke(this, 'onSubmit', [selectedModel, selectedModelIndex, targetModel, targetModelIndex]);
438
441
  keyboardReorderManager.clearRecord();
439
442
  }
440
443
  this._resetModelSelection();
@@ -452,13 +455,7 @@ export default Component.extend({
452
455
  * 6. Announce the change.
453
456
  */
454
457
  _confirmKeyboardSelection() {
455
- const {
456
- keyboardReorderManager,
457
- selectedModel,
458
- selectedModelIndex,
459
- targetModel,
460
- targetModelIndex,
461
- } = getProperties(
458
+ const { keyboardReorderManager, selectedModel, selectedModelIndex, targetModel, targetModelIndex } = getProperties(
462
459
  this,
463
460
  'keyboardReorderManager',
464
461
  'selectedModel',
@@ -471,12 +468,7 @@ export default Component.extend({
471
468
  this._disableKeyboardReorderMode();
472
469
  this._tearDownA11yApplicationContainer();
473
470
 
474
- tryInvoke(this, 'onSubmit', [
475
- selectedModel,
476
- selectedModelIndex,
477
- targetModel,
478
- targetModelIndex,
479
- ]);
471
+ tryInvoke(this, 'onSubmit', [selectedModel, selectedModelIndex, targetModel, targetModelIndex]);
480
472
 
481
473
  this._resetModelSelection();
482
474
  this._announceAction(ANNOUNCEMENT_ACTION_TYPES.CONFIRM);
@@ -576,9 +568,7 @@ export default Component.extend({
576
568
  * @param {Element} element a DOM element.
577
569
  */
578
570
  _isElementWithinHandle(element) {
579
- return element.closest(
580
- `#${this.element.id} [${DRAGGABLE_HANDLE_ATTRIBUTE}]`
581
- );
571
+ return element.closest(`#${this.element.id} [${DRAGGABLE_HANDLE_ATTRIBUTE}]`);
582
572
  },
583
573
 
584
574
  /**
@@ -599,10 +589,7 @@ export default Component.extend({
599
589
  * @return {Function}
600
590
  */
601
591
  _geti18nMessage(key, data) {
602
- const messageRenderer = get(this, 'i18n').getMessageRenderer(
603
- get(this, 'layout'),
604
- key
605
- );
592
+ const messageRenderer = get(this, 'i18n').getMessageRenderer(get(this, 'layout'), key);
606
593
  return messageRenderer([data]);
607
594
  },
608
595
 
@@ -703,8 +690,10 @@ export default Component.extend({
703
690
  });
704
691
  ```
705
692
 
706
- ### draggable-item ###
707
- #### hbs ####
693
+ ### draggable-item
694
+
695
+ #### hbs
696
+
708
697
  ```javascript
709
698
  {{yield
710
699
  (hash
@@ -721,7 +710,8 @@ export default Component.extend({
721
710
  }}
722
711
  ```
723
712
 
724
- #### js ####
713
+ #### js
714
+
725
715
  ```javascript
726
716
  /**
727
717
  * This private component represents the individual model of `draggable-group`.
@@ -762,11 +752,7 @@ export default Component.extend({
762
752
  * @param {Integer} index the position of this model in the DOM.
763
753
  */
764
754
  isSelected: computed('selectedModelIndex', 'index', function getIsSelected() {
765
- const { selectedModelIndex, index } = getProperties(
766
- this,
767
- 'selectedModelIndex',
768
- 'index'
769
- );
755
+ const { selectedModelIndex, index } = getProperties(this, 'selectedModelIndex', 'index');
770
756
 
771
757
  return selectedModelIndex === index;
772
758
  }),
@@ -790,12 +776,7 @@ export default Component.extend({
790
776
  * @param {Event} evt a HTML event.
791
777
  */
792
778
  keyDown(evt) {
793
- const {
794
- isKeyboardReorderModeEnabled,
795
- model,
796
- selectedModelIndex,
797
- index,
798
- } = getProperties(
779
+ const { isKeyboardReorderModeEnabled, model, selectedModelIndex, index } = getProperties(
799
780
  this,
800
781
  'isKeyboardReorderModeEnabled',
801
782
  'model',
@@ -805,8 +786,7 @@ export default Component.extend({
805
786
 
806
787
  if (
807
788
  selectedModelIndex < 0 &&
808
- (isKeyboardReorderModeEnabled ||
809
- (!isKeyboardReorderModeEnabled && (isEnterKey(evt) || isSpaceKey(evt))))
789
+ (isKeyboardReorderModeEnabled || (!isKeyboardReorderModeEnabled && (isEnterKey(evt) || isSpaceKey(evt))))
810
790
  ) {
811
791
  this.onSelect(model, index);
812
792
  }
@@ -837,14 +817,8 @@ export default Component.extend({
837
817
  * Asserts that required properties are defined correctly.
838
818
  */
839
819
  _assertProperties() {
840
- assert(
841
- 'isKeyboardReorderModeEnabled is required',
842
- get(this, 'isKeyboardReorderModeEnabled') !== undefined
843
- );
844
- assert(
845
- 'selectedModelIndex is required',
846
- get(this, 'selectedModelIndex') !== undefined
847
- );
820
+ assert('isKeyboardReorderModeEnabled is required', get(this, 'isKeyboardReorderModeEnabled') !== undefined);
821
+ assert('selectedModelIndex is required', get(this, 'selectedModelIndex') !== undefined);
848
822
  assert('maxIndex is required', get(this, 'maxIndex') !== undefined);
849
823
  assert('itemName is required', get(this, 'itemName') !== undefined);
850
824
  },
@@ -881,13 +855,21 @@ export default Component.extend({
881
855
  });
882
856
  ```
883
857
 
884
- ### draggable-handle ###
885
- #### hbs ####
858
+ ### draggable-handle
859
+
860
+ #### hbs
861
+
886
862
  ```javascript
887
- {{yield}}
888
- <span class="visually-hidden">{{a11yText}}</span>
863
+ {
864
+ {
865
+ yield;
866
+ }
867
+ }
868
+ <span class="visually-hidden">{{ a11yText }}</span>;
889
869
  ```
890
- #### js #####
870
+
871
+ #### js
872
+
891
873
  ```javascript
892
874
  /**
893
875
  * This private component represents the `handle` for each `draggable-item` of a `draggable-group`.
@@ -908,10 +890,7 @@ export default Component.extend({
908
890
  */
909
891
  tagName: 'div',
910
892
  tabindex: 0,
911
- classNameBindings: [
912
- 'showA11yPreviousArrow:drag-drop__handle-previous',
913
- 'showA11yNextArrow:drag-drop__handle-next',
914
- ],
893
+ classNameBindings: ['showA11yPreviousArrow:drag-drop__handle-previous', 'showA11yNextArrow:drag-drop__handle-next'],
915
894
  attributeBindings: [
916
895
  `dataDragDropHandle:${DRAGGABLE_HANDLE_ATTRIBUTE}`,
917
896
  'tabindex',
@@ -937,19 +916,13 @@ export default Component.extend({
937
916
  'selectedIndex',
938
917
  'isKeyboardReorderModeEnabled',
939
918
  function getShowA11yPreviousArrow() {
940
- const {
941
- index,
942
- selectedIndex,
943
- isKeyboardReorderModeEnabled,
944
- } = getProperties(
919
+ const { index, selectedIndex, isKeyboardReorderModeEnabled } = getProperties(
945
920
  this,
946
921
  'index',
947
922
  'selectedIndex',
948
923
  'isKeyboardReorderModeEnabled'
949
924
  );
950
- return (
951
- isKeyboardReorderModeEnabled && selectedIndex === index && index > 0
952
- );
925
+ return isKeyboardReorderModeEnabled && selectedIndex === index && index > 0;
953
926
  }
954
927
  ),
955
928
 
@@ -969,23 +942,14 @@ export default Component.extend({
969
942
  'maxIndex',
970
943
  'isKeyboardReorderModeEnabled',
971
944
  function getShowA11yNextArrow() {
972
- const {
973
- index,
974
- selectedIndex,
975
- maxIndex,
976
- isKeyboardReorderModeEnabled,
977
- } = getProperties(
945
+ const { index, selectedIndex, maxIndex, isKeyboardReorderModeEnabled } = getProperties(
978
946
  this,
979
947
  'index',
980
948
  'maxIndex',
981
949
  'selectedIndex',
982
950
  'isKeyboardReorderModeEnabled'
983
951
  );
984
- return (
985
- isKeyboardReorderModeEnabled &&
986
- selectedIndex === index &&
987
- index < maxIndex - 1
988
- );
952
+ return isKeyboardReorderModeEnabled && selectedIndex === index && index < maxIndex - 1;
989
953
  }
990
954
  ),
991
955
 
@@ -1010,14 +974,8 @@ export default Component.extend({
1010
974
  assert(`a11yText is required`, get(this, 'a11yText'));
1011
975
  assert(`index is required`, get(this, 'index') !== undefined);
1012
976
  assert(`maxIndex is required`, get(this, 'maxIndex') !== undefined);
1013
- assert(
1014
- `selectedIndex is required`,
1015
- get(this, 'selectedIndex') !== undefined
1016
- );
1017
- assert(
1018
- `isKeyboardReorderModeEnabled is required`,
1019
- get(this, 'isKeyboardReorderModeEnabled') !== undefined
1020
- );
977
+ assert(`selectedIndex is required`, get(this, 'selectedIndex') !== undefined);
978
+ assert(`isKeyboardReorderModeEnabled is required`, get(this, 'isKeyboardReorderModeEnabled') !== undefined);
1021
979
  },
1022
980
 
1023
981
  /**
@@ -1036,19 +994,21 @@ export default Component.extend({
1036
994
  });
1037
995
  ```
1038
996
 
1039
- ### utils/constants.js ###
997
+ ### utils/constants.js
998
+
1040
999
  ```javascript
1041
- export const DRAGGABLE_HANDLE_ATTRIBUTE = 'data-drag-drop-draggable-handle';
1042
- export const DRAGGABLE_ITEM_ATTRIBUTE = 'data-drag-drop-draggable-item';
1000
+ export const DRAGGABLE_HANDLE_ATTRIBUTE = 'data-drag-drop-draggable-handle';
1001
+ export const DRAGGABLE_ITEM_ATTRIBUTE = 'data-drag-drop-draggable-item';
1043
1002
  export const ANNOUNCEMENT_ACTION_TYPES = {
1044
1003
  ACTIVATE: true,
1045
1004
  MOVE: true,
1046
1005
  CONFIRM: true,
1047
1006
  CANCEL: true,
1048
- }
1007
+ };
1049
1008
  ```
1050
1009
 
1051
- ### utils/keyboard-reorder-manager.js ###
1010
+ ### utils/keyboard-reorder-manager.js
1011
+
1052
1012
  ```javascript
1053
1013
  class ReorderRecord {
1054
1014
  constructor(fromIndex, toIndex) {
@@ -1100,35 +1060,41 @@ export default class KeyboardReorderManager {
1100
1060
  }
1101
1061
  ```
1102
1062
 
1103
- ## Release Plan ##
1104
- ### 2.0 ###
1105
- * New API with backward incompatible changes
1106
- * Drag drop
1107
- * Animation
1108
- * Test helper
1109
- * Test Infrastructure Modernization
1110
- * remove `registerAsyncHelper`
1111
- * `module` and `setupHooks` syntax
1112
- * Remove `jQuery` in favor of vanilla.
1113
- * Migration Guide
1114
- * 1.x.x -> 2.x.x
1115
-
1116
- ### 2.1 ###
1117
- * Keyboard support
1118
- * Keyboard navigation (left/right/up/down)
1119
- * Commit
1120
- * Reset
1121
-
1122
- ### 2.2 ###
1123
- * Accessibility support
1124
- * Screen reader announcements
1125
- * Focus management
1126
- * Semantic markup and attributes
1127
-
1128
- ### 2.3 ###
1129
- * Nesting support
1130
-
1131
- ## Questions to be addressed ##
1063
+ ## Release Plan
1064
+
1065
+ ### 2.0
1066
+
1067
+ - New API with backward incompatible changes
1068
+ - Drag drop
1069
+ - Animation
1070
+ - Test helper
1071
+ - Test Infrastructure Modernization
1072
+ - remove `registerAsyncHelper`
1073
+ - `module` and `setupHooks` syntax
1074
+ - Remove `jQuery` in favor of vanilla.
1075
+ - Migration Guide
1076
+ - 1.x.x -> 2.x.x
1077
+
1078
+ ### 2.1
1079
+
1080
+ - Keyboard support
1081
+ - Keyboard navigation (left/right/up/down)
1082
+ - Commit
1083
+ - Reset
1084
+
1085
+ ### 2.2
1086
+
1087
+ - Accessibility support
1088
+ - Screen reader announcements
1089
+ - Focus management
1090
+ - Semantic markup and attributes
1091
+
1092
+ ### 2.3
1093
+
1094
+ - Nesting support
1095
+
1096
+ ## Questions to be addressed
1097
+
1132
1098
  1. With the introduction of Ember Octane and glimmer components, should we use any of their features? How backward compatible should this be?
1133
1099
 
1134
1100
  2. Will an external animation library be of high value to us? If so, will the extra overhead be problematic?