Skip to content

Commit d9774df

Browse files
authored
feat: add flag to carousel onActiveIdUpdate to denote if the update was initiated by autoplay (#1970)
completing as code owner
1 parent b440051 commit d9774df

File tree

4 files changed

+59
-6
lines changed

4 files changed

+59
-6
lines changed

packages/fast-components-react-msft/src/carousel/carousel.props.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export interface CarouselHandledProps extends CarouselManagedClasses {
6464
/**
6565
* The callback which is fired when the active id is changed
6666
*/
67-
onActiveIdUpdate?: (activeId: string) => void;
67+
onActiveIdUpdate?: (activeId: string, isAutoplay?: boolean) => void;
6868

6969
/**
7070
* The carousel items

packages/fast-components-react-msft/src/carousel/carousel.spec.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,22 @@ describe("carousel", (): void => {
292292
expect(onActiveIdUpdateFn.mock.results[2].value).toBe("id02");
293293
});
294294

295+
test("should provide the `isAutoplayInitiated` value to `onActiveIdUpdate` when prop is passed", () => {
296+
const onActiveIdUpdateFn: any = jest.fn(
297+
(id: string, autoplayInitiated: boolean) => autoplayInitiated
298+
);
299+
const rendered: any = mount(
300+
<MSFTCarousel {...handledProps} onActiveIdUpdate={onActiveIdUpdateFn} />
301+
);
302+
303+
rendered
304+
.find('[role="tab"]')
305+
.at(1)
306+
.simulate("click");
307+
308+
expect(onActiveIdUpdateFn.mock.results[0].value).toBe(false);
309+
});
310+
295311
describe("autoplay", (): void => {
296312
const mockFocus: any = jest.fn();
297313
const mockHover: any = jest.fn();
@@ -309,6 +325,18 @@ describe("carousel", (): void => {
309325
expect(rendered.props().autoplay).toBe(false);
310326
});
311327

328+
test("should automatically advance the slide when `autoplay` prop is passed to the component", () => {
329+
jest.useFakeTimers();
330+
331+
const rendered: any = mount(<MSFTCarousel {...props} autoplay={true} />);
332+
333+
expect(rendered.state().activeId).toBe("id01");
334+
335+
jest.advanceTimersByTime(6001);
336+
337+
expect(rendered.state().activeId).toBe("id02");
338+
});
339+
312340
test("should set `autoplay` to true when `autoplay` is passed as true", () => {
313341
const rendered: any = mount(<MSFTCarousel {...props} autoplay={true} />);
314342

packages/fast-components-react-msft/src/carousel/carousel.stories.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import CarouselHero from "../../assets/carousel-hero-content";
77
storiesOf("Carousel", module).add("Default", () => (
88
<Carousel
99
label="A carousel of items"
10+
autoplay={true}
1011
items={[
1112
{
1213
id: uniqueId(),

packages/fast-components-react-msft/src/carousel/carousel.tsx

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ class Carousel extends Foundation<
8484
activeId:
8585
typeof this.props.activeId === "string"
8686
? this.props.activeId
87-
: get(this.props.items[0], "id", ""),
87+
: get(this.props.items[0], "id", " "),
8888
};
8989
}
9090
}
@@ -120,7 +120,7 @@ class Carousel extends Foundation<
120120
if (canUseDOM() && this.props.autoplay) {
121121
// Set initial interval for autoplay
122122
this.autoplayTimer = window.setInterval(
123-
this.nextSlide,
123+
this.autoplayNextSlide,
124124
this.props.autoplayInterval
125125
);
126126
}
@@ -133,7 +133,7 @@ class Carousel extends Foundation<
133133
if (this.props.autoplay && isNil(this.autoplayTimer)) {
134134
// Set the window interval if we are in autplay and don't have a timer
135135
this.autoplayTimer = window.setInterval(
136-
this.nextSlide,
136+
this.autoplayNextSlide,
137137
this.props.autoplayInterval
138138
);
139139
} else if (!this.props.autoplay && !isNil(this.autoplayTimer)) {
@@ -319,7 +319,7 @@ class Carousel extends Foundation<
319319
*/
320320
private handleUpdate = (activeTab: string): void => {
321321
if (typeof this.props.onActiveIdUpdate === "function") {
322-
this.props.onActiveIdUpdate(activeTab);
322+
this.props.onActiveIdUpdate(activeTab, false);
323323
}
324324

325325
this.setState({
@@ -333,6 +333,29 @@ class Carousel extends Foundation<
333333
this.setTransitionDirection(activeTabIndex);
334334
};
335335

336+
/**
337+
* Handles automation of slide movement
338+
*/
339+
private autoplayNextSlide = (): void => {
340+
let nextPosition: number = this.getActiveIndex() + 1;
341+
342+
if (nextPosition > this.slides.length - 1) {
343+
nextPosition = 0;
344+
}
345+
346+
const activeId: string = this.slides[nextPosition].id;
347+
348+
this.setTransitionDirection(nextPosition);
349+
350+
if (typeof this.props.onActiveIdUpdate === "function") {
351+
this.props.onActiveIdUpdate(activeId, true);
352+
}
353+
354+
this.setState({
355+
activeId,
356+
});
357+
};
358+
336359
/**
337360
* Move to next slide if applicable
338361
*/
@@ -368,8 +391,9 @@ class Carousel extends Foundation<
368391
const newActiveId: string = this.slides[position].id;
369392

370393
if (typeof this.props.onActiveIdUpdate === "function") {
371-
this.props.onActiveIdUpdate(newActiveId);
394+
this.props.onActiveIdUpdate(newActiveId, false);
372395
}
396+
373397
this.setState({
374398
activeId: newActiveId,
375399
});

0 commit comments

Comments
 (0)