ember-sortable 2.2.4 → 2.4.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.
- package/.huskyrc +0 -1
- package/CHANGELOG.md +40 -0
- package/README.md +37 -16
- package/addon/components/sortable-group.js +25 -10
- package/addon/components/sortable-handle.js +19 -0
- package/addon/components/sortable-item.js +25 -8
- package/addon/modifiers/sortable-group.js +26 -17
- package/addon/modifiers/sortable-item.js +33 -20
- package/addon/templates/components/sortable-group.hbs +2 -2
- package/addon/utils/defaults.js +25 -0
- package/index.js +8 -0
- package/package.json +5 -5
- package/jsconfig.json +0 -1
package/.huskyrc
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,43 @@
|
|
|
1
|
+
## v2.4.0 (2021-11-10)
|
|
2
|
+
|
|
3
|
+
#### :rocket: Enhancement
|
|
4
|
+
* [#445](https://github.com/adopted-ember-addons/ember-sortable/pull/445) Use direct imports from `@ember/runloop` ([@charlesfries](https://github.com/charlesfries))
|
|
5
|
+
|
|
6
|
+
#### Committers: 2
|
|
7
|
+
- Charles Fries ([@charlesfries](https://github.com/charlesfries))
|
|
8
|
+
- Faith Or ([@faith-or](https://github.com/faith-or))
|
|
9
|
+
|
|
10
|
+
* Merge pull request #430 from jacojoubert/refactor-disabled (364fc80)
|
|
11
|
+
* (51ea46f)
|
|
12
|
+
* Merge pull request #444 from snewcomer/sn/deprecate-components (b70d5cd)
|
|
13
|
+
* Deprecate use of components (ffbd488)
|
|
14
|
+
* Add deprecation warning for `isDraggingDisabled` (ad38e58)
|
|
15
|
+
* Reset sortable-item (cebbe62)
|
|
16
|
+
* Merge pull request #440 from ntnz/patch-2 (2cbc2b5)
|
|
17
|
+
* Merge branch 'master' into refactor-disabled (0f315a6)
|
|
18
|
+
* Merge branch 'master' into refactor-disabled (36aa312)
|
|
19
|
+
* Fix syntax issues in readme (d2f8cc9)
|
|
20
|
+
* Update README.md (c0e88e7)
|
|
21
|
+
* Add disabled argument to sortable-item (888dc5c)
|
|
22
|
+
* Add examples of disabled item (4db5107)
|
|
23
|
+
|
|
24
|
+
## v2.2.6 (2021-10-21)
|
|
25
|
+
|
|
26
|
+
#### :bug: Bug Fix
|
|
27
|
+
* [#439](https://github.com/adopted-ember-addons/ember-sortable/pull/439) Resolve this-property-fallback deprecation ([@rmachielse](https://github.com/rmachielse))
|
|
28
|
+
* [#434](https://github.com/adopted-ember-addons/ember-sortable/pull/434) Update ember-cli-babel to @7.26.6, update README example ([@charlesfries](https://github.com/charlesfries))
|
|
29
|
+
|
|
30
|
+
#### Committers: 4
|
|
31
|
+
- Charles Fries ([@charlesfries](https://github.com/charlesfries))
|
|
32
|
+
- Jaco Joubert ([@jacojoubert](https://github.com/jacojoubert))
|
|
33
|
+
- Richard Machielse ([@rmachielse](https://github.com/rmachielse))
|
|
34
|
+
- Scott Newcomer ([@snewcomer](https://github.com/snewcomer))
|
|
35
|
+
|
|
36
|
+
* updated yarn.lock (ca925fa)
|
|
37
|
+
* Fix deprecation warning `Importing from ember-test-waiters is deprecated` (#423) (f817c5d)
|
|
38
|
+
* Require ember-decorators-polyfill to be installed by client app (#425) (f901543)
|
|
39
|
+
* Set default values for itemVisualClass and a11yAnnouncementConfig (#424) (436b7ac)
|
|
40
|
+
|
|
1
41
|
* update yarn.lock (a18d3cb)
|
|
2
42
|
* bump ember-get-config to version using babel v7 (#416) (92dd9b9)
|
|
3
43
|
|
package/README.md
CHANGED
|
@@ -24,6 +24,8 @@ For modifiers, please read this [migration guide](/MIGRATION_GUIDE_MODIFIERS.md)
|
|
|
24
24
|
|
|
25
25
|
In version 2.0.0+, our `closest` polyfill seems to break some app's `production` build. To mitigate this, the `closest` polyfill will only enabled if it doesn't break the `production` build (if the `polyfill` file is recognized by the build). Affected apps will need to supply their own [closest](https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill) polyfill to ensure compatibility with IE. This issue is tracked [here](https://github.com/adopted-ember-addons/ember-sortable/issues/333).
|
|
26
26
|
|
|
27
|
+
We require the `ember-decorators-polyfill` to be installed if you are using this addon with versions of Ember < 3.10.0.
|
|
28
|
+
|
|
27
29
|
Version 1.0 depends upon the availability of 2D CSS transforms.
|
|
28
30
|
Check [the matrix on caniuse.com](http://caniuse.com/#feat=transforms2d)
|
|
29
31
|
to see if your target browsers are compatible.
|
|
@@ -36,23 +38,23 @@ $ ember install ember-sortable
|
|
|
36
38
|
|
|
37
39
|
## Usage
|
|
38
40
|
|
|
39
|
-
### component
|
|
41
|
+
### component
|
|
40
42
|
```hbs
|
|
41
43
|
{{! app/templates/my-route.hbs }}
|
|
42
44
|
|
|
43
|
-
|
|
45
|
+
<SortableGroup @model={{this.model.items}} @onChange={{this.reorderItems}} as |group|>
|
|
44
46
|
{{#each group.model as |modelItem|}}
|
|
45
|
-
|
|
47
|
+
<group.item @model={{modelItem}} as |item|>
|
|
46
48
|
{{modelItem.name}}
|
|
47
|
-
|
|
49
|
+
<item.handle>
|
|
48
50
|
<span class="handle">↕</span>
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
</item.handle>
|
|
52
|
+
</group.item>
|
|
51
53
|
{{/each}}
|
|
52
|
-
|
|
54
|
+
</SortableGroup>
|
|
53
55
|
```
|
|
54
56
|
|
|
55
|
-
### modifier
|
|
57
|
+
### modifier
|
|
56
58
|
```hbs
|
|
57
59
|
{{! app/templates/my-route.hbs }}
|
|
58
60
|
|
|
@@ -178,9 +180,18 @@ modifier
|
|
|
178
180
|
<li {{sortable-item distance=30}}>
|
|
179
181
|
```
|
|
180
182
|
|
|
183
|
+
### Disabling reordering
|
|
184
|
+
|
|
185
|
+
The `disabled` attribute allows you to disable sorting for the entire group and its child items.
|
|
186
|
+
|
|
187
|
+
modifier
|
|
188
|
+
```hbs
|
|
189
|
+
<li {{sortable-group disabled=true}}>
|
|
190
|
+
```
|
|
191
|
+
|
|
181
192
|
### CSS, Animation
|
|
182
193
|
|
|
183
|
-
Sortable items can be in one of
|
|
194
|
+
Sortable items can be in one of four states: default, dragging, dropping, and activated.
|
|
184
195
|
The classes look like this:
|
|
185
196
|
|
|
186
197
|
```html
|
|
@@ -190,6 +201,8 @@ The classes look like this:
|
|
|
190
201
|
<li class="sortable-item is-dragging">...</li>
|
|
191
202
|
<!-- Dropping -->
|
|
192
203
|
<li class="sortable-item is-dropping">...</li>
|
|
204
|
+
<!-- Keyboard -->
|
|
205
|
+
<li class="sortable-item is-activated">...</li>
|
|
193
206
|
```
|
|
194
207
|
|
|
195
208
|
In our [example app.css](tests/dummy/app/styles/app.css) we apply a
|
|
@@ -225,6 +238,9 @@ slightly different colour:
|
|
|
225
238
|
}
|
|
226
239
|
```
|
|
227
240
|
|
|
241
|
+
If the user presses space to activate and move an item via the keyboard, `is-activated` is added. Once the user drops the item it is
|
|
242
|
+
removed. Use this class to add a visual indicator that the item is selected and being manipulated.
|
|
243
|
+
|
|
228
244
|
### Drag Actions
|
|
229
245
|
|
|
230
246
|
The `onDragStart` and `onDragStop` actions are available for the
|
|
@@ -276,7 +292,7 @@ modifier
|
|
|
276
292
|
</li>
|
|
277
293
|
```
|
|
278
294
|
|
|
279
|
-
### Multiple Ember-Sortables renders simultaneously (Modifier version)
|
|
295
|
+
### Multiple Ember-Sortables renders simultaneously (Modifier version)
|
|
280
296
|
|
|
281
297
|
The modifier version uses a service behind the scenes for communication between the group and the items and to maintain state. It does this seemlessly when the elements are rendered on the screen. However, if there are two sortables rendered at the same time, either in the same component or different components, the state management does not know which items belong to which group.
|
|
282
298
|
|
|
@@ -310,8 +326,10 @@ Ensure that the same name is passed to both the group and the items, this would
|
|
|
310
326
|
|
|
311
327
|
|
|
312
328
|
### Disabling Drag (Experimental)
|
|
313
|
-
`sortable-item` (component and modifier) exposes an optional `isDraggingDisabled` flag that you can use to disable
|
|
329
|
+
`sortable-item` (component and modifier) exposes an optional `disabled` (previously `isDraggingDisabled`) flag that you can use to disable reordering for that particular item. Disabling and item won't prevent it from changing position in the array. The user can still move other non-disabled items to over it.
|
|
330
|
+
|
|
314
331
|
This flag is intended as an utility to make your life easier with 3 main benefits:
|
|
332
|
+
|
|
315
333
|
1. You can now specify which `sortable-item` are not intended to be draggable/sortable.
|
|
316
334
|
2. You do not have to duplicate the `sortable-item` UI just for the purpose of disabling the `sorting` behavior.
|
|
317
335
|
3. Allows you to access the entire list of `models` for your `onChange` action, which can now be a mix of sortable and non-sortable items.
|
|
@@ -334,8 +352,8 @@ component
|
|
|
334
352
|
an ordered list, `ol`, by default.
|
|
335
353
|
- `sortable-item`
|
|
336
354
|
a list item, `li`, by default.
|
|
337
|
-
|
|
338
|
-
The modifier version can be attached to to any element that makes sense,
|
|
355
|
+
|
|
356
|
+
The modifier version can be attached to to any element that makes sense,
|
|
339
357
|
|
|
340
358
|
##### Keyboard Navigation
|
|
341
359
|
There are 4 modes during keyboard navigation:
|
|
@@ -358,8 +376,11 @@ There are 4 modes during keyboard navigation:
|
|
|
358
376
|
|
|
359
377
|
#### User configurable
|
|
360
378
|
##### Screen Reader
|
|
379
|
+
|
|
380
|
+
The default language for `ember-sortable` is English. Any language can be supported by passing in the configuration below in the appropriate language.
|
|
381
|
+
|
|
361
382
|
- **a11yItemName**
|
|
362
|
-
a name for the item.
|
|
383
|
+
a name for the item. Defaults to `item`.
|
|
363
384
|
- **a11yAnnouncementConfig**
|
|
364
385
|
a map of `action enums` to `functions` that takes the following `config`, which is exposed by `sortable-group`.
|
|
365
386
|
```javascript
|
|
@@ -373,7 +394,7 @@ a11yAnnounceConfig = {
|
|
|
373
394
|
```
|
|
374
395
|
and returns a `string` constructed from the `config`.
|
|
375
396
|
|
|
376
|
-
**
|
|
397
|
+
**Default value**
|
|
377
398
|
```javascript
|
|
378
399
|
{
|
|
379
400
|
ACTIVATE: function({ a11yItemName, index, maxLength, direction }) {
|
|
@@ -405,7 +426,7 @@ and returns a `string` constructed from the `config`.
|
|
|
405
426
|
This class will be added to the `sortable-handle` during `ACTIVATE` and `MOVE` operations. This allows you to add custom styles such as `visual arrows` via `pseudo` classes.
|
|
406
427
|
|
|
407
428
|
- **itemVisualClass**
|
|
408
|
-
This class will be added to the `sortable-item` during `ACTIVATE` and `MOVE` operations. This is needed to creating a `visual indicator` that mimics `focus` b/c the native `focus` is on the container.
|
|
429
|
+
This class will be added to the `sortable-item` during `ACTIVATE` and `MOVE` operations. The default class added is `is-activated`. This is needed to creating a `visual indicator` that mimics `focus` b/c the native `focus` is on the container.
|
|
409
430
|
|
|
410
431
|
## Testing
|
|
411
432
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { A } from '@ember/array';
|
|
2
2
|
import Component from '@ember/component';
|
|
3
3
|
import { set, get, computed, defineProperty } from '@ember/object';
|
|
4
|
-
import {
|
|
4
|
+
import { next, schedule, scheduleOnce, later } from '@ember/runloop';
|
|
5
5
|
import layout from '../templates/components/sortable-group';
|
|
6
6
|
import {
|
|
7
7
|
isEnterKey,
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
isRightArrowKey,
|
|
14
14
|
} from '../utils/keyboard';
|
|
15
15
|
import { ANNOUNCEMENT_ACTION_TYPES } from '../utils/constant';
|
|
16
|
+
import { deprecate } from '@ember/debug';
|
|
16
17
|
|
|
17
18
|
const a = A;
|
|
18
19
|
const NO_MODEL = {};
|
|
@@ -130,6 +131,20 @@ export default Component.extend({
|
|
|
130
131
|
init() {
|
|
131
132
|
this._super(...arguments);
|
|
132
133
|
|
|
134
|
+
deprecate(
|
|
135
|
+
'The <SortableGroup> component is deprecated. Please use the modifier version {{sortable-group}}.',
|
|
136
|
+
false,
|
|
137
|
+
{
|
|
138
|
+
id: 'ember-sortable:sortable-group-component-deprecated',
|
|
139
|
+
until: '3.0.0',
|
|
140
|
+
for: 'ember-sortable',
|
|
141
|
+
since: {
|
|
142
|
+
available: '2.2.6',
|
|
143
|
+
enabled: '2.2.6',
|
|
144
|
+
},
|
|
145
|
+
}
|
|
146
|
+
);
|
|
147
|
+
|
|
133
148
|
this._setGetterSetters();
|
|
134
149
|
this.set('moves', []);
|
|
135
150
|
},
|
|
@@ -168,7 +183,7 @@ export default Component.extend({
|
|
|
168
183
|
|
|
169
184
|
this.set('isRetainingFocus', true);
|
|
170
185
|
|
|
171
|
-
|
|
186
|
+
scheduleOnce('render', () => {
|
|
172
187
|
this.element.focus();
|
|
173
188
|
this.set('isRetainingFocus', false);
|
|
174
189
|
});
|
|
@@ -219,7 +234,7 @@ export default Component.extend({
|
|
|
219
234
|
}
|
|
220
235
|
this._announceAction(ANNOUNCEMENT_ACTION_TYPES.MOVE, delta);
|
|
221
236
|
// Guarantees that the before the UI is fully rendered before we move again.
|
|
222
|
-
|
|
237
|
+
scheduleOnce('render', () => {
|
|
223
238
|
this._move(sortedIndex, newSortedIndex);
|
|
224
239
|
this._updateHandleVisualIndicators(item, true);
|
|
225
240
|
|
|
@@ -396,16 +411,16 @@ export default Component.extend({
|
|
|
396
411
|
|
|
397
412
|
delete this._itemPosition;
|
|
398
413
|
|
|
399
|
-
|
|
414
|
+
schedule('render', () => {
|
|
400
415
|
items.invoke('freeze');
|
|
401
416
|
});
|
|
402
417
|
|
|
403
|
-
|
|
418
|
+
schedule('afterRender', () => {
|
|
404
419
|
items.invoke('reset');
|
|
405
420
|
});
|
|
406
421
|
|
|
407
|
-
|
|
408
|
-
|
|
422
|
+
next(() => {
|
|
423
|
+
schedule('render', () => {
|
|
409
424
|
items.invoke('thaw');
|
|
410
425
|
});
|
|
411
426
|
});
|
|
@@ -465,7 +480,7 @@ export default Component.extend({
|
|
|
465
480
|
this.confirmKeyboardSelection();
|
|
466
481
|
|
|
467
482
|
this.set('isRetainingFocus', true);
|
|
468
|
-
|
|
483
|
+
scheduleOnce('render', () => this._focusItem(itemElement));
|
|
469
484
|
} else if (isEscapeKey(event)) {
|
|
470
485
|
// cancel will reset the _selectedItem, so caching it here before we remove it.
|
|
471
486
|
const _selectedItemElement = this.get('_selectedItem.element');
|
|
@@ -473,7 +488,7 @@ export default Component.extend({
|
|
|
473
488
|
this.cancelKeyboardSelection();
|
|
474
489
|
|
|
475
490
|
this.set('isRetainingFocus', true);
|
|
476
|
-
|
|
491
|
+
scheduleOnce('render', () => {
|
|
477
492
|
const moves = this.get('moves');
|
|
478
493
|
if (moves && moves.length > 0) {
|
|
479
494
|
const sortedItems = this.get('sortedItems');
|
|
@@ -567,7 +582,7 @@ export default Component.extend({
|
|
|
567
582
|
announcer.textContent = message;
|
|
568
583
|
|
|
569
584
|
// Reset the message after the message is announced.
|
|
570
|
-
|
|
585
|
+
later(() => {
|
|
571
586
|
announcer.textContent = '';
|
|
572
587
|
}, 1000);
|
|
573
588
|
},
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Component from '@ember/component';
|
|
2
|
+
import { deprecate } from '@ember/debug';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* This component represents the handle of a `sortable-item`.
|
|
@@ -8,4 +9,22 @@ export default Component.extend({
|
|
|
8
9
|
role: 'button',
|
|
9
10
|
attributeBindings: ["dataSortableHandle:data-sortable-handle", "tabindex", "role"],
|
|
10
11
|
dataSortableHandle: true,
|
|
12
|
+
|
|
13
|
+
init() {
|
|
14
|
+
this._super(...arguments);
|
|
15
|
+
|
|
16
|
+
deprecate(
|
|
17
|
+
'The <SortableHandle> component is deprecated. Please use the modifier version {{sortable-handle}}.',
|
|
18
|
+
false,
|
|
19
|
+
{
|
|
20
|
+
id: 'ember-sortable:sortable-handle-component-deprecated',
|
|
21
|
+
until: '3.0.0',
|
|
22
|
+
for: 'ember-sortable',
|
|
23
|
+
since: {
|
|
24
|
+
available: '2.2.6',
|
|
25
|
+
enabled: '2.2.6',
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
);
|
|
29
|
+
},
|
|
11
30
|
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Promise, defer } from 'rsvp';
|
|
2
2
|
import Component from '@ember/component';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { defineProperty } from '@ember/object';
|
|
4
|
+
import { or, readOnly } from '@ember/object/computed';
|
|
5
|
+
import { run, throttle, bind, scheduleOnce, later } from '@ember/runloop';
|
|
5
6
|
import { DEBUG } from '@glimmer/env';
|
|
6
7
|
import scrollParent from '../system/scroll-parent';
|
|
7
8
|
import ScrollContainer from '../system/scroll-container';
|
|
@@ -9,8 +10,10 @@ import layout from '../templates/components/sortable-item';
|
|
|
9
10
|
import { getBorderSpacing } from '../utils/css-calculation';
|
|
10
11
|
import { DRAG_ACTIONS, ELEMENT_CLICK_ACTION, END_ACTIONS } from '../utils/constant';
|
|
11
12
|
import { getX, getY } from '../utils/coordinate';
|
|
12
|
-
import { buildWaiter } from 'ember
|
|
13
|
+
import { buildWaiter } from '@ember/test-waiters';
|
|
13
14
|
import config from 'ember-get-config';
|
|
15
|
+
import { deprecate } from '@ember/debug';
|
|
16
|
+
|
|
14
17
|
const { environment } = config;
|
|
15
18
|
const isTesting = environment === 'test';
|
|
16
19
|
|
|
@@ -118,7 +121,7 @@ export default Component.extend({
|
|
|
118
121
|
@property isBusy
|
|
119
122
|
@type Boolean
|
|
120
123
|
*/
|
|
121
|
-
isBusy:
|
|
124
|
+
isBusy: or('isDragging', 'isDropping'),
|
|
122
125
|
|
|
123
126
|
/**
|
|
124
127
|
The frequency with which the group is informed
|
|
@@ -150,13 +153,27 @@ export default Component.extend({
|
|
|
150
153
|
Allows host instance to use the `group` property for something else with
|
|
151
154
|
minimal overriding.
|
|
152
155
|
*/
|
|
153
|
-
_direction:
|
|
156
|
+
_direction: readOnly('direction'),
|
|
154
157
|
|
|
155
158
|
|
|
156
159
|
disableCheckScrollBounds: isTesting,
|
|
157
160
|
|
|
158
161
|
init() {
|
|
159
162
|
this._super(...arguments);
|
|
163
|
+
|
|
164
|
+
deprecate(
|
|
165
|
+
'The <SortableItem> component is deprecated. Please use the modifier version {{sortable-item}}.',
|
|
166
|
+
false,
|
|
167
|
+
{
|
|
168
|
+
id: 'ember-sortable:sortable-item-component-deprecated',
|
|
169
|
+
until: '3.0.0',
|
|
170
|
+
for: 'ember-sortable',
|
|
171
|
+
since: {
|
|
172
|
+
available: '2.2.6',
|
|
173
|
+
enabled: '2.2.6',
|
|
174
|
+
},
|
|
175
|
+
}
|
|
176
|
+
);
|
|
160
177
|
this._setGetterSetters();
|
|
161
178
|
},
|
|
162
179
|
|
|
@@ -280,7 +297,7 @@ export default Component.extend({
|
|
|
280
297
|
startEvent.preventDefault();
|
|
281
298
|
startEvent.stopPropagation();
|
|
282
299
|
|
|
283
|
-
this._prepareDragListener =
|
|
300
|
+
this._prepareDragListener = bind(this, this._prepareDrag, startEvent);
|
|
284
301
|
|
|
285
302
|
DRAG_ACTIONS.forEach(event => window.addEventListener(event, this._prepareDragListener));
|
|
286
303
|
|
|
@@ -490,7 +507,7 @@ export default Component.extend({
|
|
|
490
507
|
@private
|
|
491
508
|
*/
|
|
492
509
|
_scheduleApplyPosition() {
|
|
493
|
-
|
|
510
|
+
scheduleOnce('render', this, '_applyPosition');
|
|
494
511
|
},
|
|
495
512
|
|
|
496
513
|
/**
|
|
@@ -600,7 +617,7 @@ export default Component.extend({
|
|
|
600
617
|
});
|
|
601
618
|
} else {
|
|
602
619
|
const duration = this.get('isAnimated') ? this.get('transitionDuration') : 200;
|
|
603
|
-
transitionPromise = new Promise((resolve) =>
|
|
620
|
+
transitionPromise = new Promise((resolve) => later(resolve, duration));
|
|
604
621
|
}
|
|
605
622
|
|
|
606
623
|
if (DEBUG) {
|
|
@@ -10,7 +10,8 @@ import {
|
|
|
10
10
|
isUpArrowKey
|
|
11
11
|
} from "../utils/keyboard";
|
|
12
12
|
import {ANNOUNCEMENT_ACTION_TYPES} from "../utils/constant";
|
|
13
|
-
import {
|
|
13
|
+
import { defaultA11yAnnouncementConfig } from "../utils/defaults";
|
|
14
|
+
import { next, schedule, scheduleOnce, later } from '@ember/runloop';
|
|
14
15
|
import {inject as service} from '@ember/service';
|
|
15
16
|
|
|
16
17
|
const NO_MODEL = {};
|
|
@@ -53,6 +54,10 @@ export default class SortableGroupModifier extends Modifier {
|
|
|
53
54
|
isRetainingFocus = false;
|
|
54
55
|
/** End of keyboard utils */
|
|
55
56
|
|
|
57
|
+
get disabled() {
|
|
58
|
+
return this.args.named.disabled || false;
|
|
59
|
+
}
|
|
60
|
+
|
|
56
61
|
/** Start of a11y properties */
|
|
57
62
|
/**
|
|
58
63
|
* @property an object containing different classes for visual indicators
|
|
@@ -73,7 +78,6 @@ export default class SortableGroupModifier extends Modifier {
|
|
|
73
78
|
/**
|
|
74
79
|
* @property an object containing functions for producing screen reader announcements
|
|
75
80
|
* @type {Object}
|
|
76
|
-
* @default null
|
|
77
81
|
* @example
|
|
78
82
|
* {
|
|
79
83
|
* MOVE: function() {},
|
|
@@ -83,15 +87,15 @@ export default class SortableGroupModifier extends Modifier {
|
|
|
83
87
|
* }
|
|
84
88
|
*/
|
|
85
89
|
get a11yAnnouncementConfig() {
|
|
86
|
-
return this.args.named.a11yAnnouncementConfig ||
|
|
90
|
+
return this.args.named.a11yAnnouncementConfig || defaultA11yAnnouncementConfig;
|
|
87
91
|
}
|
|
88
92
|
|
|
89
93
|
get itemVisualClass() {
|
|
90
|
-
return this.args.named.itemVisualClass;
|
|
94
|
+
return this.args.named.itemVisualClass || "is-activated";
|
|
91
95
|
}
|
|
92
96
|
|
|
93
97
|
get a11yItemName() {
|
|
94
|
-
return this.args.named.a11yItemName;
|
|
98
|
+
return this.args.named.a11yItemName || 'item';
|
|
95
99
|
}
|
|
96
100
|
/** End of a11y properties */
|
|
97
101
|
|
|
@@ -136,7 +140,7 @@ export default class SortableGroupModifier extends Modifier {
|
|
|
136
140
|
|
|
137
141
|
this.isRetainingFocus = true;
|
|
138
142
|
|
|
139
|
-
|
|
143
|
+
scheduleOnce('render', () => {
|
|
140
144
|
this.element.focus();
|
|
141
145
|
this.isRetainingFocus = false;
|
|
142
146
|
});
|
|
@@ -217,7 +221,7 @@ export default class SortableGroupModifier extends Modifier {
|
|
|
217
221
|
this.confirmKeyboardSelection();
|
|
218
222
|
|
|
219
223
|
this.isRetainingFocus = true;
|
|
220
|
-
|
|
224
|
+
scheduleOnce('render', () => this._focusItem(itemElement));
|
|
221
225
|
} else if (isEscapeKey(event)) {
|
|
222
226
|
// cancel will reset the selectedItem, so caching it here before we remove it.
|
|
223
227
|
const _selectedItemElement = selectedItem.element;
|
|
@@ -225,7 +229,7 @@ export default class SortableGroupModifier extends Modifier {
|
|
|
225
229
|
this.cancelKeyboardSelection();
|
|
226
230
|
|
|
227
231
|
this.isRetainingFocus = true;
|
|
228
|
-
|
|
232
|
+
scheduleOnce('render', () => {
|
|
229
233
|
const moves = this.moves;
|
|
230
234
|
if (moves && moves.length > 0) {
|
|
231
235
|
const sortedItems = this.sortedItems;
|
|
@@ -258,7 +262,7 @@ export default class SortableGroupModifier extends Modifier {
|
|
|
258
262
|
}
|
|
259
263
|
this._announceAction(ANNOUNCEMENT_ACTION_TYPES.MOVE, delta);
|
|
260
264
|
// Guarantees that the before the UI is fully rendered before we move again.
|
|
261
|
-
|
|
265
|
+
scheduleOnce('render', () => {
|
|
262
266
|
this._move(sortedIndex, newSortedIndex);
|
|
263
267
|
this._updateHandleVisualIndicators(item, true);
|
|
264
268
|
|
|
@@ -319,7 +323,7 @@ export default class SortableGroupModifier extends Modifier {
|
|
|
319
323
|
const a11yAnnouncementConfig = this.a11yAnnouncementConfig;
|
|
320
324
|
const a11yItemName = this.a11yItemName;
|
|
321
325
|
|
|
322
|
-
if (
|
|
326
|
+
if (!a11yItemName || !(type in a11yAnnouncementConfig)) {
|
|
323
327
|
return;
|
|
324
328
|
}
|
|
325
329
|
|
|
@@ -340,7 +344,7 @@ export default class SortableGroupModifier extends Modifier {
|
|
|
340
344
|
announcer.textContent = message;
|
|
341
345
|
|
|
342
346
|
// Reset the message after the message is announced.
|
|
343
|
-
|
|
347
|
+
later(() => {
|
|
344
348
|
announcer.textContent = '';
|
|
345
349
|
}, 1000);
|
|
346
350
|
}
|
|
@@ -671,16 +675,16 @@ export default class SortableGroupModifier extends Modifier {
|
|
|
671
675
|
|
|
672
676
|
delete this._firstItemPosition;
|
|
673
677
|
|
|
674
|
-
|
|
678
|
+
schedule('render', () => {
|
|
675
679
|
items.forEach(item => item.freeze());
|
|
676
680
|
});
|
|
677
681
|
|
|
678
|
-
|
|
682
|
+
schedule('afterRender', () => {
|
|
679
683
|
items.forEach(item => item.reset());
|
|
680
684
|
});
|
|
681
685
|
|
|
682
|
-
|
|
683
|
-
|
|
686
|
+
next(() => {
|
|
687
|
+
schedule('render', () => {
|
|
684
688
|
items.forEach(item => item.thaw());
|
|
685
689
|
});
|
|
686
690
|
});
|
|
@@ -707,14 +711,19 @@ export default class SortableGroupModifier extends Modifier {
|
|
|
707
711
|
}
|
|
708
712
|
|
|
709
713
|
didReceiveArguments() {
|
|
714
|
+
this.removeEventListener();
|
|
715
|
+
|
|
716
|
+
if (this.disabled) {
|
|
717
|
+
return;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
this.addEventListener();
|
|
710
721
|
}
|
|
711
722
|
|
|
712
723
|
didUpdateArguments() {
|
|
713
724
|
}
|
|
714
725
|
|
|
715
726
|
didInstall() {
|
|
716
|
-
this.addEventListener();
|
|
717
|
-
|
|
718
727
|
this.announcer = this._createAnnouncer();
|
|
719
728
|
this.element.insertAdjacentElement('afterend', this.announcer);
|
|
720
729
|
|
|
@@ -4,15 +4,15 @@ import {action, set} from '@ember/object';
|
|
|
4
4
|
import {reads} from '@ember/object/computed';
|
|
5
5
|
import {or} from '@ember/object/computed';
|
|
6
6
|
import {DRAG_ACTIONS, ELEMENT_CLICK_ACTION, END_ACTIONS} from "../utils/constant";
|
|
7
|
-
import { run, throttle } from '@ember/runloop';
|
|
7
|
+
import { run, throttle, bind, scheduleOnce, later } from '@ember/runloop';
|
|
8
8
|
import { DEBUG } from '@glimmer/env';
|
|
9
9
|
import {getX, getY} from "../utils/coordinate";
|
|
10
10
|
import ScrollContainer from "../system/scroll-container";
|
|
11
11
|
import scrollParent from "../system/scroll-parent";
|
|
12
12
|
import {getBorderSpacing} from "../utils/css-calculation";
|
|
13
|
-
import { buildWaiter } from 'ember
|
|
13
|
+
import { buildWaiter } from '@ember/test-waiters';
|
|
14
14
|
import {inject as service} from '@ember/service';
|
|
15
|
-
import {assert} from '@ember/debug';
|
|
15
|
+
import { assert, deprecate } from '@ember/debug';
|
|
16
16
|
import config from 'ember-get-config';
|
|
17
17
|
const { environment } = config;
|
|
18
18
|
const isTesting = environment === 'test';
|
|
@@ -23,7 +23,7 @@ const sortableItemWaiter = buildWaiter("sortable-item-waiter");
|
|
|
23
23
|
* Modifier to mark an element as an item to be reordered
|
|
24
24
|
*
|
|
25
25
|
* @param {Object} model The model that this item will represent
|
|
26
|
-
* @param {boolean} [
|
|
26
|
+
* @param {boolean} [disabled=false] Set to true to make this item not sortable
|
|
27
27
|
* @param {Function} [onDragStart] An optional callback for when dragging starts.
|
|
28
28
|
* @param {Function} [onDragStop] An optional callback for when dragging stops.
|
|
29
29
|
*
|
|
@@ -63,6 +63,9 @@ export default class SortableItemModifier extends Modifier {
|
|
|
63
63
|
@reads("sortableGroup.direction")
|
|
64
64
|
direction;
|
|
65
65
|
|
|
66
|
+
@reads("sortableGroup.disabled")
|
|
67
|
+
groupDisabled;
|
|
68
|
+
|
|
66
69
|
@service('ember-sortable@ember-sortable')
|
|
67
70
|
sortableService;
|
|
68
71
|
|
|
@@ -99,13 +102,27 @@ export default class SortableItemModifier extends Modifier {
|
|
|
99
102
|
}
|
|
100
103
|
|
|
101
104
|
/**
|
|
102
|
-
Removes the ability for the current item to be
|
|
103
|
-
@property
|
|
105
|
+
Removes the ability for the current item to be sorted
|
|
106
|
+
@property disabled
|
|
104
107
|
@type boolean
|
|
105
108
|
@default false
|
|
106
109
|
*/
|
|
107
|
-
get
|
|
108
|
-
|
|
110
|
+
get isDisabled() {
|
|
111
|
+
deprecate(
|
|
112
|
+
'"isDraggingDisabled" is deprecated. Please migrate to "disabled" named argument',
|
|
113
|
+
!("isDraggingDisabled" in this.args.named),
|
|
114
|
+
{
|
|
115
|
+
id: 'ember-sortable.is-dragging-disabled',
|
|
116
|
+
url: 'https://github.com/adopted-ember-addons/ember-sortable#readme',
|
|
117
|
+
until: '3.0.0',
|
|
118
|
+
for: 'ember-sortable',
|
|
119
|
+
since: {
|
|
120
|
+
available: '2.2.6',
|
|
121
|
+
enabled: '2.2.6',
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
return this.groupDisabled || this.args.named.disabled || this.args.named.isDraggingDisabled || false;
|
|
109
126
|
}
|
|
110
127
|
|
|
111
128
|
/**
|
|
@@ -217,10 +234,7 @@ export default class SortableItemModifier extends Modifier {
|
|
|
217
234
|
isBusy;
|
|
218
235
|
|
|
219
236
|
/**
|
|
220
|
-
|
|
221
|
-
@property isDraggingDisabled
|
|
222
|
-
@type boolean
|
|
223
|
-
@default false
|
|
237
|
+
@property disableCheckScrollBounds
|
|
224
238
|
*/
|
|
225
239
|
get disableCheckScrollBounds() {
|
|
226
240
|
return this.args.named.disableCheckScrollBounds != undefined ? this.args.named.disableCheckScrollBounds : isTesting;
|
|
@@ -239,6 +253,8 @@ export default class SortableItemModifier extends Modifier {
|
|
|
239
253
|
|
|
240
254
|
@action
|
|
241
255
|
keyDown(event) {
|
|
256
|
+
if (this.isDisabled) { return; }
|
|
257
|
+
|
|
242
258
|
// If the event is coming from within the item, we do not want to activate keyboard reorder mode.
|
|
243
259
|
if (event.target === this.handleElement || event.target === this.element) {
|
|
244
260
|
this.sortableGroup.activateKeyDown(this);
|
|
@@ -296,10 +312,7 @@ export default class SortableItemModifier extends Modifier {
|
|
|
296
312
|
* @private
|
|
297
313
|
*/
|
|
298
314
|
_primeDrag(startEvent) {
|
|
299
|
-
|
|
300
|
-
if (this.isDraggingDisabled) {
|
|
301
|
-
return;
|
|
302
|
-
}
|
|
315
|
+
if (this.isDisabled) { return; }
|
|
303
316
|
|
|
304
317
|
if (this.handleElement && !startEvent.target.closest(this.handle)) {
|
|
305
318
|
return;
|
|
@@ -308,7 +321,7 @@ export default class SortableItemModifier extends Modifier {
|
|
|
308
321
|
startEvent.preventDefault();
|
|
309
322
|
startEvent.stopPropagation();
|
|
310
323
|
|
|
311
|
-
this._prepareDragListener =
|
|
324
|
+
this._prepareDragListener = bind(this, this._prepareDrag, startEvent);
|
|
312
325
|
|
|
313
326
|
DRAG_ACTIONS.forEach(event => window.addEventListener(event, this._prepareDragListener));
|
|
314
327
|
|
|
@@ -515,7 +528,7 @@ export default class SortableItemModifier extends Modifier {
|
|
|
515
528
|
@private
|
|
516
529
|
*/
|
|
517
530
|
_scheduleApplyPosition() {
|
|
518
|
-
|
|
531
|
+
scheduleOnce('render', this, '_applyPosition');
|
|
519
532
|
}
|
|
520
533
|
|
|
521
534
|
/**
|
|
@@ -625,7 +638,7 @@ export default class SortableItemModifier extends Modifier {
|
|
|
625
638
|
});
|
|
626
639
|
} else {
|
|
627
640
|
const duration = this.isAnimated ? this.transitionDuration : 200;
|
|
628
|
-
transitionPromise = new Promise((resolve) =>
|
|
641
|
+
transitionPromise = new Promise((resolve) => later(resolve, duration));
|
|
629
642
|
}
|
|
630
643
|
|
|
631
644
|
if (DEBUG) {
|
|
@@ -650,7 +663,7 @@ export default class SortableItemModifier extends Modifier {
|
|
|
650
663
|
|
|
651
664
|
get isAnimated() {
|
|
652
665
|
if (!this.element) {
|
|
653
|
-
return;
|
|
666
|
+
return undefined;
|
|
654
667
|
}
|
|
655
668
|
|
|
656
669
|
let el = this.element;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{{yield (
|
|
2
2
|
hash
|
|
3
3
|
item=(component "ember-sortable@sortable-item"
|
|
4
|
-
direction=direction
|
|
4
|
+
direction=this.direction
|
|
5
5
|
registerItem=(action "registerItem")
|
|
6
6
|
deregisterItem=(action "deregisterItem")
|
|
7
7
|
setSelectedItem=(action "setSelectedItem")
|
|
@@ -11,6 +11,6 @@
|
|
|
11
11
|
activateKeyDown=(action "activateKeyDown")
|
|
12
12
|
deactivateKeyDown=(action "deactivateKeyDown")
|
|
13
13
|
)
|
|
14
|
-
model=model
|
|
14
|
+
model=this.model
|
|
15
15
|
)
|
|
16
16
|
}}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const defaultA11yAnnouncementConfig = {
|
|
2
|
+
ACTIVATE({ a11yItemName, index, maxLength, direction }) {
|
|
3
|
+
let message = `${a11yItemName} at position, ${index + 1} of ${maxLength}, is activated to be repositioned.`;
|
|
4
|
+
|
|
5
|
+
if (direction === 'y') {
|
|
6
|
+
message += 'Press up and down keys to change position,';
|
|
7
|
+
}
|
|
8
|
+
else {
|
|
9
|
+
message += 'Press left and right keys to change position,';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
message += ' Space to confirm new position, Escape to cancel.';
|
|
13
|
+
|
|
14
|
+
return message;
|
|
15
|
+
},
|
|
16
|
+
MOVE({ a11yItemName, index, maxLength, delta }) {
|
|
17
|
+
return `${a11yItemName} is moved to position, ${index + 1 + delta} of ${maxLength}. Press Space to confirm new position, Escape to cancel.`;
|
|
18
|
+
},
|
|
19
|
+
CONFIRM({ a11yItemName }) {
|
|
20
|
+
return `${a11yItemName} is successfully repositioned.`;
|
|
21
|
+
},
|
|
22
|
+
CANCEL({ a11yItemName }) {
|
|
23
|
+
return `Cancelling ${a11yItemName} repositioning`;
|
|
24
|
+
},
|
|
25
|
+
};
|
package/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const fs = require('fs');
|
|
4
|
+
const VersionChecker = require('ember-cli-version-checker');
|
|
4
5
|
|
|
5
6
|
module.exports = {
|
|
6
7
|
name: require('./package').name,
|
|
@@ -13,5 +14,12 @@ module.exports = {
|
|
|
13
14
|
if (fs.existsSync('vendor/polyfills/closest.js')) {
|
|
14
15
|
app.import('vendor/polyfills/closest.js', { prepend: true});
|
|
15
16
|
}
|
|
17
|
+
|
|
18
|
+
var checker = new VersionChecker(this);
|
|
19
|
+
var emberVersion = checker.for('ember-source');
|
|
20
|
+
|
|
21
|
+
if (emberVersion.lt('3.10.0')) {
|
|
22
|
+
this.ui.writeWarnLine('ember-sortable requires the ember-decorator-polyfill. Please add it to your `package.json`.');
|
|
23
|
+
}
|
|
16
24
|
}
|
|
17
25
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ember-sortable",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Sortable UI primitives for Ember.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ember-addon",
|
|
@@ -25,13 +25,13 @@
|
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@ember/render-modifiers": "^1.0.2",
|
|
28
|
-
"ember-
|
|
28
|
+
"@ember/test-waiters": "^2.4.4",
|
|
29
|
+
"ember-cli-babel": "^7.26.6",
|
|
29
30
|
"ember-cli-htmlbars": "^5.0.0",
|
|
30
|
-
"ember-
|
|
31
|
+
"ember-cli-version-checker": "^5.1.2",
|
|
31
32
|
"ember-get-config": "^0.3.0",
|
|
32
33
|
"ember-modifier": "^2.1.0",
|
|
33
|
-
"ember-test-selectors": "^5.0.0"
|
|
34
|
-
"ember-test-waiters": "^1.1.1"
|
|
34
|
+
"ember-test-selectors": "^5.0.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@ember/optional-features": "^0.6.3",
|
package/jsconfig.json
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"compilerOptions":{"target":"es6","experimentalDecorators":true},"exclude":["node_modules","bower_components","tmp","vendor",".git","dist"]}
|