@bennerinformatics/ember-fw-table 2.1.2 → 2.1.4
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/.yalc/ember-sortable/.huskyrc +5 -0
- package/.yalc/ember-sortable/CHANGELOG.md +755 -0
- package/.yalc/ember-sortable/CODE_OF_CONDUCT.md +6 -0
- package/.yalc/ember-sortable/LICENSE.md +9 -0
- package/.yalc/ember-sortable/MIGRATION_GUIDE_MODIFIERS.md +95 -0
- package/.yalc/ember-sortable/MIGRATION_GUIDE_V2.md +120 -0
- package/.yalc/ember-sortable/Makefile +24 -0
- package/.yalc/ember-sortable/README.md +423 -0
- package/.yalc/ember-sortable/RELEASE.md +60 -0
- package/.yalc/ember-sortable/V2_MIGRATION_RFC.md +1100 -0
- package/.yalc/ember-sortable/addon/modifiers/sortable-group.js +754 -0
- package/.yalc/ember-sortable/addon/modifiers/sortable-handle.js +29 -0
- package/.yalc/ember-sortable/addon/modifiers/sortable-item.js +869 -0
- package/.yalc/ember-sortable/addon/services/ember-sortable.js +92 -0
- package/.yalc/ember-sortable/addon/system/scroll-container.js +53 -0
- package/.yalc/ember-sortable/addon/system/scroll-parent.js +33 -0
- package/.yalc/ember-sortable/addon/utils/constant.js +9 -0
- package/.yalc/ember-sortable/addon/utils/coordinate.js +34 -0
- package/.yalc/ember-sortable/addon/utils/css-calculation.js +20 -0
- package/.yalc/ember-sortable/addon/utils/defaults.js +26 -0
- package/.yalc/ember-sortable/addon/utils/keyboard.js +32 -0
- package/.yalc/ember-sortable/addon-test-support/helpers/drag.js +111 -0
- package/.yalc/ember-sortable/addon-test-support/helpers/index.js +4 -0
- package/.yalc/ember-sortable/addon-test-support/helpers/reorder.js +41 -0
- package/.yalc/ember-sortable/addon-test-support/utils/keyboard.js +32 -0
- package/.yalc/ember-sortable/addon-test-support/utils/offset.js +14 -0
- package/.yalc/ember-sortable/app/modifiers/sortable-group.js +1 -0
- package/.yalc/ember-sortable/app/modifiers/sortable-handle.js +1 -0
- package/.yalc/ember-sortable/app/modifiers/sortable-item.js +1 -0
- package/.yalc/ember-sortable/app/services/ember-sortable-internal-state.js +1 -0
- package/.yalc/ember-sortable/config/environment.js +5 -0
- package/.yalc/ember-sortable/demo.gif +0 -0
- package/.yalc/ember-sortable/index.js +5 -0
- package/.yalc/ember-sortable/package.json +65 -0
- package/.yalc/ember-sortable/yalc.sig +1 -0
- package/addon/components/fw-pagination-wrapper.js +2 -2
- package/addon/components/fw-table-sortable.js +14 -3
- package/addon/templates/components/fw-delete-modal.hbs +1 -1
- package/addon/templates/components/fw-table-resort.hbs +4 -4
- package/addon/utils/formats.js +6 -3
- package/package.json +65 -65
- package/yalc.lock +10 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import Service from '@ember/service';
|
|
2
|
+
|
|
3
|
+
export default class EmberSortableService extends Service {
|
|
4
|
+
/**
|
|
5
|
+
* Internal State for any groups currently in DOM
|
|
6
|
+
*
|
|
7
|
+
* {
|
|
8
|
+
* groupName: {
|
|
9
|
+
* groupModifier: object,
|
|
10
|
+
* items: []
|
|
11
|
+
* }
|
|
12
|
+
* }
|
|
13
|
+
* @type {{}}
|
|
14
|
+
*/
|
|
15
|
+
groups = {};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Register a new group with the service
|
|
19
|
+
*
|
|
20
|
+
* @param {String} groupName
|
|
21
|
+
* @param {SortableGroupModifier} groupModifier
|
|
22
|
+
*/
|
|
23
|
+
registerGroup(groupName, groupModifier) {
|
|
24
|
+
if (this.groups[groupName] === undefined) {
|
|
25
|
+
this.groups[groupName] = {
|
|
26
|
+
groupModifier: groupModifier,
|
|
27
|
+
items: [],
|
|
28
|
+
};
|
|
29
|
+
} else {
|
|
30
|
+
this.groups[groupName].groupModifier = groupModifier;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* De-register a group with the service
|
|
36
|
+
*
|
|
37
|
+
* @param {String} groupName
|
|
38
|
+
*/
|
|
39
|
+
deregisterGroup(groupName) {
|
|
40
|
+
delete this.groups[groupName];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Register an item with this group
|
|
45
|
+
*
|
|
46
|
+
* @method registerItem
|
|
47
|
+
* @param {String} groupName
|
|
48
|
+
* @param {SortableItemModifier} item
|
|
49
|
+
*/
|
|
50
|
+
registerItem(groupName, item) {
|
|
51
|
+
let groupDef = this.fetchGroup(groupName);
|
|
52
|
+
let items = groupDef.items;
|
|
53
|
+
|
|
54
|
+
if (items.indexOf(item) === -1) {
|
|
55
|
+
items = [...items, item];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
groupDef.items = items;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
De-register an item with this group.
|
|
63
|
+
|
|
64
|
+
@method deregisterItem
|
|
65
|
+
@param groupName
|
|
66
|
+
@param item
|
|
67
|
+
*/
|
|
68
|
+
deregisterItem(groupName, item) {
|
|
69
|
+
let groupDef = this.fetchGroup(groupName);
|
|
70
|
+
let items = groupDef.items;
|
|
71
|
+
|
|
72
|
+
const index = items.indexOf(item);
|
|
73
|
+
if (index !== -1) {
|
|
74
|
+
let newItems = [...items.slice(0, index), ...items.slice(index + 1)];
|
|
75
|
+
groupDef.items = newItems;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Fetch a group definition
|
|
81
|
+
*
|
|
82
|
+
* @param {String} groupName
|
|
83
|
+
* @returns {*}
|
|
84
|
+
*/
|
|
85
|
+
fetchGroup(groupName) {
|
|
86
|
+
if (this.groups[groupName] === undefined) {
|
|
87
|
+
this.registerGroup(groupName, undefined);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return this.groups[groupName];
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export default class ScrollContainer {
|
|
2
|
+
constructor(element) {
|
|
3
|
+
this.isWindow = element === document;
|
|
4
|
+
this.element = this.isWindow ? document.documentElement : element;
|
|
5
|
+
|
|
6
|
+
if (this.isWindow) {
|
|
7
|
+
this.top = 0;
|
|
8
|
+
this.left = 0;
|
|
9
|
+
this.width = document.documentElement.clientWidth;
|
|
10
|
+
this.height = document.documentElement.clientHeight;
|
|
11
|
+
} else {
|
|
12
|
+
// Absolute position in document
|
|
13
|
+
let { top, left } = this.element.getBoundingClientRect();
|
|
14
|
+
this.top = top;
|
|
15
|
+
this.left = left;
|
|
16
|
+
// Viewport size of the container element
|
|
17
|
+
this.width = parseFloat(getComputedStyle(this.element).width);
|
|
18
|
+
this.height = parseFloat(getComputedStyle(this.element).height);
|
|
19
|
+
}
|
|
20
|
+
// Total size of the container element (including scrollable part)
|
|
21
|
+
this.scrollWidth = this.element.scrollWidth;
|
|
22
|
+
this.scrollHeight = this.element.scrollHeight;
|
|
23
|
+
// Max scroll pos
|
|
24
|
+
this.maxScrollTop = this.scrollHeight - this.height;
|
|
25
|
+
this.maxScrollLeft = this.scrollWidth - this.width;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get bottom() {
|
|
29
|
+
return this.top + this.height;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
get right() {
|
|
33
|
+
return this.left + this.width;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
scrollTop(value) {
|
|
37
|
+
if (value) {
|
|
38
|
+
value = Math.max(0, Math.min(this.maxScrollTop, value));
|
|
39
|
+
this.element.scrollTop = value;
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
return this.element.scrollTop;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
scrollLeft(value) {
|
|
46
|
+
if (value) {
|
|
47
|
+
value = Math.max(0, Math.min(this.maxScrollLeft, value));
|
|
48
|
+
this.element.scrollLeft = value;
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
51
|
+
return this.element.scrollLeft;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
function getParentElements(element) {
|
|
2
|
+
const parentsArray = [];
|
|
3
|
+
|
|
4
|
+
if (!element) {
|
|
5
|
+
return parentsArray;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
let currentParent = element.parentElement;
|
|
9
|
+
|
|
10
|
+
while (currentParent !== null) {
|
|
11
|
+
parentsArray.push(currentParent);
|
|
12
|
+
currentParent = currentParent.parentElement;
|
|
13
|
+
}
|
|
14
|
+
return parentsArray;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default function (element) {
|
|
18
|
+
let position = getComputedStyle(element).position;
|
|
19
|
+
let excludeStaticParent = position === 'absolute';
|
|
20
|
+
let scrollParent = getParentElements(element).filter(function (parent) {
|
|
21
|
+
let parentElemStyles = getComputedStyle(parent);
|
|
22
|
+
if (excludeStaticParent && parentElemStyles.position === 'static') {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
let { overflow, overflowX, overflowY } = parentElemStyles;
|
|
26
|
+
return /(auto|scroll)/.test(overflow + overflowX + overflowY);
|
|
27
|
+
})[0];
|
|
28
|
+
|
|
29
|
+
if (!scrollParent || scrollParent === document.body) {
|
|
30
|
+
scrollParent = document;
|
|
31
|
+
}
|
|
32
|
+
return position === 'fixed' || scrollParent;
|
|
33
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const DRAG_ACTIONS = ['mousemove', 'touchmove'];
|
|
2
|
+
export const ELEMENT_CLICK_ACTION = 'click';
|
|
3
|
+
export const END_ACTIONS = ['click', 'mouseup', 'touchend'];
|
|
4
|
+
export const ANNOUNCEMENT_ACTION_TYPES = {
|
|
5
|
+
ACTIVATE: 'ACTIVATE',
|
|
6
|
+
MOVE: 'MOVE',
|
|
7
|
+
CONFIRM: 'CONFIRM',
|
|
8
|
+
CANCEL: 'CANCEL',
|
|
9
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Gets the y offset for a given event.
|
|
3
|
+
Work for touch and mouse events.
|
|
4
|
+
@method getY
|
|
5
|
+
@return {Number}
|
|
6
|
+
@private
|
|
7
|
+
*/
|
|
8
|
+
export function getY(event) {
|
|
9
|
+
let touches = event.changedTouches;
|
|
10
|
+
let touch = touches && touches[0];
|
|
11
|
+
|
|
12
|
+
if (touch) {
|
|
13
|
+
return touch.screenY;
|
|
14
|
+
} else {
|
|
15
|
+
return event.clientY;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
Gets the x offset for a given event.
|
|
21
|
+
@method getX
|
|
22
|
+
@return {Number}
|
|
23
|
+
@private
|
|
24
|
+
*/
|
|
25
|
+
export function getX(event) {
|
|
26
|
+
let touches = event.changedTouches;
|
|
27
|
+
let touch = touches && touches[0];
|
|
28
|
+
|
|
29
|
+
if (touch) {
|
|
30
|
+
return touch.screenX;
|
|
31
|
+
} else {
|
|
32
|
+
return event.clientX;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Gets a numeric border-spacing values for a given element.
|
|
3
|
+
|
|
4
|
+
@method getBorderSpacing
|
|
5
|
+
@param {Element} element
|
|
6
|
+
@return {Object}
|
|
7
|
+
@private
|
|
8
|
+
*/
|
|
9
|
+
export function getBorderSpacing(el) {
|
|
10
|
+
let css = getComputedStyle(el).borderSpacing; // '0px 0px'
|
|
11
|
+
let [horizontal, vertical] = css.split(' ');
|
|
12
|
+
if (vertical === undefined) {
|
|
13
|
+
vertical = horizontal;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
horizontal: parseFloat(horizontal),
|
|
18
|
+
vertical: parseFloat(vertical),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
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
|
+
} else {
|
|
8
|
+
message += 'Press left and right keys to change position,';
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
message += ' Space to confirm new position, Escape to cancel.';
|
|
12
|
+
|
|
13
|
+
return message;
|
|
14
|
+
},
|
|
15
|
+
MOVE({ a11yItemName, index, maxLength, delta }) {
|
|
16
|
+
return `${a11yItemName} is moved to position, ${
|
|
17
|
+
index + 1 + delta
|
|
18
|
+
} of ${maxLength}. Press Space to confirm new position, Escape to cancel.`;
|
|
19
|
+
},
|
|
20
|
+
CONFIRM({ a11yItemName }) {
|
|
21
|
+
return `${a11yItemName} is successfully repositioned.`;
|
|
22
|
+
},
|
|
23
|
+
CANCEL({ a11yItemName }) {
|
|
24
|
+
return `Cancelling ${a11yItemName} repositioning`;
|
|
25
|
+
},
|
|
26
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const ENTER_KEY = 'Enter';
|
|
2
|
+
const ESCAPE_KEY = 'Escape';
|
|
3
|
+
const SPACE_KEY = 'Space';
|
|
4
|
+
const ARROW_KEYS = {
|
|
5
|
+
LEFT: 'ArrowLeft',
|
|
6
|
+
UP: 'ArrowUp',
|
|
7
|
+
RIGHT: 'ArrowRight',
|
|
8
|
+
DOWN: 'ArrowDown',
|
|
9
|
+
};
|
|
10
|
+
export const ENTER_KEY_CODE = 13;
|
|
11
|
+
export const ESCAPE_KEY_CODE = 27;
|
|
12
|
+
export const SPACE_KEY_CODE = 32;
|
|
13
|
+
export const ARROW_KEY_CODES = {
|
|
14
|
+
LEFT: 37,
|
|
15
|
+
UP: 38,
|
|
16
|
+
RIGHT: 39,
|
|
17
|
+
DOWN: 40,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
function createKeyTest(key, keyCode) {
|
|
21
|
+
return function isKey(event) {
|
|
22
|
+
return event.key === key || event.keyCode === keyCode;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const isEnterKey = createKeyTest(ENTER_KEY, ENTER_KEY_CODE);
|
|
27
|
+
export const isEscapeKey = createKeyTest(ESCAPE_KEY, ESCAPE_KEY_CODE);
|
|
28
|
+
export const isSpaceKey = createKeyTest(SPACE_KEY, SPACE_KEY_CODE);
|
|
29
|
+
export const isLeftArrowKey = createKeyTest(ARROW_KEYS.LEFT, ARROW_KEY_CODES.LEFT);
|
|
30
|
+
export const isUpArrowKey = createKeyTest(ARROW_KEYS.UP, ARROW_KEY_CODES.UP);
|
|
31
|
+
export const isRightArrowKey = createKeyTest(ARROW_KEYS.RIGHT, ARROW_KEY_CODES.RIGHT);
|
|
32
|
+
export const isDownArrowKey = createKeyTest(ARROW_KEYS.DOWN, ARROW_KEY_CODES.DOWN);
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { triggerEvent, find, settled } from '@ember/test-helpers';
|
|
2
|
+
import { getOffset } from '../utils/offset';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
Drags elements by an offset specified in pixels.
|
|
6
|
+
|
|
7
|
+
Examples
|
|
8
|
+
|
|
9
|
+
drag(
|
|
10
|
+
'mouse',
|
|
11
|
+
'.some-list li[data-item=uno]',
|
|
12
|
+
function() {
|
|
13
|
+
return { dy: 50, dx: 20 };
|
|
14
|
+
}
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
@method drag
|
|
18
|
+
@param {'mouse'|'touch'} [mode]
|
|
19
|
+
event mode
|
|
20
|
+
@param {String} [itemSelector]
|
|
21
|
+
selector for the element to drag
|
|
22
|
+
@param {Function} [offsetFn]
|
|
23
|
+
function returning the offset by which to drag
|
|
24
|
+
@param {Object} [callbacks]
|
|
25
|
+
callbacks that are fired at the different stages of the interaction
|
|
26
|
+
@return {Promise}
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
export async function drag(mode, itemSelector, offsetFn, callbacks = {}) {
|
|
30
|
+
let start;
|
|
31
|
+
let move;
|
|
32
|
+
let end;
|
|
33
|
+
let which;
|
|
34
|
+
|
|
35
|
+
if (mode === 'mouse') {
|
|
36
|
+
start = 'mousedown';
|
|
37
|
+
move = 'mousemove';
|
|
38
|
+
end = 'mouseup';
|
|
39
|
+
which = 1;
|
|
40
|
+
} else if (mode === 'touch') {
|
|
41
|
+
start = 'touchstart';
|
|
42
|
+
move = 'touchmove';
|
|
43
|
+
end = 'touchend';
|
|
44
|
+
} else {
|
|
45
|
+
throw new Error(`Unsupported mode: '${mode}'`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const itemElement = find(itemSelector);
|
|
49
|
+
const itemOffset = getOffset(itemElement);
|
|
50
|
+
const offset = offsetFn();
|
|
51
|
+
const rect = itemElement.getBoundingClientRect();
|
|
52
|
+
// firefox gives some elements, like <svg>, a clientHeight of 0.
|
|
53
|
+
// we can try to grab it off the parent instead to have a better
|
|
54
|
+
// guess at what the scale is.
|
|
55
|
+
// https://bugzilla.mozilla.org/show_bug.cgi?id=874811#c14
|
|
56
|
+
// https://stackoverflow.com/a/13647345
|
|
57
|
+
// https://stackoverflow.com/a/5042051
|
|
58
|
+
const dx = offset.dx || 0;
|
|
59
|
+
const dy = offset.dy || 0;
|
|
60
|
+
const clientHeight = itemElement.clientHeight || itemElement.offsetHeight || itemElement.parentNode.offsetHeight;
|
|
61
|
+
const scale = clientHeight / (rect.bottom - rect.top);
|
|
62
|
+
const halfwayX = itemOffset.left + (dx * scale) / 2;
|
|
63
|
+
const halfwayY = itemOffset.top + (dy * scale) / 2;
|
|
64
|
+
const targetX = itemOffset.left + dx * scale;
|
|
65
|
+
const targetY = itemOffset.top + dy * scale;
|
|
66
|
+
|
|
67
|
+
await triggerEvent(itemElement, start, {
|
|
68
|
+
clientX: itemOffset.left,
|
|
69
|
+
clientY: itemOffset.top,
|
|
70
|
+
which,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
if (callbacks.dragstart) {
|
|
74
|
+
await callbacks.dragstart();
|
|
75
|
+
await settled();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
await triggerEvent(itemElement, move, {
|
|
79
|
+
clientX: itemOffset.left,
|
|
80
|
+
clientY: itemOffset.top,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
if (callbacks.dragmove) {
|
|
84
|
+
await callbacks.dragmove();
|
|
85
|
+
await settled();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
await triggerEvent(itemElement, move, {
|
|
89
|
+
clientX: halfwayX,
|
|
90
|
+
clientY: halfwayY,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
await triggerEvent(itemElement, move, {
|
|
94
|
+
clientX: targetX,
|
|
95
|
+
clientY: targetY,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
if (callbacks.beforedragend) {
|
|
99
|
+
await callbacks.beforedragend();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
await triggerEvent(itemElement, end, {
|
|
103
|
+
clientX: targetX,
|
|
104
|
+
clientY: targetY,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
if (callbacks.dragend) {
|
|
108
|
+
await callbacks.dragend();
|
|
109
|
+
await settled();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { find, findAll } from '@ember/test-helpers';
|
|
2
|
+
import { drag } from './drag';
|
|
3
|
+
import { getOffset } from '../utils/offset';
|
|
4
|
+
|
|
5
|
+
const OVERSHOOT = 2;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
Reorders elements to the specified state.
|
|
9
|
+
|
|
10
|
+
Examples
|
|
11
|
+
|
|
12
|
+
reorder(
|
|
13
|
+
'mouse',
|
|
14
|
+
'.some-list li',
|
|
15
|
+
'[data-id="66278893"]',
|
|
16
|
+
'[data-id="66278894"]',
|
|
17
|
+
'[data-id="66278892"]'
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
@method reorder
|
|
21
|
+
@param {'mouse'|'touch'} [mode]
|
|
22
|
+
event mode
|
|
23
|
+
@param {String} [itemSelector]
|
|
24
|
+
selector for all items
|
|
25
|
+
@param {...String} [resultSelectors]
|
|
26
|
+
selectors for the resultant order
|
|
27
|
+
@return {Promise}
|
|
28
|
+
*/
|
|
29
|
+
export async function reorder(mode, itemSelector, ...resultSelectors) {
|
|
30
|
+
for (let targetIndex = 0; targetIndex < resultSelectors.length; targetIndex++) {
|
|
31
|
+
const items = findAll(itemSelector);
|
|
32
|
+
const sourceElement = find(resultSelectors[targetIndex]);
|
|
33
|
+
const targetElement = items[targetIndex];
|
|
34
|
+
const dx = getOffset(targetElement).left - OVERSHOOT - getOffset(sourceElement).left;
|
|
35
|
+
const dy = getOffset(targetElement).top - OVERSHOOT - getOffset(sourceElement).top;
|
|
36
|
+
|
|
37
|
+
await drag(mode, sourceElement, () => {
|
|
38
|
+
return { dx: dx, dy: dy };
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const ENTER_KEY = 'Enter';
|
|
2
|
+
const ESCAPE_KEY = 'Escape';
|
|
3
|
+
const SPACE_KEY = 'Space';
|
|
4
|
+
const ARROW_KEYS = {
|
|
5
|
+
LEFT: 'ArrowLeft',
|
|
6
|
+
UP: 'ArrowUp',
|
|
7
|
+
RIGHT: 'ArrowRight',
|
|
8
|
+
DOWN: 'ArrowDown',
|
|
9
|
+
};
|
|
10
|
+
export const ENTER_KEY_CODE = 13;
|
|
11
|
+
export const ESCAPE_KEY_CODE = 27;
|
|
12
|
+
export const SPACE_KEY_CODE = 32;
|
|
13
|
+
export const ARROW_KEY_CODES = {
|
|
14
|
+
LEFT: 37,
|
|
15
|
+
UP: 38,
|
|
16
|
+
RIGHT: 39,
|
|
17
|
+
DOWN: 40,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
function createKeyTest(key, keyCode) {
|
|
21
|
+
return function isKey(event) {
|
|
22
|
+
return event.key === key || event.keyCode === keyCode;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const isEnterKey = createKeyTest(ENTER_KEY, ENTER_KEY_CODE);
|
|
27
|
+
export const isEscapeKey = createKeyTest(ESCAPE_KEY, ESCAPE_KEY_CODE);
|
|
28
|
+
export const isSpaceKey = createKeyTest(SPACE_KEY, SPACE_KEY_CODE);
|
|
29
|
+
export const isLeftArrowKey = createKeyTest(ARROW_KEYS.LEFT, ARROW_KEY_CODES.LEFT);
|
|
30
|
+
export const isUpArrowKey = createKeyTest(ARROW_KEYS.UP, ARROW_KEY_CODES.UP);
|
|
31
|
+
export const isRightArrowKey = createKeyTest(ARROW_KEYS.RIGHT, ARROW_KEY_CODES.RIGHT);
|
|
32
|
+
export const isDownArrowKey = createKeyTest(ARROW_KEYS.DOWN, ARROW_KEY_CODES.DOWN);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Vanilla Javascript equivalent of JQuery's `.offset`.
|
|
2
|
+
* Reference: https://github.com/nefe/You-Dont-Need-jQuery
|
|
3
|
+
*
|
|
4
|
+
* @method getOffset
|
|
5
|
+
* @param {Element} el an element
|
|
6
|
+
*/
|
|
7
|
+
export function getOffset(el) {
|
|
8
|
+
const box = el.getBoundingClientRect();
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
top: box.top + window.pageYOffset - document.documentElement.clientTop,
|
|
12
|
+
left: box.left + window.pageXOffset - document.documentElement.clientLeft,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from 'ember-sortable/modifiers/sortable-group';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from 'ember-sortable/modifiers/sortable-handle';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from 'ember-sortable/modifiers/sortable-item';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from 'ember-sortable/services/ember-sortable';
|
|
Binary file
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ember-sortable",
|
|
3
|
+
"version": "4.0.3",
|
|
4
|
+
"description": "Sortable UI primitives for Ember.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ember-addon",
|
|
7
|
+
"sortable"
|
|
8
|
+
],
|
|
9
|
+
"repository": "https://github.com/adopted-ember-addons/ember-sortable",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"author": "",
|
|
12
|
+
"directories": {
|
|
13
|
+
"doc": "doc",
|
|
14
|
+
"test": "tests"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "ember build",
|
|
18
|
+
"lint:hbs": "ember-template-lint .",
|
|
19
|
+
"lint:js": "eslint .",
|
|
20
|
+
"start": "ember serve",
|
|
21
|
+
"test:ember": "ember test",
|
|
22
|
+
"test:all": "ember try:each",
|
|
23
|
+
"lint": "yarn lint:hbs && yarn lint:js",
|
|
24
|
+
"release": "release-it"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@ember/test-waiters": "^3.0.1",
|
|
28
|
+
"@embroider/macros": "^1.9.0",
|
|
29
|
+
"ember-cli-babel": "^7.26.11",
|
|
30
|
+
"ember-modifier": "^3.2.0"
|
|
31
|
+
},
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": "14.* || >= 16"
|
|
34
|
+
},
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"registry": "https://registry.npmjs.org"
|
|
37
|
+
},
|
|
38
|
+
"ember": {
|
|
39
|
+
"edition": "octane"
|
|
40
|
+
},
|
|
41
|
+
"ember-addon": {
|
|
42
|
+
"configPath": "tests/dummy/config",
|
|
43
|
+
"demoURL": "https://adopted-ember-addons.github.io/ember-sortable/demo/"
|
|
44
|
+
},
|
|
45
|
+
"release-it": {
|
|
46
|
+
"plugins": {
|
|
47
|
+
"release-it-lerna-changelog": {
|
|
48
|
+
"infile": "CHANGELOG.md",
|
|
49
|
+
"launchEditor": false
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"git": {
|
|
53
|
+
"tagName": "v${version}"
|
|
54
|
+
},
|
|
55
|
+
"github": {
|
|
56
|
+
"release": true,
|
|
57
|
+
"tokenRef": "GITHUB_AUTH"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"volta": {
|
|
61
|
+
"node": "14.19.2",
|
|
62
|
+
"yarn": "1.22.18"
|
|
63
|
+
},
|
|
64
|
+
"yalcSig": "ab25b0d0909fb9a6a84df88f6bf1f2f5"
|
|
65
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ab25b0d0909fb9a6a84df88f6bf1f2f5
|
|
@@ -414,7 +414,7 @@ export default Component.extend({
|
|
|
414
414
|
},
|
|
415
415
|
|
|
416
416
|
/**
|
|
417
|
-
* Query for
|
|
417
|
+
* Query for setting a new sort order. Internal method.
|
|
418
418
|
* @method querySort
|
|
419
419
|
* @private
|
|
420
420
|
* @param {Number} page Page number to start
|
|
@@ -551,7 +551,7 @@ export default Component.extend({
|
|
|
551
551
|
page = max;
|
|
552
552
|
}
|
|
553
553
|
|
|
554
|
-
// if we
|
|
554
|
+
// if we have entries at the page number, use those
|
|
555
555
|
// if missing, query them
|
|
556
556
|
if (isNone(this.pageEntries.objectAt(page - 1))) {
|
|
557
557
|
this.incrementProperty('pagesSearching');
|
|
@@ -224,7 +224,18 @@ const TableSortable = Component.extend({
|
|
|
224
224
|
sortOrder: computed('_defaultSort.[]', 'sortColumn', function() {
|
|
225
225
|
let sortColumn = this.sortColumn;
|
|
226
226
|
if (sortColumn) {
|
|
227
|
-
|
|
227
|
+
// this addresses a bug where sorting by the default sort column would break
|
|
228
|
+
// in that case just sort by the selected column and ignore the default sort
|
|
229
|
+
if (this._defaultSort.any((sort) => {
|
|
230
|
+
return sort === sortColumn || sort === `${sortColumn}:desc` || `${sort}:desc` === sortColumn;
|
|
231
|
+
})) {
|
|
232
|
+
return [sortColumn];
|
|
233
|
+
}
|
|
234
|
+
// otherwise add the sort column to the front of the default sort array so the default sort is done after
|
|
235
|
+
let sortOrder = this._defaultSort.slice();
|
|
236
|
+
sortOrder.unshift(sortColumn);
|
|
237
|
+
|
|
238
|
+
return sortOrder;
|
|
228
239
|
}
|
|
229
240
|
return this._defaultSort;
|
|
230
241
|
}),
|
|
@@ -239,7 +250,7 @@ const TableSortable = Component.extend({
|
|
|
239
250
|
sortedData: sort('data', 'sortOrder'),
|
|
240
251
|
|
|
241
252
|
/**
|
|
242
|
-
* Internal table instance, in general changes to the table should be done to columns or data so they update
|
|
253
|
+
* Internal table instance, in general changes to the table should be done to columns or data so they update properly
|
|
243
254
|
*
|
|
244
255
|
* @protected
|
|
245
256
|
* @property table
|
|
@@ -375,7 +386,7 @@ const TableSortable = Component.extend({
|
|
|
375
386
|
// determine how we are sorting
|
|
376
387
|
let sortKey = column.sortKey || column.valuePath;
|
|
377
388
|
|
|
378
|
-
// if the column is now
|
|
389
|
+
// if the column is now descending, sort descending
|
|
379
390
|
if (!column.ascending) {
|
|
380
391
|
sortKey = `${sortKey}:desc`;
|
|
381
392
|
}
|