From ec178b8050debec74b58ec7e52f5eddfde2130a8 Mon Sep 17 00:00:00 2001 From: Brad Adams Date: Tue, 21 Jun 2022 17:54:56 +0200 Subject: [PATCH] feat: add `components` prop + Add new prop for injecting custom loading component + Update stories --- .../react/src/components/Card/CardEmpty.js | 6 +++--- packages/react/src/index.js | 21 +++++++++++++------ packages/react/src/utils/index.js | 6 +++++- packages/react/stories/index.js | 11 ++++++++++ 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/packages/react/src/components/Card/CardEmpty.js b/packages/react/src/components/Card/CardEmpty.js index ac7b9a3a9..8c9a7affe 100644 --- a/packages/react/src/components/Card/CardEmpty.js +++ b/packages/react/src/components/Card/CardEmpty.js @@ -7,13 +7,13 @@ import { emptyStateAnimation, emptyStateImageAnimation } from './CardAnimation' import CardImage from './CardMedia/Image' import { Content } from './CardContent' import { GlobalContext } from '../../context/GlobalState' -import { isLarge, isSmall } from '../../utils' +import { classNames, isLarge, isSmall } from '../../utils' const Placeholder = styled.span.attrs({ - className: 'microlink_card_placeholder' + className: classNames.placeholderContent })`` -const MediaEmpty = styled(CardImage)` +const MediaEmpty = styled(CardImage).attrs({ className: classNames.placeholderMedia })` ${emptyStateImageAnimation}; ` diff --git a/packages/react/src/index.js b/packages/react/src/index.js index bbcddfe71..165b9d76b 100644 --- a/packages/react/src/index.js +++ b/packages/react/src/index.js @@ -32,6 +32,7 @@ import { useIntersectionObserver } from './utils/hooks' const Card = props => { const { className, + components, fetchData, lazy, loading, @@ -39,7 +40,6 @@ const Card = props => { setData, url, apiKey, // destructuring to avoid pass it - placeholderComponent: CardEmpty, ...restProps } = props @@ -54,6 +54,10 @@ const Card = props => { [mediaProps, props] ) + const { PlaceholderComponent = CardEmpty } = components + + const isLoading = isLoadingUndefined ? loadingState : loading + const isLazyEnabled = useMemo( () => isLazySupported && (lazy === true || isObject(lazy)), [lazy] @@ -69,6 +73,12 @@ const Card = props => { [isLazyEnabled, hasIntersected] ) + const cardWrapClassName = useMemo(() => { + const base = `${classNames.main} ${isLoading ? classNames.placeholder : ''}`.trim() + + return `${base} ${className}`.trim() + }, [className, isLoading]) + const toFetchData = useCallback(() => { if (canFetchData) { setLoading(true) @@ -167,8 +177,6 @@ microlink.io/${error.code.toLowerCase()} useEffect(toFetchData, [url, setData, hasIntersected]) - const isLoading = isLoadingUndefined ? loadingState : loading - if (isError) { return ( @@ -200,14 +208,14 @@ microlink.io/${error.code.toLowerCase()} return ( {isLoading ? ( - + ) : ( <> @@ -225,8 +233,8 @@ const Microlink = props => ( Microlink.defaultProps = { className: '', apiKey: undefined, - placeholderComponent: CardEmpty, autoPlay: true, + components: { PlaceholderComponent: CardEmpty }, controls: true, direction: 'ltr', lazy: true, @@ -241,6 +249,7 @@ Microlink.defaultProps = { Microlink.propTypes = { apiKey: PropTypes.string, autoPlay: PropTypes.bool, + components: PropTypes.shape({ PlaceholderComponent: PropTypes.elementType }), contrast: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]), controls: PropTypes.bool, direction: PropTypes.string, diff --git a/packages/react/src/utils/index.js b/packages/react/src/utils/index.js index 0ed479fdd..66a628665 100644 --- a/packages/react/src/utils/index.js +++ b/packages/react/src/utils/index.js @@ -114,6 +114,7 @@ const BASE_CLASSNAME = 'microlink_card' const CONTENT_BASE_CLASSNAME = `${BASE_CLASSNAME}__content` const MEDIA_BASE_CLASSNAME = `${BASE_CLASSNAME}__media` const CONTROLS_BASE_CLASSNAME = `${MEDIA_BASE_CLASSNAME}__controls` +const PLACEHOLDER_BASE_CLASSNAME = `${BASE_CLASSNAME}__placeholder` export const classNames = { main: BASE_CLASSNAME, @@ -137,5 +138,8 @@ export const classNames = { progressBar: `${CONTROLS_BASE_CLASSNAME}_progress_bar`, progressTime: `${CONTROLS_BASE_CLASSNAME}_progress_time`, spinner: `${CONTROLS_BASE_CLASSNAME}_spinner`, - iframe: `${BASE_CLASSNAME}__iframe` + iframe: `${BASE_CLASSNAME}__iframe`, + placeholder: PLACEHOLDER_BASE_CLASSNAME, + placeholderMedia: `${PLACEHOLDER_BASE_CLASSNAME}_media`, + placeholderContent: `${PLACEHOLDER_BASE_CLASSNAME}_content` } diff --git a/packages/react/stories/index.js b/packages/react/stories/index.js index fd1555f4f..aff0466ac 100644 --- a/packages/react/stories/index.js +++ b/packages/react/stories/index.js @@ -1,5 +1,6 @@ import 'unfetch/polyfill' +import React from 'react' import { storiesOf } from '@storybook/react' import { urls, urlsVideo, urlsAudio, urlsIframe } from './data' @@ -207,3 +208,13 @@ storiesOf('style', module) }) ) ) + +const PlaceholderComponent = () => loading... + +storiesOf('components', module) + .add('PlaceholderComponent', () => + createStoryEntry({ + loading: true, + fetchData: false, + components: { PlaceholderComponent } + }))