demarches-normaliennes/app/javascript/controllers/sortable_controller.ts

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
};
}
}