diff --git a/packages/calcite-components/src/components/list/list.e2e.ts b/packages/calcite-components/src/components/list/list.e2e.ts index 27c6c6e9512..db811d55a62 100755 --- a/packages/calcite-components/src/components/list/list.e2e.ts +++ b/packages/calcite-components/src/components/list/list.e2e.ts @@ -659,6 +659,8 @@ describe("calcite-list", () => { calledTimes: number; newIndex: number; oldIndex: number; + startCalledTimes: number; + endCalledTimes: number; }>; it("works using a mouse", async () => { @@ -670,11 +672,19 @@ describe("calcite-list", () => { testWindow.calledTimes = 0; testWindow.newIndex = -1; testWindow.oldIndex = -1; + testWindow.startCalledTimes = 0; + testWindow.endCalledTimes = 0; list.addEventListener("calciteListOrderChange", (event: CustomEvent) => { testWindow.calledTimes++; testWindow.newIndex = event?.detail?.newIndex; testWindow.oldIndex = event?.detail?.oldIndex; }); + list.addEventListener("calciteListDragEnd", () => { + testWindow.endCalledTimes++; + }); + list.addEventListener("calciteListDragStart", () => { + testWindow.startCalledTimes++; + }); }); await dragAndDrop( @@ -696,10 +706,19 @@ describe("calcite-list", () => { const results = await page.evaluate(() => { const testWindow = window as TestWindow; - return { calledTimes: testWindow.calledTimes, oldIndex: testWindow.oldIndex, newIndex: testWindow.newIndex }; + + return { + calledTimes: testWindow.calledTimes, + oldIndex: testWindow.oldIndex, + newIndex: testWindow.newIndex, + endCalledTimes: testWindow.endCalledTimes, + startCalledTimes: testWindow.startCalledTimes, + }; }); expect(results.calledTimes).toBe(1); + expect(results.startCalledTimes).toBe(1); + expect(results.endCalledTimes).toBe(1); expect(results.oldIndex).toBe(0); expect(results.newIndex).toBe(1); }); diff --git a/packages/calcite-components/src/components/list/list.tsx b/packages/calcite-components/src/components/list/list.tsx index 62b140c1f7f..b10cd486b6f 100755 --- a/packages/calcite-components/src/components/list/list.tsx +++ b/packages/calcite-components/src/components/list/list.tsx @@ -220,6 +220,16 @@ export class List */ @Event({ cancelable: false }) calciteListChange: EventEmitter; + /** + * Emits when the component's dragging has ended. + */ + @Event({ cancelable: false }) calciteListDragEnd: EventEmitter; + + /** + * Emits when the component's dragging has started. + */ + @Event({ cancelable: false }) calciteListDragStart: EventEmitter; + /** * Emits when the component's filter has changed. */ @@ -598,14 +608,22 @@ export class List connectSortableComponent(this); } - onDragStart(): void { + onGlobalDragStart(): void { this.disconnectObserver(); } - onDragEnd(): void { + onGlobalDragEnd(): void { this.connectObserver(); } + onDragEnd(): void { + this.calciteListDragEnd.emit(); + } + + onDragStart(): void { + this.calciteListDragStart.emit(); + } + onDragSort(detail: ListDragDetail): void { this.setParentList(); this.updateListItems(); diff --git a/packages/calcite-components/src/components/sortable-list/sortable-list.tsx b/packages/calcite-components/src/components/sortable-list/sortable-list.tsx index 347f95e1bc6..85720792418 100644 --- a/packages/calcite-components/src/components/sortable-list/sortable-list.tsx +++ b/packages/calcite-components/src/components/sortable-list/sortable-list.tsx @@ -146,14 +146,18 @@ export class SortableList implements InteractiveComponent, SortableComponent { // // -------------------------------------------------------------------------- - onDragStart(): void { + onGlobalDragStart(): void { this.endObserving(); } - onDragEnd(): void { + onGlobalDragEnd(): void { this.beginObserving(); } + onDragEnd(): void {} + + onDragStart(): void {} + onDragSort(): void { this.items = Array.from(this.el.children); this.calciteListOrderChange.emit(); diff --git a/packages/calcite-components/src/components/value-list/value-list.tsx b/packages/calcite-components/src/components/value-list/value-list.tsx index 25780cc7cf6..122eff4095f 100644 --- a/packages/calcite-components/src/components/value-list/value-list.tsx +++ b/packages/calcite-components/src/components/value-list/value-list.tsx @@ -333,14 +333,18 @@ export class ValueList< // // -------------------------------------------------------------------------- - onDragStart(): void { + onGlobalDragStart(): void { cleanUpObserver.call(this); } - onDragEnd(): void { + onGlobalDragEnd(): void { initializeObserver.call(this); } + onDragEnd(): void {} + + onDragStart(): void {} + onDragSort(): void { this.items = Array.from(this.el.querySelectorAll("calcite-value-list-item")); const values = this.items.map((item) => item.value); diff --git a/packages/calcite-components/src/utils/sortableComponent.ts b/packages/calcite-components/src/utils/sortableComponent.ts index c6865de793b..699da0de0eb 100644 --- a/packages/calcite-components/src/utils/sortableComponent.ts +++ b/packages/calcite-components/src/utils/sortableComponent.ts @@ -60,19 +60,29 @@ export interface SortableComponent { canPut: (detail: DragDetail) => boolean; /** - * Called by any change to the list (add / update / remove). + * Called when any sortable component drag starts. For internal use only. Any public drag events should emit within `onDragStart()`. */ - onDragSort: (detail: DragDetail) => void; + onGlobalDragStart: () => void; + + /** + * Called when any sortable component drag ends. For internal use only. Any public drag events should emit within `onDragEnd()`. + */ + onGlobalDragEnd: () => void; /** - * Called when a sortable component drag starts. + * Called when a component's dragging ends. */ - onDragStart: () => void; + onDragEnd: (detail: DragDetail) => void; /** - * Called when a sortable component drag ends. + * Called when a component's dragging starts. */ - onDragEnd: () => void; + onDragStart: (detail: DragDetail) => void; + + /** + * Called by any change to the list (add / update / remove). + */ + onDragSort: (detail: DragDetail) => void; } export interface SortableComponentItem { @@ -119,13 +129,15 @@ export function connectSortableComponent(component: SortableComponent): void { }), handle, filter: "[drag-disabled]", - onStart: () => { + onStart: ({ from: fromEl, item: dragEl, to: toEl, newIndex, oldIndex }) => { dragState.active = true; - onDragStart(); + onGlobalDragStart(); + component.onDragStart({ fromEl, dragEl, toEl, newIndex, oldIndex }); }, - onEnd: () => { + onEnd: ({ from: fromEl, item: dragEl, to: toEl, newIndex, oldIndex }) => { dragState.active = false; - onDragEnd(); + onGlobalDragEnd(); + component.onDragEnd({ fromEl, dragEl, toEl, newIndex, oldIndex }); }, onSort: ({ from: fromEl, item: dragEl, to: toEl, newIndex, oldIndex }) => { component.onDragSort({ fromEl, dragEl, toEl, newIndex, oldIndex }); @@ -157,10 +169,10 @@ export function dragActive(component: SortableComponent): boolean { return component.dragEnabled && dragState.active; } -function onDragStart(): void { - Array.from(sortableComponentSet).forEach((component) => component.onDragStart()); +function onGlobalDragStart(): void { + Array.from(sortableComponentSet).forEach((component) => component.onGlobalDragStart()); } -function onDragEnd(): void { - Array.from(sortableComponentSet).forEach((component) => component.onDragEnd()); +function onGlobalDragEnd(): void { + Array.from(sortableComponentSet).forEach((component) => component.onGlobalDragEnd()); }