From c732e6834f8b8e63f8e7a8114f2aaac1deb705c2 Mon Sep 17 00:00:00 2001 From: chenchen32 Date: Thu, 23 Sep 2021 14:48:20 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20Guide=20=E7=BB=84=E4=BB=B6=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E5=AE=8C=E6=88=90=EF=BC=8Cfixed=20=E5=92=8C=20normal?= =?UTF-8?q?=20=E4=B8=A4=E7=A7=8D=20mode=20=E8=BF=9B=E8=A1=8C=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E6=8B=86=E5=88=86=EF=BC=8C=E5=B9=B6=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95=20fix=EF=BC=9A=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E4=BA=86=E4=B8=80=E4=BA=9B=E6=97=A7=E9=97=AE=E9=A2=98?= =?UTF-8?q?=EF=BC=8C=E7=88=B6=E7=B1=BB=E6=9E=84=E9=80=A0=E5=87=BD=E6=95=B0?= =?UTF-8?q?=20options=20=E4=BC=A0=E9=80=92=E9=97=AE=E9=A2=98=EF=BC=8C?= =?UTF-8?q?=E6=8C=89=E9=92=AE=E6=96=87=E6=A1=88=E9=85=8D=E7=BD=AE=E4=B8=8D?= =?UTF-8?q?=E7=94=9F=E6=95=88=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jest.config.js | 1 + source/components/Guide/Guide.tsx | 80 +++++ source/components/Guide/GuideFixed.tsx | 152 +++++++++ source/components/Guide/GuideNormal.tsx | 85 +++++ .../components/Guide/__tests__/index.test.tsx | 322 ++++++++++++++++++ source/components/Guide/index.tsx | 276 +-------------- source/components/Guide/src/core/popover.js | 2 +- source/components/Guide/src/core/stage.js | 2 +- 8 files changed, 644 insertions(+), 276 deletions(-) create mode 100644 source/components/Guide/Guide.tsx create mode 100644 source/components/Guide/GuideFixed.tsx create mode 100644 source/components/Guide/GuideNormal.tsx create mode 100644 source/components/Guide/__tests__/index.test.tsx diff --git a/jest.config.js b/jest.config.js index 3b15cb6f7..0e1ad9d3f 100644 --- a/jest.config.js +++ b/jest.config.js @@ -24,6 +24,7 @@ const refactoredComp = [ 'Dropdown', 'Input', 'ImageLoader', + 'Guide', ]; const getRefactoredCompMatch = name => { diff --git a/source/components/Guide/Guide.tsx b/source/components/Guide/Guide.tsx new file mode 100644 index 000000000..5034fb656 --- /dev/null +++ b/source/components/Guide/Guide.tsx @@ -0,0 +1,80 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import GuideFixed from './GuideFixed'; +import GuideNormal from './GuideNormal'; +import ConfigConsumer from '../Config/Consumer'; +import { LocaleProperties } from '../Locale'; + +export interface GuideProps { + allowClose?: boolean; + className?: string; + counter?: boolean; + keyboardControl?: boolean; + mask?: boolean; + mode?: string; + onClose?: () => void; + steps?: any[]; + style?: React.CSSProperties; + visible?: boolean; + prefixCls?: string; + doneBtnText?: string; + prevBtnText?: string; + nextBtnText?: string; + skipBtnText?: string; +} + +const Guide = (props: GuideProps) => { + return ( + + {(Locale: LocaleProperties['Guide']) => { + const btnTextProps = { + prevBtnText: props.prevBtnText || Locale.prevBtnText, + nextBtnText: props.nextBtnText || Locale.nextBtnText, + doneBtnText: props.doneBtnText || Locale.doneBtnText, + skipBtnText: props.skipBtnText || Locale.skipBtnText, + }; + const childrenProps = { + ...props, + ...btnTextProps, + }; + const { mode } = props; + if (mode === 'fixed') { + return ; + } else { + return ; + } + }} + + ); +}; + +Guide.propTypes = { + prefixCls: PropTypes.string, + className: PropTypes.string, + style: PropTypes.object, + mode: PropTypes.string, + steps: PropTypes.array.isRequired, + visible: PropTypes.bool, + counter: PropTypes.bool, + mask: PropTypes.bool, + allowClose: PropTypes.bool, + keyboardControl: PropTypes.bool, + onClose: PropTypes.func, + doneBtnText: PropTypes.string, + prevBtnText: PropTypes.string, + nextBtnText: PropTypes.string, + skipBtnText: PropTypes.string, +}; + +Guide.defaultProps = { + prefixCls: 'fishd-guide', + mode: 'normal', + allowClose: false, + keyboardControl: false, + visible: false, + counter: true, + mask: true, + steps: [], +}; + +export default Guide; diff --git a/source/components/Guide/GuideFixed.tsx b/source/components/Guide/GuideFixed.tsx new file mode 100644 index 000000000..0640368d2 --- /dev/null +++ b/source/components/Guide/GuideFixed.tsx @@ -0,0 +1,152 @@ +import * as React from 'react'; +import classNames from 'classnames'; +import Modal from '../Modal'; +import Button from '../Button'; +import useUpdateEffect from '../../hooks/useUpdateEffect'; +import { GuideProps } from './Guide'; +import { ESC_KEY_CODE, LEFT_KEY_CODE, RIGHT_KEY_CODE } from './src/common/constants'; + +const GuideFixed = (props: GuideProps) => { + const totalCountRef = React.useRef(props.steps.length); + const totalCount = totalCountRef.current; + const [visible, setVisible] = React.useState(props.visible); + const [currentIndex, setCurrentIndex] = React.useState(0); + + const handleClose = () => { + Promise.resolve() + .then(() => { + setVisible(false); + }) + .then(() => { + setCurrentIndex(0); + }); + + props.onClose?.(); + }; + + const handleNext = () => { + if (currentIndex >= totalCount - 1) { + handleClose(); + } else { + const nextIndex = currentIndex + 1; + setCurrentIndex(nextIndex); + } + }; + + const handlePrev = () => { + let nextIndex; + + if (currentIndex <= 0) { + nextIndex = 0; + } else { + nextIndex = currentIndex - 1; + } + + setCurrentIndex(nextIndex); + }; + + const onKeyUp = event => { + if (!props.keyboardControl || !visible) { + return; + } + + if (event.keyCode === ESC_KEY_CODE) { + handleClose(); + return; + } + + if (event.keyCode === RIGHT_KEY_CODE) { + handleNext(); + } else if (event.keyCode === LEFT_KEY_CODE) { + handlePrev(); + } + }; + + React.useEffect(() => { + window.addEventListener('keyup', onKeyUp, false); + return () => { + window.removeEventListener('keyup', onKeyUp); + }; + }, [onKeyUp]); + + useUpdateEffect(() => { + if (!visible && props.visible) { + setVisible(true); + } + }, [props]); + + const renderTitle = curStep => { + if (!curStep.title) { + return null; + } + + if (curStep.subtitle) { + return ( + + {curStep.title} +
{curStep.subtitle}
+
+ ); + } else { + return curStep.title; + } + }; + + const { + prefixCls, + allowClose, + mask, + className, + style, + steps, + skipBtnText, + prevBtnText, + nextBtnText, + doneBtnText, + } = props; + const rootCls = classNames(`${prefixCls}-fixed`, { + [className]: className, + }); + const isFirstStep = currentIndex <= 0; + const isLastStep = currentIndex >= totalCount - 1; + + return ( + +
+ {skipBtnText} +
+ {isFirstStep ? null : ( + + )} + + + } + onCancel={handleClose} + > + {steps[currentIndex].content} +
+ ); +}; + +export default GuideFixed; diff --git a/source/components/Guide/GuideNormal.tsx b/source/components/Guide/GuideNormal.tsx new file mode 100644 index 000000000..e95663a55 --- /dev/null +++ b/source/components/Guide/GuideNormal.tsx @@ -0,0 +1,85 @@ +import * as React from 'react'; +import Driver from './src/index'; +import useUpdateEffect from '../../hooks/useUpdateEffect'; +import { GuideProps } from './Guide'; + +const GuideNormal = (props: GuideProps) => { + const [visible, setVisible] = React.useState(props.visible); + + const handleCloseRef = React.useRef<() => void>(); + handleCloseRef.current = () => { + setVisible(false); + + props.onClose?.(); + }; + + const driver: Driver = React.useMemo(() => { + let opt = { + counter: props.counter, + allowClose: props.allowClose, + keyboardControl: props.keyboardControl, + prevBtnText: props.prevBtnText, + nextBtnText: props.nextBtnText, + skipBtnText: props.skipBtnText, + doneBtnText: props.doneBtnText, + onReset: () => { + const handleClose = handleCloseRef.current; + handleClose?.(); + }, + }; + + if (!props.mask) { + opt['opacity'] = 0; + } + + return new Driver(opt); + }, []); + + const init = () => { + let { steps } = props; + + if (!(steps && steps.length)) { + return; + } + + setTimeout(() => { + if (steps.length == 1) { + driver.highlight(steps[0]); + } else { + driver.defineSteps(props.steps); + driver.start(); + } + }, 300); + }; + + React.useEffect(() => { + if (!visible) { + return; + } + + init(); + }, []); + + /* + 重构前,visible 字段没有被设计成受控属性 + 外部想要重新打开 Guide 组件,是通过重新 setState visible 为 true, + Guide 组件内部 componentWillReceiveProps 判断组件内部 visible 为 false + 且 nextProps.visible 为 true 时,进行重新初始化 + + 这里存在隐患,Guide 组件内部 visible 变为 false 时, + 因为 visible 不受控,外部 visible 还是 true, + 此时除 visible 外其他的 props 改变, + componentWillReceiveProps 内也会执行重新初始化的逻辑,弹出 Guide 组件 + 重构成 hooks 之后,暂时和重构前保持一致的逻辑 + */ + useUpdateEffect(() => { + if (!visible && props.visible) { + setVisible(true); + init(); + } + }, [props]); + + return null; +}; + +export default GuideNormal; diff --git a/source/components/Guide/__tests__/index.test.tsx b/source/components/Guide/__tests__/index.test.tsx new file mode 100644 index 000000000..589eb3247 --- /dev/null +++ b/source/components/Guide/__tests__/index.test.tsx @@ -0,0 +1,322 @@ +import React from 'react'; +import { mount } from 'enzyme'; +import Guide from '../index'; +import { ESC_KEY_CODE, LEFT_KEY_CODE, RIGHT_KEY_CODE } from '../src/common/constants'; +import { act } from 'react-dom/test-utils'; + +describe('Guide', () => { + describe('fixed mode', () => { + const steps = [ + { + title: '标题 1', + subtitle: '春眠不觉晓,处处闻啼鸟。夜来风雨声,花落知多少。', + content: ( + 图片 + ), + }, + { + title: '标题 2', + content: ( + 图片 + ), + }, + { + content: ( + 图片 + ), + }, + ]; + + it('should support onClose', () => { + const onClose = jest.fn(); + const wrapper = mount( + , + ); + const skipBtn = wrapper.find('.skip').at(0); + skipBtn.simulate('click'); + expect(onClose).toHaveBeenCalledTimes(1); + + wrapper.setProps({ visible: true }); + wrapper.update(); + + const nextBtn = wrapper.find('.fishd-guide-next-btn').at(0); + nextBtn.simulate('click'); + nextBtn.simulate('click'); + nextBtn.simulate('click'); + expect(onClose).toHaveBeenCalledTimes(2); + }); + + it('should support button text: doneBtnText, prevBtnText, nextBtnText, skipBtnText', () => { + const onClose = jest.fn(); + const btnTextConfig = { + skipBtnText: 'skip btn', + prevBtnText: 'prev btn', + nextBtnText: 'next btn', + doneBtnText: 'done btn', + }; + const wrapper = mount( + , + ); + const skipBtn = wrapper.find('.skip'); + const nextBtn = wrapper.find('.fishd-guide-next-btn').at(0); + nextBtn.simulate('click'); + wrapper.update(); + const prevBtn = wrapper.find('.fishd-guide-prev-btn').at(0); + expect(skipBtn.text()).toBe(btnTextConfig.skipBtnText); + expect(prevBtn.text()).toBe(btnTextConfig.prevBtnText); + expect(nextBtn.text()).toBe(`${btnTextConfig.nextBtnText} (2/3)`); + + nextBtn.simulate('click'); + wrapper.update(); + const doneBtn = wrapper.find('.fishd-guide-done-btn').at(0); + expect(doneBtn.text()).toBe(`${btnTextConfig.doneBtnText} (3/3)`); + }); + + it('should support keyboardControl', () => { + const onClose = jest.fn(); + const wrapper = mount( + , + ); + const rightEvent = new KeyboardEvent('keyup', { keyCode: RIGHT_KEY_CODE } as any); + const leftEvent = new KeyboardEvent('keyup', { keyCode: LEFT_KEY_CODE } as any); + const escEvent = new KeyboardEvent('keyup', { keyCode: ESC_KEY_CODE } as any); + const Global = global as any; + + expect(document.querySelector('.fishd-guide-fixed-subtitle').textContent).toBe( + steps[0].subtitle, + ); + Global.dispatchEvent(rightEvent); + expect(document.querySelector('.fishd-modal-title').textContent).toBe(steps[1].title); + Global.dispatchEvent(leftEvent); + expect(document.querySelector('.fishd-guide-fixed-subtitle').textContent).toBe( + steps[0].subtitle, + ); + + Global.dispatchEvent(rightEvent); + Global.dispatchEvent(rightEvent); + Global.dispatchEvent(rightEvent); + expect(onClose).toHaveBeenCalledTimes(1); + + wrapper.setProps({ visible: true }); + wrapper.update(); + Global.dispatchEvent(escEvent); + expect(onClose).toHaveBeenCalledTimes(2); + }); + }); + + describe('normal mode', () => { + const getBoundingClientRectMock = jest.spyOn(HTMLElement.prototype, 'getBoundingClientRect'); + let originStyle = Object.prototype['style']; + beforeAll(() => { + Object.prototype['style'] = {}; + getBoundingClientRectMock.mockImplementation(function (this: HTMLElement) { + return { + top: 100, + bottom: 0, + left: 100, + right: 200, + width: 100, + height: 100, + } as any; + }); + }); + + afterAll(() => { + Object.prototype['style'] = originStyle; + getBoundingClientRectMock.mockRestore(); + }); + + const Global = global as any; + const normalSteps = [ + { + element: '.guide-demo-step1', + popover: { + className: 'custom', + title: '第1步', + description: '第1步介绍', + position: 'bottomLeft', + }, + }, + { + counterPosition: 'leftBottom', + element: '.guide-demo-step2', + popover: { + title: '第2步', + description: '第2步介绍', + position: 'right', + }, + }, + ]; + const NormalDemo = props => { + const { guideProps } = props; + return ( +
+
+

第1步

+

第2步

+
+ +
+ ); + }; + it('should support onClose', () => { + jest.useFakeTimers(); + const onClose = jest.fn(); + const container = document.createElement('div'); + Global.document.body.appendChild(container); + const wrapper = mount(, { + attachTo: container, + }); + act(() => { + jest.runAllTimers(); + }); + act(() => { + const nextBtn = document.querySelector('.fishd-guide-driver-next-btn') as HTMLElement; + nextBtn.click(); + nextBtn.click(); + jest.runAllTimers(); + }); + expect(onClose).toHaveBeenCalledTimes(1); + + wrapper.setProps({ + guideProps: { + visible: true, + onClose, + }, + }); + act(() => { + jest.runAllTimers(); + const skipBtn = document.querySelector('.fishd-guide-driver-skip-btn') as HTMLElement; + skipBtn.click(); + }); + expect(onClose).toHaveBeenCalledTimes(2); + + const itemNode = document.querySelector('#fishd-guide-driver-popover-item'); + expect(itemNode.style.display).toBe('none'); + }); + + it('should support button text: doneBtnText, prevBtnText, nextBtnText, skipBtnText', () => { + jest.useFakeTimers(); + const container = document.createElement('div'); + Global.document.body.appendChild(container); + const onClose = jest.fn(); + const btnTextConfig = { + skipBtnText: 'skip btn', + prevBtnText: 'prev btn', + nextBtnText: 'next btn', + doneBtnText: 'done btn', + }; + const wrapper = mount( + , + { attachTo: container }, + ); + act(() => { + jest.runAllTimers(); + }); + const skipBtn = document.querySelector('.fishd-guide-driver-skip-btn') as HTMLElement; + const nextBtn = document.querySelector('.fishd-guide-driver-next-btn') as HTMLElement; + act(() => { + nextBtn.click(); + jest.runAllTimers(); + }); + const prevBtn = document.querySelector('.fishd-guide-driver-prev-btn') as HTMLElement; + expect(skipBtn.innerHTML).toBe(btnTextConfig.skipBtnText); + expect(prevBtn.innerHTML).toBe(btnTextConfig.prevBtnText); + expect(nextBtn.innerHTML).toBe(`${btnTextConfig.nextBtnText} (1/2)`); + + act(() => { + nextBtn.click(); + jest.runAllTimers(); + }); + const doneBtn = document.querySelector('.fishd-guide-driver-next-btn') as HTMLElement; + expect(doneBtn.innerHTML).toBe(`${btnTextConfig.doneBtnText} (2/2)`); + }); + + it('should support keyboardControl', () => { + jest.useFakeTimers(); + const container = document.createElement('div'); + Global.document.body.appendChild(container); + const onClose = jest.fn(); + const wrapper = mount( + , + { attachTo: container }, + ); + act(() => { + jest.runAllTimers(); + }); + const rightEvent = new KeyboardEvent('keyup', { keyCode: RIGHT_KEY_CODE } as any); + const leftEvent = new KeyboardEvent('keyup', { keyCode: LEFT_KEY_CODE } as any); + const escEvent = new KeyboardEvent('keyup', { keyCode: ESC_KEY_CODE } as any); + + expect(document.querySelector('.fishd-guide-driver-popover-title').innerHTML).toBe( + normalSteps[0].popover.title, + ); + act(() => { + Global.dispatchEvent(rightEvent); + jest.runAllTimers(); + }); + expect(document.querySelector('.fishd-guide-driver-popover-title').innerHTML).toBe( + normalSteps[1].popover.title, + ); + act(() => { + Global.dispatchEvent(leftEvent); + jest.runAllTimers(); + }); + expect(document.querySelector('.fishd-guide-driver-popover-title').innerHTML).toBe( + normalSteps[0].popover.title, + ); + + act(() => { + Global.dispatchEvent(rightEvent); + Global.dispatchEvent(rightEvent); + jest.runAllTimers(); + }); + expect(onClose).toHaveBeenCalledTimes(1); + + wrapper.setProps({ + visible: true, + onClose, + keyboardControl: true, + }); + act(() => { + wrapper.update(); + jest.runAllTimers(); + }); + act(() => { + Global.dispatchEvent(escEvent); + jest.runAllTimers(); + }); + expect(onClose).toHaveBeenCalledTimes(2); + }); + }); +}); diff --git a/source/components/Guide/index.tsx b/source/components/Guide/index.tsx index bbcbd30fc..6efa5ed3a 100644 --- a/source/components/Guide/index.tsx +++ b/source/components/Guide/index.tsx @@ -1,278 +1,6 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import classNames from 'classnames'; -import Driver from './src'; -import { ESC_KEY_CODE, LEFT_KEY_CODE, RIGHT_KEY_CODE } from './src/common/constants'; -import Modal from '../Modal'; -import Button from '../Button'; +import Guide from './Guide'; import './style/index.less'; -import ConfigConsumer from '../Config/Consumer'; -import { LocaleProperties } from '../Locale'; -interface GuideProps { - allowClose?: boolean; - className?: string; - counter?: boolean; - keyboardControl?: boolean; - mask?: boolean; - mode?: string; - onClose?: () => void; - steps?: any[]; - style?: React.CSSProperties; - visible?: boolean; - prefixCls?: string; -} - -interface GuideState { - visible: boolean; - currentIndex: number; -} - -class Guide extends Component { - static propTypes = { - prefixCls: PropTypes.string, - className: PropTypes.string, - style: PropTypes.object, - mode: PropTypes.string, - steps: PropTypes.array.isRequired, - visible: PropTypes.bool, - counter: PropTypes.bool, - mask: PropTypes.bool, - allowClose: PropTypes.bool, - keyboardControl: PropTypes.bool, - onClose: PropTypes.func - }; - - static defaultProps = { - prefixCls: 'fishd-guide', - mode: 'normal', - allowClose: false, - keyboardControl: false, - visible: false, - counter: true, - mask: true, - steps: [] - }; - - totalCount: number = 0; - driver: Driver = null; - - constructor(props: GuideProps) { - super(props); - - this.state = { - visible: props.visible, - currentIndex: 0 - }; - - this.totalCount = props.steps.length; - - if (props.mode != 'fixed') { - let opt = { - counter: props.counter, - allowClose: props.allowClose, - keyboardControl: props.keyboardControl, - onReset: () => { - this.handleClose(); - } - }; - - if (!props.mask) { - opt['opacity'] = 0; - } - - this.driver = new Driver(opt); - } else { - if (props.keyboardControl) { - window.addEventListener('keyup', this.onKeyUp.bind(this), false); - } - } - } - - componentDidMount() { - let { visible } = this.state; - - if (!visible) return; - - this.init(); - } - - // eslint-disable-next-line react/no-deprecated - componentWillReceiveProps(nextProps) { - let { visible } = this.state; - - if (!visible && nextProps.visible) { - this.setState( - { - visible: true - }, - () => { - this.init(); - } - ); - } - } - - init = () => { - let { steps, mode } = this.props; - - if (!(steps && steps.length) || mode == 'fixed') return; - - setTimeout(() => { - if (steps.length == 1) { - this.driver.highlight(steps[0]); - } else { - this.driver.defineSteps(this.props.steps); - this.driver.start(); - } - }, 300); - }; - - onKeyUp(event) { - if (!this.props.keyboardControl || this.props.mode != 'fixed') return; - - if (event.keyCode === ESC_KEY_CODE) { - this.handleClose(); - return; - } - - if (event.keyCode === RIGHT_KEY_CODE) { - this.handleNext(); - } else if (event.keyCode === LEFT_KEY_CODE) { - this.handlePrev(); - } - } - - handleClose = () => { - this.setState( - { - visible: false - }, - () => { - this.setState({ - currentIndex: 0 - }); - } - ); - - this.props.onClose && this.props.onClose(); - }; - - handleNext = () => { - let { currentIndex } = this.state, - nextIndex = 0; - - if (currentIndex >= this.totalCount - 1) { - nextIndex = this.totalCount - 1; - this.handleClose(); - } else { - nextIndex = currentIndex + 1; - } - - this.setState({ - currentIndex: nextIndex - }); - }; - - handlePrev = () => { - let { currentIndex } = this.state, - nextIndex = 0; - - if (currentIndex <= 0) { - nextIndex = 0; - } else { - nextIndex = currentIndex - 1; - } - - this.setState({ - currentIndex: nextIndex - }); - }; - - renderTitle = curStep => { - if (!curStep.title) return null; - - if (curStep.subtitle) { - return ( - - {curStep.title} -
{curStep.subtitle}
-
- ); - } else { - return curStep.title; - } - }; - - render() { - let { - prefixCls, - allowClose, - mode, - mask, - className, - style, - steps, - } = this.props, - { visible, currentIndex } = this.state, - rootCls = classNames(`${prefixCls}-fixed`, { - [className]: className - }), - isFirstStep = currentIndex <= 0, - isLastStep = currentIndex >= this.totalCount - 1; - - if (mode != 'fixed') { - return null; - } - - return ( - - { - (Locale: LocaleProperties['Guide']) => { - const { - prevBtnText = '上一步', - nextBtnText = '下一步', - doneBtnText = '知道了', - skipBtnText = '跳过', - } = Locale; - - return ( - -
- {skipBtnText} -
- {isFirstStep ? null : ( - - )} - - - } - onCancel={this.handleClose} - > - {steps[currentIndex].content} -
- ) - } - } -
- ); - } -} +export { GuideProps } from './Guide'; export default Guide; diff --git a/source/components/Guide/src/core/popover.js b/source/components/Guide/src/core/popover.js index 95cd39581..59182dc99 100644 --- a/source/components/Guide/src/core/popover.js +++ b/source/components/Guide/src/core/popover.js @@ -24,7 +24,7 @@ export default class Popover extends Element { * @param {Document} document */ constructor(options, window, document) { - super(); + super(options); this.options = { isFirst: true, diff --git a/source/components/Guide/src/core/stage.js b/source/components/Guide/src/core/stage.js index cedad11fd..10c7028d2 100644 --- a/source/components/Guide/src/core/stage.js +++ b/source/components/Guide/src/core/stage.js @@ -13,7 +13,7 @@ export default class Stage extends Element { * @param {Document} document */ constructor(options, window, document) { - super(); + super(options); this.options = options; this.window = window;