Skip to content

Commit

Permalink
fix(combobox, dropdown, input-date-picker, input-time-picker, popover…
Browse files Browse the repository at this point in the history
…, tooltip): Prevent repositioning from affecting other floating components (#7178)

**Related Issue:** #7158

## Summary

This prevent repositioning from affecting other floating components
caused by using a shared, debounced reposition function.

Additionally, this will cancel any in-progress debounced calls if the
component is disconnected.

---------

Co-authored-by: JC Franco <jfranco@esri.com>
  • Loading branch information
driskull and jcfranco authored Jun 23, 2023
1 parent cbf399b commit 1b02dae
Show file tree
Hide file tree
Showing 3 changed files with 188 additions and 149 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ export class InputTimePicker

private getExtendedLocaleConfig(
locale: string
): Parameters<typeof dayjs["updateLocale"]>[1] | undefined {
): Parameters<(typeof dayjs)["updateLocale"]>[1] | undefined {
if (locale === "ar") {
return {
meridiem: (hour) => (hour > 12 ? "م" : "ص"),
Expand Down
33 changes: 28 additions & 5 deletions packages/calcite-components/src/utils/floating-ui.spec.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import { waitForAnimationFrame } from "../tests/utils";
import {
import * as floatingUI from "./floating-ui";
import { FloatingUIComponent } from "./floating-ui";

const {
cleanupMap,
connectFloatingUI,
defaultOffsetDistance,
disconnectFloatingUI,
effectivePlacements,
filterComputedPlacements,
FloatingUIComponent,
getEffectivePlacement,
placements,
positionFloatingUI,
reposition,
repositionDebounceTimeout
} from "./floating-ui";
} = floatingUI;

import * as floatingUIDOM from "@floating-ui/dom";

Expand Down Expand Up @@ -56,15 +58,19 @@ describe("repositioning", () => {
let referenceEl: HTMLButtonElement;
let positionOptions: Parameters<typeof positionFloatingUI>[1];

beforeEach(() => {
fakeFloatingUiComponent = {
function createFakeFloatingUiComponent(): FloatingUIComponent {
return {
open: false,
reposition: async () => {
/* noop */
},
overlayPositioning: "absolute",
placement: "auto"
};
}

beforeEach(() => {
fakeFloatingUiComponent = createFakeFloatingUiComponent();

floatingEl = document.createElement("div");
referenceEl = document.createElement("button");
Expand Down Expand Up @@ -155,6 +161,23 @@ describe("repositioning", () => {
expect(floatingEl.style.position).toBe("fixed");
});
});

it("debounces positioning per instance", async () => {
const positionSpy = jest.spyOn(floatingUI, "positionFloatingUI");
fakeFloatingUiComponent.open = true;

const anotherFakeFloatingUiComponent = createFakeFloatingUiComponent();
anotherFakeFloatingUiComponent.open = true;

floatingUI.reposition(fakeFloatingUiComponent, positionOptions, true);
expect(positionSpy).toHaveBeenCalledTimes(1);

floatingUI.reposition(anotherFakeFloatingUiComponent, positionOptions, true);
expect(positionSpy).toHaveBeenCalledTimes(2);

await new Promise<void>((resolve) => setTimeout(resolve, repositionDebounceTimeout));
expect(positionSpy).toHaveBeenCalledTimes(2);
});
});

it("should have correct value for defaultOffsetDistance", () => {
Expand Down
Loading

0 comments on commit 1b02dae

Please sign in to comment.