Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion addon/components/sortable-group.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Ember from 'ember';
import layout from '../templates/components/sortable-group';
import computed from 'ember-new-computed';
import { computed } from '@ember/object';
const { A, Component, get, set, run } = Ember;
Comment on lines +3 to 4

Copilot AI May 1, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ember/object imports won’t resolve in the current ember-try scenarios that use bower Ember (e.g., 1.13). This will break those builds/tests unless the addon is migrated to ember-source + ember-modules. Also, the line has trailing whitespace which violates the repo’s .editorconfig (trim_trailing_whitespace = true).

Suggested change
import { computed } from '@ember/object';
const { A, Component, get, set, run } = Ember;
const { A, Component, computed, get, set, run } = Ember;

Copilot uses AI. Check for mistakes.
const a = A;
const NO_MODEL = {};
Expand Down
25 changes: 18 additions & 7 deletions addon/mixins/sortable-item.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Ember from 'ember';
import computed from 'ember-new-computed';
import { computed } from '@ember/object';
const { Mixin, $, run } = Ember;
const { Promise } = Ember.RSVP;

Expand Down Expand Up @@ -103,6 +103,7 @@ export default Mixin.create({
*/
isAnimated: computed(function() {
let el = this.$();
if (el === undefined || el === null) return false;
let property = el.css('transition-property');

return /all|transform/.test(property);
Expand All @@ -115,6 +116,7 @@ export default Mixin.create({
*/
transitionDuration: computed(function() {
let el = this.$();
if (el === undefined || el === null) return 0;
let rule = el.css('transition-duration');
let match = rule.match(/([\d\.]+)([ms]*)/);

Expand All @@ -140,7 +142,9 @@ export default Mixin.create({
x: computed({
get() {
if (this._x === undefined) {
let marginLeft = parseFloat(this.$().css('margin-left'));
let el = this.$()
if (el === undefined || el === null) return 0;
let marginLeft = parseFloat(el.css('margin-left'));
this._x = this.element.scrollLeft + this.element.offsetLeft - marginLeft;
}

Expand Down Expand Up @@ -182,6 +186,7 @@ export default Mixin.create({
*/
width: computed(function() {
let el = this.$();
if (el === undefined || el === null) return 0;
let width = el.outerWidth(true);

width += getBorderSpacing(el).horizontal;
Expand All @@ -196,6 +201,7 @@ export default Mixin.create({
*/
height: computed(function() {
let el = this.$();
if (el === undefined || el === null) return 0;
let height = el.outerHeight();

let marginBottom = parseFloat(el.css('margin-bottom'));
Expand Down Expand Up @@ -401,7 +407,9 @@ export default Mixin.create({

if (groupDirection === 'x') {
let x = this.get('x');
let dx = x - this.element.offsetLeft + parseFloat(this.$().css('margin-left'));
let el = this.$()
if (el === undefined || el === null) return 0;
let dx = x - this.element.offsetLeft + parseFloat(el.css('margin-left'));

this.$().css({
transform: `translateX(${dx}px)`
Expand All @@ -410,8 +418,9 @@ export default Mixin.create({
if (groupDirection === 'y') {
let y = this.get('y');
let dy = y - this.element.offsetTop;

this.$().css({
let el = this.$()
if (el === undefined || el === null) return 0;
el.css({
transform: `translateY(${dy}px)`
});
}
Expand Down Expand Up @@ -485,6 +494,7 @@ export default Mixin.create({
@private
*/
_complete() {
if (this.isDestroyed || this.isDestroying) return;
this.sendAction('onDragStop', this.get('model'));
this.set('isDropping', false);
this.set('wasDropped', true);
Expand Down Expand Up @@ -539,9 +549,10 @@ function getX(event) {
*/
function getBorderSpacing(el) {
el = $(el);

if (el === undefined || el === null) return 0;
let css = el.css('border-spacing'); // '0px 0px'
let [horizontal, vertical] = css.split(' ');
const [horizontal, initialVertical] = css.split(" ");
const vertical = initialVertical === undefined ? horizontal : initialVertical;
Comment on lines 550 to +555

Copilot AI May 1, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getBorderSpacing sometimes returns a number (0), but callers treat its return value as an object (.horizontal/.vertical). This will produce NaN widths/heights. Return a consistent { horizontal: 0, vertical: 0 } shape (and consider guarding when border-spacing CSS is missing/empty).

Copilot uses AI. Check for mistakes.

return {
horizontal: parseFloat(horizontal),
Expand Down
4 changes: 2 additions & 2 deletions addon/utils/arrangement.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export default class Arrangement {
}

walkTree(func) {
walk(this.root, func);
walk(this.root, func, [0]);
}

walkPath(path, func) {
Expand Down Expand Up @@ -131,7 +131,7 @@ export default class Arrangement {
}
}

function walk(slot, func, path = [0]) {
function walk(slot, func, path) {
func(slot, path);

slot.children.forEach((child, index) => {
Expand Down
11 changes: 10 additions & 1 deletion addon/utils/gesture.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export default class Gesture {
this.clientY = 0;
this.listeners = [];
this.isDestroyed = false;
this.isInAnimationFrame = false;
}

/**
Expand Down Expand Up @@ -194,7 +195,14 @@ export default class Gesture {
this.dx = this.x - this.ox;
this.dy = this.y - this.oy;

this.onUpdate(this);
if (this.isInAnimationFrame === false){
this.isInAnimationFrame = true;
window.requestAnimationFrame(() => {
Comment on lines +199 to +200

Copilot AI May 1, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gesture accepts a configurable eventTarget, but this code hard-codes window.requestAnimationFrame, which makes it harder to test and can break if a non-window target is provided. Prefer the global requestAnimationFrame (as used elsewhere in this repo) or a requestAnimationFrame function sourced from eventTarget/injected for tests.

Suggested change
this.isInAnimationFrame = true;
window.requestAnimationFrame(() => {
let requestAnimationFrameFn = this.eventTarget.requestAnimationFrame || requestAnimationFrame;
this.isInAnimationFrame = true;
requestAnimationFrameFn(() => {

Copilot uses AI. Check for mistakes.
if (this.onUpdate) this.onUpdate(this);
this.isInAnimationFrame = false;
});
};

}

/**
Expand All @@ -211,6 +219,7 @@ export default class Gesture {
}
}


/**
@method waitingStop
*/
Expand Down
6 changes: 3 additions & 3 deletions addon/utils/slot.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ export default class Slot {

if (node.isDestroyed || node.isDestroying) { return; }

node.$().css({ width: '', height: '', transform: '' }).height();
node.$().css({ width: '', height: '', transform: '' });
}

/**
Expand All @@ -164,15 +164,15 @@ export default class Slot {

if (node.isDestroyed || node.isDestroying) { return; }

node.$().css('transition', 'none').height();
node.$().css('transition', 'none');
}

thaw() {
let { node } = this;

if (node.isDestroyed || node.isDestroying) { return; }

node.$().css('transition', '').height();
node.$().css('transition', '');
}

/**
Expand Down
1 change: 1 addition & 0 deletions addon/utils/transition-duration.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export default function transitionDuration(el) {
$(el).height(); // force re-flow

let value = $(el).css('transition');
if (value === null || value === undefined) return 0;
let match = value.match(/(all|transform) ([\d\.]+)([ms]*)/);

if (match) {
Expand Down
3 changes: 3 additions & 0 deletions addon/utils/transitionend.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Thanks to http://davidwalsh.name/css-animation-callback

function whichTransitionEvent() {
if (typeof document === "undefined") {
return "";
};
var t;
var el = document.createElement('fake-element');
var transitions = {
Expand Down
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,8 @@
"sortable"
],
"dependencies": {
"ember-cli-babel": "^5.1.5",
"ember-cli-htmlbars": "^1.0.1",
"ember-new-computed": "^1.0.2"
"ember-cli-babel": "^6.6.0",
"ember-cli-htmlbars": "^1.0.1"
},
"ember-addon": {
"configPath": "tests/dummy/config",
Expand Down