diff --git a/README.md b/README.md index f9b9c6b3..8c7a4dd2 100644 --- a/README.md +++ b/README.md @@ -116,15 +116,16 @@ const Gallery = () => { } } ``` - +- `syncStateOnPropsUpdate`: Boolean, default `true` - Sync some props (like `activeIndex`) with carousel state while new props passed. This allows you to avoid resetting the carousel position while updating the props (e.g.: `children` or `items`). - `swipeDelta`: Number, default `20` - Set minimum distance to the start of the swiping (px). - `swipeExtraPadding`: Number, default `200` - Set maximum distance from initial place before swipe action will be stopped (px). - `ssrSilentMode`: Boolean, default `true` - Disable classnames modifiers for server side rendering. - `touchTracking`: Boolean, default `true` - Enable touch move animation. - `touchMoveDefaultEvents`: Boolean, default `true` - Enable touch move default events on swiping. If `false` was specified, this prevents vertical scrolling of the parent elements during the swipe. - `onInitialized(e: EventObject)`: Function - Fired as callback after the gallery was created. -- `onResizeEvent(e: Event)`: Function - Fired during the "resize" event to determine whether to call the event handler. Default result of `() => true`; +- `onResizeEvent(e: Event)`: Function, default `shouldProcessResizeEvent` method - Fired during the "resize" event to determine whether to call the event handler. Default method checks is the root element width has changed. - `onResized(e: EventObject)`: Function - Fired as callback after the gallery was resized. +- `onUpdated(e: EventObject)`: Function - Fired as callback after updating the gallery props. - `onSlideChange(e: EventObject)`: Function - Fired before the event object changes. - `onSlideChanged(e: EventObject)`: Function - Fired after the event object was changed. - `renderSlideInfo(e: SlideInfo)`: Rendering function - create a custom component. @@ -133,7 +134,7 @@ const Gallery = () => { - `renderNextButton({ isDisabled })`: Rendering function - create a custom component. - `renderPlayPauseButton({ isPlaying })`: Rendering function - create a custom component. -#### Methods +#### Methods (Refs [example](https://maxmarinich.github.io/react-alice-carousel/#custom-components-refs)) - `slidePrev(e: Event) => void` : Go to the prev slide. - `slideNext(e: Event) => void` : Go to the next slide. - `slideTo(activeIndex?: number) => void` : Go to the specified slide. @@ -163,7 +164,7 @@ enum EventType { ACTION = 'action', // used if a general user action (button click or swipe) INIT = 'init', // used if the initial event was triggered RESIZE = 'resize', // used if the gallery size was changed - UPDATE = 'update', // used if the gallery was updated with props (activeIndex) + UPDATE = 'update', // used if the gallery was updated with props } ``` diff --git a/package-lock.json b/package-lock.json index 1e2a1a71..458dda51 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "react-alice-carousel", - "version": "2.7.1", + "version": "2.8.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "react-alice-carousel", - "version": "2.7.1", + "version": "2.8.0", "license": "MIT", "dependencies": { "vanilla-swipe": "^2.4.1" diff --git a/package.json b/package.json index b93be317..ea154a01 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-alice-carousel", - "version": "2.7.1", + "version": "2.8.0", "description": "React image gallery, react slideshow carousel, react content rotator", "main": "./lib/react-alice-carousel.js", "types": "./lib/react-alice-carousel.d.ts", diff --git a/src/components/app.tsx b/src/components/app.tsx index ead34b7a..f25a08a9 100644 --- a/src/components/app.tsx +++ b/src/components/app.tsx @@ -3,12 +3,13 @@ import Header from './header'; import Navigation from './navigation'; import getPageComponent from './pages'; import scheme from './scheme'; +import { scrollTo } from '../hooks/useScroll'; import '../main.scss'; import '../lib/scss/alice-carousel.scss'; export default function App() { const [defaultPage] = scheme; - const [{ id, title }, setPage] = useState(defaultPage); + const [page, setPage] = useState(defaultPage); useEffect(() => { const { hash = '#' } = window.location; @@ -16,7 +17,13 @@ export default function App() { const page = scheme.find(({ id }) => id === hashId || hashId.includes(id)); if (page) setPage(page); - }, []); + + requestAnimationFrame(() => { + if (hash.length > 1) { + scrollTo(hash); + } + }); + }, [page]); return (
@@ -24,9 +31,9 @@ export default function App() {

- {title} example + {page.title} example

- {getPageComponent(id)} + {getPageComponent(page.id)}
); diff --git a/src/components/pages/auto-width/index.tsx b/src/components/pages/auto-width/index.tsx index ffc7153f..fa9bdd77 100644 --- a/src/components/pages/auto-width/index.tsx +++ b/src/components/pages/auto-width/index.tsx @@ -7,7 +7,7 @@ const AutowidthPage = () => { return (

- +   Base

diff --git a/src/components/pages/custom-components/event-components/index.jsx b/src/components/pages/custom-components/event-components/index.jsx deleted file mode 100644 index 01050b7f..00000000 --- a/src/components/pages/custom-components/event-components/index.jsx +++ /dev/null @@ -1,87 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var react_1 = require("react"); -var code_md_1 = require("./code.md"); -var the_code_1 = require("../../../the-code"); -var react_alice_carousel_1 = require("../../../../lib/react-alice-carousel"); -var items = [ -
- 1 -
, -
- 2 -
, -
- 3 -
, -
- 4 -
, -
- 5 -
, -]; -var thumbItems = function (items, _a) { - var setThumbIndex = _a[0], setThumbAnimation = _a[1]; - return items.map(function (item, i) { return (
- {item} -
); }); -}; -var Carousel = function () { - var _a = (0, react_1.useState)(0), mainIndex = _a[0], setMainIndex = _a[1]; - var _b = (0, react_1.useState)(false), mainAnimation = _b[0], setMainAnimation = _b[1]; - var _c = (0, react_1.useState)(0), thumbIndex = _c[0], setThumbIndex = _c[1]; - var _d = (0, react_1.useState)(false), thumbAnimation = _d[0], setThumbAnimation = _d[1]; - var thumbs = (0, react_1.useState)(thumbItems(items, [setThumbIndex, setThumbAnimation]))[0]; - var slideNext = function () { - if (!thumbAnimation && thumbIndex < thumbs.length - 1) { - setThumbAnimation(true); - setThumbIndex(thumbIndex + 1); - } - }; - var slidePrev = function () { - if (!thumbAnimation && thumbIndex > 0) { - setThumbAnimation(true); - setThumbIndex(thumbIndex - 1); - } - }; - var syncMainBeforeChange = function () { - setMainAnimation(true); - }; - var syncMainAfterChange = function (e) { - setMainAnimation(false); - if (e.type === 'action') { - setThumbIndex(e.item); - setThumbAnimation(false); - } - else { - setMainIndex(thumbIndex); - } - }; - var syncThumbs = function (e) { - setThumbIndex(e.item); - setThumbAnimation(false); - if (!mainAnimation) { - setMainIndex(e.item); - } - }; - return [ - , -
- -
- ⟨ -
-
- ⟩ -
-
, - ]; -}; -var EventComponentPage = function () { - return (
- {Carousel()} - -
); -}; -exports.default = EventComponentPage; diff --git a/src/components/pages/custom-components/index.jsx b/src/components/pages/custom-components/index.jsx deleted file mode 100644 index 5f1576a7..00000000 --- a/src/components/pages/custom-components/index.jsx +++ /dev/null @@ -1,42 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var react_1 = require("react"); -var render_components_1 = require("./render-components"); -var refs_components_1 = require("./refs-components"); -var props_components_1 = require("./props-components"); -var event_components_1 = require("./event-components"); -var the_anchor_1 = require("../../the-anchor"); -var CustomComponentsPage = function () { - return (
-

- -   Base -

- -
-
-
-

- -   Props -

- -
-
-
-

- -   Render functions -

- -
-
-
-

- -   Refs -

- -
); -}; -exports.default = CustomComponentsPage; diff --git a/src/components/pages/custom-components/index.tsx b/src/components/pages/custom-components/index.tsx index 6b8eedeb..fb4fca05 100644 --- a/src/components/pages/custom-components/index.tsx +++ b/src/components/pages/custom-components/index.tsx @@ -9,7 +9,7 @@ const CustomComponentsPage = () => { return (

- +   Base

diff --git a/src/components/pages/custom-components/props-components/code.md b/src/components/pages/custom-components/props-components/code.md index 6b6686bb..d4a16e28 100644 --- a/src/components/pages/custom-components/props-components/code.md +++ b/src/components/pages/custom-components/props-components/code.md @@ -1,6 +1,7 @@ -```javascript -import React, { useState } from 'react'; +```typescript jsx +import React from 'react'; import AliceCarousel from 'react-alice-carousel'; +import type { EventObject } from 'react-alice-carousel'; import 'react-alice-carousel/lib/alice-carousel.css'; const responsive = { @@ -20,7 +21,7 @@ const createItems = (length, [handleClick]) => { className="item" onMouseDown={(e) => (deltaX = e.pageX)} onMouseUp={(e) => (difference = Math.abs(e.pageX - deltaX))} - onClick={() => (difference < swipeDelta) && handleClick(i)} + onClick={() => difference < swipeDelta && handleClick(i)} > @@ -33,7 +34,16 @@ const Carousel = () => { const slidePrev = () => setActiveIndex(activeIndex - 1); const slideNext = () => setActiveIndex(activeIndex + 1); - const syncActiveIndex = ({ item }) => setActiveIndex(item); + const syncActiveIndexForSwipeGestures = (e: EventObject) => setActiveIndex(e.item); + + const onSlideChanged = (e: EventObject) => { + syncActiveIndexForSwipeGestures(e); + console.debug(`onSlideChanged => Item's position after changes: ${e.item}. Event:`, e); + }; + + const onUpdated = (e: EventObject) => { + console.debug(`onUpdated => Item's position after update: ${e.item}. Event:`, e); + }; return [ { items={items} activeIndex={activeIndex} responsive={responsive} - onSlideChanged={syncActiveIndex} + onSlideChanged={onSlideChanged} + onUpdated={onUpdated} />,
diff --git a/src/components/pages/custom-components/props-components/index.jsx b/src/components/pages/custom-components/props-components/index.jsx deleted file mode 100644 index d0b2d451..00000000 --- a/src/components/pages/custom-components/props-components/index.jsx +++ /dev/null @@ -1,40 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var react_1 = require("react"); -var code_md_1 = require("./code.md"); -var the_code_1 = require("../../../the-code"); -var react_alice_carousel_1 = require("../../../../lib/react-alice-carousel"); -var responsive = { - 0: { items: 1 }, - 568: { items: 2 }, - 1024: { items: 3 }, -}; -var createItems = function (length, _a) { - if (length === void 0) { length = 0; } - var handleClick = _a[0]; - var deltaX = 0; - var difference = 0; - var swipeDelta = 20; - return Array.from({ length: length }).map(function (item, i) { return (
- -
); }); -}; -var PropsComponent = function () { - var _a = (0, react_1.useState)(0), activeIndex = _a[0], setActiveIndex = _a[1]; - var items = (0, react_1.useState)(createItems(5, [setActiveIndex]))[0]; - var slidePrev = function () { return setActiveIndex(activeIndex - 1); }; - var slideNext = function () { return setActiveIndex(activeIndex + 1); }; - var syncActiveIndex = function (_a) { - var _b = _a.item, item = _b === void 0 ? 0 : _b; - return setActiveIndex(item); - }; - return (
- -
- - -
- -
); -}; -exports.default = PropsComponent; diff --git a/src/components/pages/custom-components/props-components/index.tsx b/src/components/pages/custom-components/props-components/index.tsx index f0bfc958..76b0f0c4 100644 --- a/src/components/pages/custom-components/props-components/index.tsx +++ b/src/components/pages/custom-components/props-components/index.tsx @@ -3,6 +3,7 @@ import React, { useState } from 'react'; import markdown from './code.md'; import TheCode from '../../../the-code'; import AliceCarousel from '../../../../lib/react-alice-carousel'; +import type { EventObject } from '../../../../lib/react-alice-carousel'; const responsive = { 0: { items: 1 }, @@ -34,7 +35,16 @@ const PropsComponent = () => { const slidePrev = () => setActiveIndex(activeIndex - 1); const slideNext = () => setActiveIndex(activeIndex + 1); - const syncActiveIndex = ({ item = 0 }) => setActiveIndex(item); + const syncActiveIndexForSwipeGestures = ({ item = 0 }) => setActiveIndex(item); + + const onSlideChanged = (e: EventObject) => { + syncActiveIndexForSwipeGestures(e); + console.debug(`onSlideChanged => Item's position after changes: ${e.item}. Event:`, e); + }; + + const onUpdated = (e: EventObject) => { + console.debug(`onUpdated => Item's position after update: ${e.item}. Event:`, e); + }; return (
@@ -45,7 +55,8 @@ const PropsComponent = () => { items={items} activeIndex={activeIndex} responsive={responsive} - onSlideChanged={syncActiveIndex} + onSlideChanged={onSlideChanged} + onUpdated={onUpdated} />
diff --git a/src/components/pages/custom-components/refs-components/index.jsx b/src/components/pages/custom-components/refs-components/index.jsx deleted file mode 100644 index 99a4dced..00000000 --- a/src/components/pages/custom-components/refs-components/index.jsx +++ /dev/null @@ -1,40 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var react_1 = require("react"); -var code_md_1 = require("./code.md"); -var the_code_1 = require("../../../the-code"); -var react_alice_carousel_1 = require("../../../../lib/react-alice-carousel"); -var items = [ -
- 1 -
, -
- 2 -
, -
- 3 -
, -
- 4 -
, -
- 5 -
, -]; -var RefsComponent = function () { - var carousel = (0, react_1.useRef)(null); - return (
- - -
- - -
- -
); -}; -exports.default = RefsComponent; diff --git a/src/components/pages/custom-components/render-components/index.jsx b/src/components/pages/custom-components/render-components/index.jsx deleted file mode 100644 index a9c6ca30..00000000 --- a/src/components/pages/custom-components/render-components/index.jsx +++ /dev/null @@ -1,50 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var react_1 = require("react"); -var code_md_1 = require("./code.md"); -var the_code_1 = require("../../../the-code"); -var react_alice_carousel_1 = require("../../../../lib/react-alice-carousel"); -var items = [ -
- 1 -
, -
- 2 -
, -
- 3 -
, -
- 4 -
, -
- 5 -
, -]; -var renderSlideInfo = function (_a) { - var _b = _a.item, item = _b === void 0 ? 0 : _b, _c = _a.itemsCount, itemsCount = _c === void 0 ? 0 : _c; - return "".concat(item, "\\").concat(itemsCount); -}; -var renderPrevButton = function (_a) { - var _b = _a.isDisabled, isDisabled = _b === void 0 ? false : _b; - return <; -}; -var renderNextButton = function (_a) { - var _b = _a.isDisabled, isDisabled = _b === void 0 ? false : _b; - return >; -}; -var renderPlayPauseButton = function (_a) { - var _b = _a.isPlaying, isPlaying = _b === void 0 ? false : _b; - return isPlaying ? 'PAUSE' : 'PLAY'; -}; -var renderDotsItem = function (_a) { - var _b = _a.isActive, isActive = _b === void 0 ? false : _b; - return isActive ? 'x' : 'o'; -}; -var RenderComponent = function () { - return (
- - -
); -}; -exports.default = RenderComponent; diff --git a/src/components/pages/events/code.md b/src/components/pages/events/change-events/code.md similarity index 58% rename from src/components/pages/events/code.md rename to src/components/pages/events/change-events/code.md index 51abd56e..b48fd9ba 100644 --- a/src/components/pages/events/code.md +++ b/src/components/pages/events/change-events/code.md @@ -1,6 +1,7 @@ -```javascript +```typescript jsx import React from 'react'; import AliceCarousel from 'react-alice-carousel'; +import type { EventObject } from 'react-alice-carousel'; import 'react-alice-carousel/lib/alice-carousel.css'; const responsive = { @@ -17,20 +18,12 @@ const items = [
5
, ]; -const onInitialized = (e) => { - console.debug(`Start position(activeIndex) on init: ${e.item}. Event:`, e); +const onSlideChange = (e: EventObject) => { + console.debug(`onSlideChange => Item's position before a change: ${e.item}. Event:`, e); }; -const onSlideChange = (e) => { - console.debug(`Item's position before a change: ${e.item}. Event:`, e); -}; - -const onSlideChanged = (e) => { - console.debug(`Item's position after changes: ${e.item}. Event:`, e); -}; - -const onResized = (e) => { - console.debug(`Item's position after resize: ${e.item}. Event:`, e); +const onSlideChanged = (e: EventObject) => { + console.debug(`onSlideChanged => Item's position after changes: ${e.item}. Event:`, e); }; const Carousel = () => ( @@ -39,10 +32,8 @@ const Carousel = () => ( keyboardNavigation items={items} responsive={responsive} - onInitialized={onInitialized} onSlideChange={onSlideChange} onSlideChanged={onSlideChanged} - onResized={onResized} /> ); ``` diff --git a/src/components/pages/events/change-events/index.tsx b/src/components/pages/events/change-events/index.tsx new file mode 100644 index 00000000..14dd487c --- /dev/null +++ b/src/components/pages/events/change-events/index.tsx @@ -0,0 +1,53 @@ +import React from 'react'; + +import markdown from './code.md'; +import TheCode from '../../../the-code'; +import AliceCarousel, { EventObject } from '../../../../lib/react-alice-carousel'; + +const responsive = { + 0: { items: 1 }, + 568: { items: 2 }, + 1024: { items: 3 }, +}; + +const items = [ +
+ 1 +
, +
+ 2 +
, +
+ 3 +
, +
+ 4 +
, +
+ 5 +
, +]; + +const onSlideChange = (e: EventObject) => { + console.debug(`onSlideChange => Item's position before a change: ${e.item}. Event:`, e); +}; + +const onSlideChanged = (e: EventObject) => { + console.debug(`onSlideChanged => Item's position after changes: ${e.item}. Event:`, e); +}; + +export default function ChangeEvents() { + return ( +
+ + +
+ ); +} diff --git a/src/components/pages/events/index.tsx b/src/components/pages/events/index.tsx index 788d4abc..fe7e365c 100644 --- a/src/components/pages/events/index.tsx +++ b/src/components/pages/events/index.tsx @@ -1,65 +1,27 @@ import React from 'react'; -import markdown from './code.md'; -import TheCode from '../../the-code'; -import AliceCarousel from '../../../lib/react-alice-carousel'; +import Anchor, { genAnchorProps } from '../../the-anchor'; +import ChangeEventsExample from './change-events'; +import UpdateEventsExample from './update-events'; -const responsive = { - 0: { items: 1 }, - 568: { items: 2 }, - 1024: { items: 3 }, -}; - -const items = [ -
- 1 -
, -
- 2 -
, -
- 3 -
, -
- 4 -
, -
- 5 -
, -]; - -const onInitialized = (e: any) => { - console.debug(`Start position(activeIndex) on init: ${e.item}. Event:`, e); -}; - -const onSlideChange = (e: any) => { - console.debug(`Item's position before a change: ${e.item}. Event:`, e); -}; - -const onSlideChanged = (e: any) => { - console.debug(`Item's position after changes: ${e.item}. Event:`, e); -}; - -const onResized = (e: any) => { - console.debug(`Item's position after resize: ${e.item}. Event:`, e); -}; - -function Events() { +const EventsComponentsPage = () => { return ( -
- - +
+

+ +   Base Events +

+ +
+
+
+

+ +   Change Events +

+
); -} +}; -export default Events; +export default EventsComponentsPage; diff --git a/src/components/pages/events/update-events/code.md b/src/components/pages/events/update-events/code.md new file mode 100644 index 00000000..96be08b1 --- /dev/null +++ b/src/components/pages/events/update-events/code.md @@ -0,0 +1,52 @@ +```typescript jsx +import React from 'react'; +import AliceCarousel from 'react-alice-carousel'; +import type { EventObject } from 'react-alice-carousel'; +import 'react-alice-carousel/lib/alice-carousel.css'; + +const responsive = { + 0: { items: 1 }, + 568: { items: 2 }, + 1024: { items: 3 }, +}; + +const createItems = (length = 5) => { + return Array.from({ length }).map((e, i) =>
{i + 1}
); +}; + +const onInitialized = (e: EventObject) => { + console.debug('onInitialized => ItemsLength:', items.length, 'Event:', e); +}; + +const onResized = (e: EventObject) => { + console.debug('onResized => ItemsLength:', items.length, 'Event:', e); +}; + +const onUpdated = (e: EventObject) => { + console.debug('onUpdated => ItemsLength:', items.length, 'Event:', e); +}; + +const Carousel = () => { + const [items, setItems] = useState(createItems()); + const isDisabled = items.length <= 1; + + return ( +
+
+ + Items ({items.length}) + +
+ +
+ ); +}; +``` diff --git a/src/components/pages/events/update-events/index.tsx b/src/components/pages/events/update-events/index.tsx new file mode 100644 index 00000000..741b103f --- /dev/null +++ b/src/components/pages/events/update-events/index.tsx @@ -0,0 +1,61 @@ +import React, { useState } from 'react'; + +import markdown from './code.md'; +import TheCode from '../../../the-code'; +import AliceCarousel from '../../../../lib/react-alice-carousel'; +import type { EventObject } from '../../../../lib/react-alice-carousel'; + +const responsive = { + 0: { items: 1 }, + 568: { items: 2 }, + 1024: { items: 3 }, +}; + +const createItems = (length = 5) => { + return Array.from({ length }).map((e, i) => ( +
+ {i + 1} +
+ )); +}; + +export default function UpdateEvents() { + const [items, setItems] = useState(createItems()); + + const onInitialized = (e: EventObject) => { + console.debug('onInitialized => ItemsLength:', items.length, 'Event:', e); + }; + + const onResized = (e: EventObject) => { + console.debug('onResized => ItemsLength:', items.length, 'Event:', e); + }; + + const onUpdated = (e: EventObject) => { + console.debug('onUpdated => ItemsLength:', items.length, 'Event:', e); + }; + + return ( +
+
+ + +  Items ({items.length})  + + +
+ + + +
+ ); +} diff --git a/src/components/pages/stage-padding/index.tsx b/src/components/pages/stage-padding/index.tsx index d744ddf7..640453a5 100644 --- a/src/components/pages/stage-padding/index.tsx +++ b/src/components/pages/stage-padding/index.tsx @@ -7,7 +7,7 @@ const StagePaddingPage = () => { return (

- +   Base

diff --git a/src/hooks/useScroll.tsx b/src/hooks/useScroll.tsx new file mode 100644 index 00000000..d17b560e --- /dev/null +++ b/src/hooks/useScroll.tsx @@ -0,0 +1,16 @@ +import { useEffect } from 'react'; + +export const scrollTo = (selector = '', behavior: ScrollBehavior = 'smooth') => { + const section = document.querySelector(selector); + if (section) { + section.scrollIntoView({ behavior, block: 'start' }); + } +}; + +export default function UseScroll() { + useEffect(() => { + scrollTo('#root'); + }, []); + + return null; +} diff --git a/src/lib/defaultProps.ts b/src/lib/defaultProps.ts index ef6eb698..a994d647 100644 --- a/src/lib/defaultProps.ts +++ b/src/lib/defaultProps.ts @@ -22,6 +22,7 @@ export const defaultProps = { items: undefined, keyboardNavigation: false, mouseTracking: false, + syncStateOnPropsUpdate: true, name: '', paddingLeft: 0, paddingRight: 0, @@ -33,6 +34,7 @@ export const defaultProps = { touchMoveDefaultEvents: true, onInitialized: () => undefined, onResized: () => undefined, + onUpdated: () => undefined, onResizeEvent: undefined, onSlideChange: () => undefined, onSlideChanged: () => undefined, diff --git a/src/lib/react-alice-carousel.tsx b/src/lib/react-alice-carousel.tsx index 63728c6a..896f128b 100644 --- a/src/lib/react-alice-carousel.tsx +++ b/src/lib/react-alice-carousel.tsx @@ -68,7 +68,7 @@ export default class AliceCarousel extends React.PureComponent { this.props.autoPlay && this._handlePlay(); } - componentDidUpdate(prevProps: Readonly, state: Readonly) { + componentDidUpdate(prevProps: Readonly) { const { activeIndex, animationDuration, @@ -86,12 +86,8 @@ export default class AliceCarousel extends React.PureComponent { touchMoveDefaultEvents, } = this.props; - if (children && prevProps.children !== children) { - const { activeIndex } = state; - const props = { ...this.props, activeIndex }; - - this._updateComponent(props); - } else if ( + if ( + (children && prevProps.children !== children) || prevProps.autoWidth !== autoWidth || prevProps.infinite !== infinite || prevProps.items !== items || @@ -234,9 +230,9 @@ export default class AliceCarousel extends React.PureComponent { async _handleResize(e: Event) { const { onResizeEvent } = this.props; const nextRootComponentDimensions = Utils.getElementDimensions(this.rootElement); - const shouldProcessEvent = onResizeEvent || Utils.shouldHandleResizeEvent; + const shouldProcessResizeEvent = onResizeEvent || Utils.shouldHandleResizeEvent; - if (shouldProcessEvent(e, this.rootComponentDimensions, nextRootComponentDimensions)) { + if (shouldProcessResizeEvent(e, this.rootComponentDimensions, nextRootComponentDimensions)) { this._cancelTimeoutAnimations(); this.rootComponentDimensions = nextRootComponentDimensions; @@ -425,6 +421,12 @@ export default class AliceCarousel extends React.PureComponent { }); } + _handleUpdated() { + if (this.props.onUpdated) { + this.props.onUpdated({ ...this.eventObject, type: EventType.UPDATE }); + } + } + _handleResized() { if (this.props.onResized) { this.props.onResized({ ...this.eventObject, type: EventType.RESIZE }); @@ -452,6 +454,11 @@ export default class AliceCarousel extends React.PureComponent { const event = eventType ? { ...this.eventObject, type: eventType } : this.eventObject; onSlideChanged(event); } + + // Emits event that props were updated + if (eventType === EventType.UPDATE) { + this._handleUpdated(); + } } _handleDotClick(index: number) { @@ -567,7 +574,10 @@ export default class AliceCarousel extends React.PureComponent { this.swipeListener.init(); } - _updateComponent(props = this.props) { + _updateComponent() { + const { activeIndex } = this.props.syncStateOnPropsUpdate ? this.state : this.props; + const props = { ...this.props, activeIndex }; + this._cancelTimeoutAnimations(); this.isAnimationDisabled = false; this.state.isAutoPlaying && this._handlePlay(); @@ -575,7 +585,7 @@ export default class AliceCarousel extends React.PureComponent { this.setState({ clones: Utils.createClones(props) }); requestAnimationFrame(() => { - this.setState(Utils.calculateInitialState(props, this.stageComponent)); + this.setState(Utils.calculateInitialState(props, this.stageComponent), () => this._handleUpdated()); }); } diff --git a/src/lib/types/index.ts b/src/lib/types/index.ts index 9dec8d57..366d0da8 100644 --- a/src/lib/types/index.ts +++ b/src/lib/types/index.ts @@ -22,6 +22,7 @@ export interface Props { items?: any[]; keyboardNavigation?: boolean; mouseTracking?: boolean; + syncStateOnPropsUpdate?: boolean; name?: string; paddingLeft?: number; paddingRight?: number; @@ -36,6 +37,7 @@ export interface Props { onInitialized?: (e: EventObject) => void; onResizeEvent?: (e: Event, prevProps: RootElement, nextProps: RootElement) => boolean; onResized?: (e: EventObject) => void; + onUpdated?: (e: EventObject) => void; onSlideChange?: (e: EventObject) => void; onSlideChanged?: (e: EventObject) => void; renderSlideInfo?: (e: SlideInfo) => ReactNode; diff --git a/src/lib/utils/elements.ts b/src/lib/utils/elements.ts index 42e54543..a2178606 100644 --- a/src/lib/utils/elements.ts +++ b/src/lib/utils/elements.ts @@ -11,7 +11,7 @@ export const getSlides = (props: Props) => { return items; }; -export const getItemsCount = (props: Props) => { +export const getItemsCount = (props: Props): number => { return getSlides(props).length; }; @@ -294,7 +294,7 @@ export const getItemsInSlide = (itemsCount: number, props: Props) => { const value = innerWidth === undefined ? window.innerWidth : innerWidth; configKeys.forEach((key) => { if (Number(key) <= value) { - const { items, itemsFit = 'fill' } = responsive[key]; + const { items, itemsFit = 'fill' } = responsive[key]; if (itemsFit === 'contain') { itemsInSlide = items; } else { diff --git a/src/main.scss b/src/main.scss index f9ae940f..14107f98 100644 --- a/src/main.scss +++ b/src/main.scss @@ -74,3 +74,6 @@ html, border-radius: 6px; } } +.btn { + color: $color-dark-lighten +}