68 lines
1.7 KiB
TypeScript
68 lines
1.7 KiB
TypeScript
import Sortable from 'sortablejs';
|
|
|
|
import { ApplicationController } from './application_controller';
|
|
|
|
export class SortableController extends ApplicationController {
|
|
declare readonly animationValue: number;
|
|
declare readonly handleValue: string;
|
|
declare readonly groupValue: string;
|
|
|
|
#sortable?: Sortable;
|
|
|
|
static values = {
|
|
animation: Number,
|
|
handle: String,
|
|
group: String
|
|
};
|
|
|
|
connect() {
|
|
this.#sortable = new Sortable(this.element as HTMLElement, {
|
|
...this.defaultOptions,
|
|
...this.options
|
|
});
|
|
this.onGlobal('sortable:sort', () => this.setEdgeClassNames());
|
|
}
|
|
|
|
disconnect() {
|
|
this.#sortable?.destroy();
|
|
}
|
|
|
|
private onEnd({ item, newIndex }: { item: HTMLElement; newIndex?: number }) {
|
|
if (newIndex == null) return;
|
|
|
|
this.dispatch('end', {
|
|
target: item,
|
|
detail: { position: newIndex }
|
|
});
|
|
this.setEdgeClassNames();
|
|
}
|
|
|
|
setEdgeClassNames() {
|
|
const items = this.element.children;
|
|
for (const item of items) {
|
|
item.classList.remove('first', 'last');
|
|
}
|
|
if (items.length > 1) {
|
|
const first = items[0];
|
|
const last = items[items.length - 1];
|
|
first?.classList.add('first');
|
|
last?.classList.add('last');
|
|
}
|
|
}
|
|
|
|
get options(): Sortable.Options {
|
|
return {
|
|
animation: this.animationValue || this.defaultOptions.animation || 150,
|
|
handle: this.handleValue || this.defaultOptions.handle || undefined,
|
|
group: this.groupValue || this.defaultOptions.group || undefined,
|
|
onEnd: (event) => this.onEnd(event)
|
|
};
|
|
}
|
|
|
|
get defaultOptions(): Sortable.Options {
|
|
return {
|
|
fallbackOnBody: true,
|
|
swapThreshold: 0.65
|
|
};
|
|
}
|
|
}
|