diff --git a/example/.dumirc.ts b/example/.dumirc.ts
index 79ec100..fa4881c 100644
--- a/example/.dumirc.ts
+++ b/example/.dumirc.ts
@@ -67,7 +67,6 @@ export default defineConfig({
'dumi-theme-antd-style': path.join(__dirname, '../src'),
},
mfsu: false,
- extraBabelPlugins: ['@emotion'],
styles: [
`html, body { background: transparent; }
diff --git a/package.json b/package.json
index eff6cfe..0cd86bc 100644
--- a/package.json
+++ b/package.json
@@ -73,7 +73,6 @@
"polished": "^4",
"rc-footer": "^0.6",
"react-layout-kit": "^1",
- "react-lazy-load": "^4.0.1",
"react-syntax-highlighter": "^15",
"shiki-es": "^0.2",
"use-merge-value": "^1",
diff --git a/src/builtins/Previewer/index.tsx b/src/builtins/Previewer/index.tsx
index 57e0e5e..784ac29 100644
--- a/src/builtins/Previewer/index.tsx
+++ b/src/builtins/Previewer/index.tsx
@@ -1,11 +1,10 @@
-import { Card } from 'antd';
import { createStyles } from 'antd-style';
import { IPreviewerProps } from 'dumi/dist/client/theme-api/types';
import Previewer from 'dumi/theme-default/builtins/Previewer';
import { rgba } from 'polished';
-import { useMemo, useState } from 'react';
-import LazyLoad from 'react-lazy-load';
+import { useMemo } from 'react';
import DemoProvider from '../../components/DemoProvider';
+import { IntersectionLoad } from '../../components/LazyLoad';
const useStyles = createStyles(({ css, token, prefixCls }) => {
return {
@@ -124,8 +123,6 @@ const useStyles = createStyles(({ css, token, prefixCls }) => {
export default (props: IPreviewerProps) => {
const { styles, cx, theme } = useStyles();
- const [loading, setLoading] = useState(true);
-
const height = useMemo(() => {
if (typeof props.iframe === 'number') {
return props.iframe;
@@ -138,26 +135,11 @@ export default (props: IPreviewerProps) => {
return (
-
{
- setLoading(false);
- }}
- >
+
-
- {loading && (
-
- )}
+
);
};
diff --git a/src/components/LazyLoad/index.tsx b/src/components/LazyLoad/index.tsx
new file mode 100644
index 0000000..adcc944
--- /dev/null
+++ b/src/components/LazyLoad/index.tsx
@@ -0,0 +1,137 @@
+// copy form https://github.com/loktar00/react-lazy-load/blob/master/src/LazyLoad.tsx#L2
+import { Card } from 'antd';
+import React, { Children, Component, createElement, ReactNode, RefObject } from 'react';
+import scrollParent from './utils';
+
+type Props = {
+ children: ReactNode;
+ className?: string;
+ elementType?: string;
+ height?: string | number;
+ offset?: string | number;
+ threshold?: number;
+ width?: number | string;
+ onContentVisible?: () => void;
+};
+
+type State = {
+ visible: boolean;
+};
+
+export class IntersectionLoad extends Component {
+ static defaultProps = {
+ elementType: 'div',
+ className: '',
+ offset: 0,
+ threshold: 0,
+ width: null,
+ onContentVisible: null,
+ height: null,
+ };
+
+ elementObserver: IntersectionObserver | null;
+
+ wrapper: RefObject | null;
+
+ constructor(props: Props) {
+ super(props);
+ this.elementObserver = null;
+ this.wrapper = React.createRef();
+
+ this.state = { visible: false };
+ }
+
+ componentDidMount() {
+ let eventNode = this.getEventNode();
+
+ if (eventNode === window) {
+ eventNode = document.body;
+ }
+
+ setTimeout(() => {
+ const { offset, threshold } = this.props;
+ const options = {
+ rootMargin: typeof offset === 'number' ? `${offset}px` : offset || '0px',
+ threshold: threshold || 0,
+
+ root: document.body,
+ };
+
+ this.elementObserver = new IntersectionObserver(this.lazyLoadHandler, options);
+
+ const node = this.wrapper?.current;
+
+ if (node instanceof HTMLElement) {
+ this.elementObserver.observe(node);
+ }
+ }, 200);
+ }
+
+ shouldComponentUpdate(_: Props, nextState: State) {
+ return nextState.visible;
+ }
+
+ componentWillUnmount() {
+ const node = this.wrapper?.current;
+ console.log(node);
+ if (node && node instanceof HTMLElement) {
+ this.elementObserver?.unobserve(node);
+ }
+ }
+
+ getEventNode() {
+ if (!this.wrapper?.current) return document.body;
+ return scrollParent(this.wrapper?.current);
+ }
+
+ lazyLoadHandler = (entries: IntersectionObserverEntry[]) => {
+ const { onContentVisible } = this.props;
+ const [entry] = entries;
+ const { isIntersecting } = entry;
+
+ if (isIntersecting) {
+ this.setState({ visible: true }, () => {
+ if (onContentVisible) {
+ onContentVisible();
+ }
+ });
+
+ // Stop observing
+ const node = this.wrapper?.current;
+ if (node && node instanceof HTMLElement) {
+ this.elementObserver?.unobserve(node);
+ }
+ }
+ };
+
+ render() {
+ const { children, className, height, width, elementType } = this.props;
+ const { visible } = this.state;
+
+ const elStyles = { width };
+ const elClasses = `LazyLoad${visible ? ' is-visible' : ''}${className ? ` ${className}` : ''}`;
+
+ const componentElementType = elementType || 'div';
+
+ return createElement(
+ componentElementType,
+ {
+ className: elClasses,
+ style: elStyles,
+ ref: this.wrapper,
+ },
+ visible ? (
+ Children.only(children)
+ ) : (
+
+ ),
+ );
+ }
+}
diff --git a/src/components/LazyLoad/utils.ts b/src/components/LazyLoad/utils.ts
new file mode 100644
index 0000000..8ea300c
--- /dev/null
+++ b/src/components/LazyLoad/utils.ts
@@ -0,0 +1,33 @@
+const style = (element: HTMLElement, prop: string) =>
+ typeof getComputedStyle !== 'undefined'
+ ? getComputedStyle(element, null).getPropertyValue(prop)
+ : element.style.getPropertyValue(prop);
+
+const overflow = (element: HTMLElement) =>
+ style(element, 'overflow') + style(element, 'overflow-y') + style(element, 'overflow-x');
+
+export default (element: HTMLElement) => {
+ if (!(element instanceof HTMLElement)) {
+ return window;
+ }
+
+ let parent = element;
+
+ while (parent) {
+ if (parent === document.body || parent === document.documentElement) {
+ break;
+ }
+
+ if (!parent.parentNode) {
+ break;
+ }
+
+ if (/(scroll|auto)/.test(overflow(parent))) {
+ return parent;
+ }
+
+ parent = parent.parentNode as HTMLDivElement;
+ }
+
+ return window;
+};