react-intersection-observer
Version:
Monitor if a component is inside the viewport, using IntersectionObserver API
1 lines • 28 kB
Source Map (JSON)
{"version":3,"sources":["../src/InView.tsx","../src/observe.ts","../src/useInView.tsx","../src/useOnInView.tsx"],"sourcesContent":["import * as React from \"react\";\nimport type { IntersectionObserverProps, PlainChildrenProps } from \"./index\";\nimport { observe } from \"./observe\";\n\ntype State = {\n inView: boolean;\n entry?: IntersectionObserverEntry;\n};\n\nfunction isPlainChildren(\n props: IntersectionObserverProps | PlainChildrenProps,\n): props is PlainChildrenProps {\n return typeof props.children !== \"function\";\n}\n\n/**\n ## Render props\n\n To use the `<InView>` component, you pass it a function. It will be called\n whenever the state changes, with the new value of `inView`. In addition to the\n `inView` prop, children also receive a `ref` that should be set on the\n containing DOM element. This is the element that the IntersectionObserver will\n monitor.\n\n If you need it, you can also access the\n [`IntersectionObserverEntry`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry)\n on `entry`, giving you access to all the details about the current intersection\n state.\n\n ```jsx\n import { InView } from 'react-intersection-observer';\n\n const Component = () => (\n <InView>\n {({ inView, ref, entry }) => (\n <div ref={ref}>\n <h2>{`Header inside viewport ${inView}.`}</h2>\n </div>\n )}\n </InView>\n );\n\n export default Component;\n ```\n\n ## Plain children\n\n You can pass any element to the `<InView />`, and it will handle creating the\n wrapping DOM element. Add a handler to the `onChange` method, and control the\n state in your own component. Any extra props you add to `<InView>` will be\n passed to the HTML element, allowing you set the `className`, `style`, etc.\n\n ```jsx\n import { InView } from 'react-intersection-observer';\n\n const Component = () => (\n <InView as=\"div\" onChange={(inView, entry) => console.log('Inview:', inView)}>\n <h2>Plain children are always rendered. Use onChange to monitor state.</h2>\n </InView>\n );\n\n export default Component;\n ```\n */\nexport class InView extends React.Component<\n IntersectionObserverProps | PlainChildrenProps,\n State\n> {\n node: Element | null = null;\n _unobserveCb: (() => void) | null = null;\n lastInView: boolean | undefined;\n\n constructor(props: IntersectionObserverProps | PlainChildrenProps) {\n super(props);\n this.state = {\n inView: !!props.initialInView,\n entry: undefined,\n };\n this.lastInView = props.initialInView;\n }\n\n componentDidMount() {\n this.unobserve();\n this.observeNode();\n }\n\n componentDidUpdate(prevProps: IntersectionObserverProps) {\n // If a IntersectionObserver option changed, reinit the observer\n if (\n prevProps.rootMargin !== this.props.rootMargin ||\n prevProps.root !== this.props.root ||\n prevProps.threshold !== this.props.threshold ||\n prevProps.skip !== this.props.skip ||\n prevProps.trackVisibility !== this.props.trackVisibility ||\n prevProps.delay !== this.props.delay\n ) {\n this.unobserve();\n this.observeNode();\n }\n }\n\n componentWillUnmount() {\n this.unobserve();\n }\n\n observeNode() {\n if (!this.node || this.props.skip) return;\n const {\n threshold,\n root,\n rootMargin,\n trackVisibility,\n delay,\n fallbackInView,\n } = this.props;\n\n if (this.lastInView === undefined) {\n this.lastInView = this.props.initialInView;\n }\n this._unobserveCb = observe(\n this.node,\n this.handleChange,\n {\n threshold,\n root,\n rootMargin,\n // @ts-expect-error\n trackVisibility,\n delay,\n },\n fallbackInView,\n );\n }\n\n unobserve() {\n if (this._unobserveCb) {\n this._unobserveCb();\n this._unobserveCb = null;\n }\n }\n\n handleNode = (node?: Element | null) => {\n if (this.node) {\n // Clear the old observer, before we start observing a new element\n this.unobserve();\n\n if (!node && !this.props.triggerOnce && !this.props.skip) {\n // Reset the state if we get a new node, and we aren't ignoring updates\n this.setState({ inView: !!this.props.initialInView, entry: undefined });\n this.lastInView = this.props.initialInView;\n }\n }\n\n this.node = node ? node : null;\n this.observeNode();\n };\n\n handleChange = (inView: boolean, entry: IntersectionObserverEntry) => {\n const previousInView = this.lastInView;\n this.lastInView = inView;\n\n // Ignore the very first `false` notification so consumers only hear about actual state changes.\n if (previousInView === undefined && !inView) {\n return;\n }\n\n if (inView && this.props.triggerOnce) {\n // If `triggerOnce` is true, we should stop observing the element.\n this.unobserve();\n }\n if (!isPlainChildren(this.props)) {\n // Store the current State, so we can pass it to the children in the next render update\n // There's no reason to update the state for plain children, since it's not used in the rendering.\n this.setState({ inView, entry });\n }\n if (this.props.onChange) {\n // If the user is actively listening for onChange, always trigger it\n this.props.onChange(inView, entry);\n }\n };\n\n render() {\n const { children } = this.props;\n if (typeof children === \"function\") {\n const { inView, entry } = this.state;\n return children({ inView, entry, ref: this.handleNode });\n }\n\n const {\n as,\n triggerOnce,\n threshold,\n root,\n rootMargin,\n onChange,\n skip,\n trackVisibility,\n delay,\n initialInView,\n fallbackInView,\n ...props\n } = this.props as PlainChildrenProps;\n\n return React.createElement(\n as || \"div\",\n { ref: this.handleNode, ...props },\n children,\n );\n }\n}\n","import type { ObserverInstanceCallback } from \"./index\";\n\nconst observerMap = new Map<\n string,\n {\n id: string;\n observer: IntersectionObserver;\n elements: Map<Element, Array<ObserverInstanceCallback>>;\n }\n>();\n\nconst RootIds: WeakMap<Element | Document, string> = new WeakMap();\nlet rootId = 0;\n\nlet unsupportedValue: boolean | undefined;\n\n/**\n * What should be the default behavior if the IntersectionObserver is unsupported?\n * Ideally the polyfill has been loaded, you can have the following happen:\n * - `undefined`: Throw an error\n * - `true` or `false`: Set the `inView` value to this regardless of intersection state\n * **/\nexport function defaultFallbackInView(inView: boolean | undefined) {\n unsupportedValue = inView;\n}\n\n/**\n * Generate a unique ID for the root element\n * @param root\n */\nfunction getRootId(root: IntersectionObserverInit[\"root\"]) {\n if (!root) return \"0\";\n if (RootIds.has(root)) return RootIds.get(root);\n rootId += 1;\n RootIds.set(root, rootId.toString());\n return RootIds.get(root);\n}\n\n/**\n * Convert the options to a string Id, based on the values.\n * Ensures we can reuse the same observer when observing elements with the same options.\n * @param options\n */\nexport function optionsToId(options: IntersectionObserverInit) {\n return Object.keys(options)\n .sort()\n .filter(\n (key) => options[key as keyof IntersectionObserverInit] !== undefined,\n )\n .map((key) => {\n return `${key}_${\n key === \"root\"\n ? getRootId(options.root)\n : options[key as keyof IntersectionObserverInit]\n }`;\n })\n .toString();\n}\n\nfunction createObserver(options: IntersectionObserverInit) {\n // Create a unique ID for this observer instance, based on the root, root margin and threshold.\n const id = optionsToId(options);\n let instance = observerMap.get(id);\n\n if (!instance) {\n // Create a map of elements this observer is going to observe. Each element has a list of callbacks that should be triggered, once it comes into view.\n const elements = new Map<Element, Array<ObserverInstanceCallback>>();\n let thresholds: number[] | readonly number[];\n\n const observer = new IntersectionObserver((entries) => {\n entries.forEach((entry) => {\n // While it would be nice if you could just look at isIntersecting to determine if the component is inside the viewport, browsers can't agree on how to use it.\n // -Firefox ignores `threshold` when considering `isIntersecting`, so it will never be false again if `threshold` is > 0\n const inView =\n entry.isIntersecting &&\n thresholds.some((threshold) => entry.intersectionRatio >= threshold);\n\n // @ts-expect-error support IntersectionObserver v2\n if (options.trackVisibility && typeof entry.isVisible === \"undefined\") {\n // The browser doesn't support Intersection Observer v2, falling back to v1 behavior.\n // @ts-expect-error\n entry.isVisible = inView;\n }\n\n elements.get(entry.target)?.forEach((callback) => {\n callback(inView, entry);\n });\n });\n }, options);\n\n // Ensure we have a valid thresholds array. If not, use the threshold from the options\n thresholds =\n observer.thresholds ||\n (Array.isArray(options.threshold)\n ? options.threshold\n : [options.threshold || 0]);\n\n instance = {\n id,\n observer,\n elements,\n };\n\n observerMap.set(id, instance);\n }\n\n return instance;\n}\n\n/**\n * @param element - DOM Element to observe\n * @param callback - Callback function to trigger when intersection status changes\n * @param options - Intersection Observer options\n * @param fallbackInView - Fallback inView value.\n * @return Function - Cleanup function that should be triggered to unregister the observer\n */\nexport function observe(\n element: Element,\n callback: ObserverInstanceCallback,\n options: IntersectionObserverInit = {},\n fallbackInView = unsupportedValue,\n) {\n if (\n typeof window.IntersectionObserver === \"undefined\" &&\n fallbackInView !== undefined\n ) {\n const bounds = element.getBoundingClientRect();\n callback(fallbackInView, {\n isIntersecting: fallbackInView,\n target: element,\n intersectionRatio:\n typeof options.threshold === \"number\" ? options.threshold : 0,\n time: 0,\n boundingClientRect: bounds,\n intersectionRect: bounds,\n rootBounds: bounds,\n });\n return () => {\n // Nothing to cleanup\n };\n }\n // An observer with the same options can be reused, so lets use this fact\n const { id, observer, elements } = createObserver(options);\n\n // Register the callback listener for this element\n const callbacks = elements.get(element) || [];\n if (!elements.has(element)) {\n elements.set(element, callbacks);\n }\n\n callbacks.push(callback);\n observer.observe(element);\n\n return function unobserve() {\n // Remove the callback from the callback list\n callbacks.splice(callbacks.indexOf(callback), 1);\n\n if (callbacks.length === 0) {\n // No more callback exists for element, so destroy it\n elements.delete(element);\n observer.unobserve(element);\n }\n\n if (elements.size === 0) {\n // No more elements are being observer by this instance, so destroy it\n observer.disconnect();\n observerMap.delete(id);\n }\n };\n}\n","import * as React from \"react\";\nimport type { IntersectionOptions, InViewHookResponse } from \"./index\";\nimport { observe } from \"./observe\";\n\ntype State = {\n inView: boolean;\n entry?: IntersectionObserverEntry;\n};\n\n/**\n * React Hooks make it easy to monitor the `inView` state of your components. Call\n * the `useInView` hook with the (optional) [options](#options) you need. It will\n * return an array containing a `ref`, the `inView` status and the current\n * [`entry`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry).\n * Assign the `ref` to the DOM element you want to monitor, and the hook will\n * report the status.\n *\n * @example\n * ```jsx\n * import React from 'react';\n * import { useInView } from 'react-intersection-observer';\n *\n * const Component = () => {\n * const { ref, inView, entry } = useInView({\n * threshold: 0,\n * });\n *\n * return (\n * <div ref={ref}>\n * <h2>{`Header inside viewport ${inView}.`}</h2>\n * </div>\n * );\n * };\n * ```\n */\nexport function useInView({\n threshold,\n delay,\n trackVisibility,\n rootMargin,\n root,\n triggerOnce,\n skip,\n initialInView,\n fallbackInView,\n onChange,\n}: IntersectionOptions = {}): InViewHookResponse {\n const [ref, setRef] = React.useState<Element | null>(null);\n const callback = React.useRef<IntersectionOptions[\"onChange\"]>(onChange);\n const lastInViewRef = React.useRef<boolean | undefined>(initialInView);\n const [state, setState] = React.useState<State>({\n inView: !!initialInView,\n entry: undefined,\n });\n\n // Store the onChange callback in a `ref`, so we can access the latest instance\n // inside the `useEffect`, but without triggering a rerender.\n callback.current = onChange;\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: threshold is not correctly detected as a dependency\n React.useEffect(\n () => {\n if (lastInViewRef.current === undefined) {\n lastInViewRef.current = initialInView;\n }\n // Ensure we have node ref, and that we shouldn't skip observing\n if (skip || !ref) return;\n\n let unobserve: (() => void) | undefined;\n unobserve = observe(\n ref,\n (inView, entry) => {\n const previousInView = lastInViewRef.current;\n lastInViewRef.current = inView;\n\n // Ignore the very first `false` notification so consumers only hear about actual state changes.\n if (previousInView === undefined && !inView) {\n return;\n }\n\n setState({\n inView,\n entry,\n });\n if (callback.current) callback.current(inView, entry);\n\n if (entry.isIntersecting && triggerOnce && unobserve) {\n // If it should only trigger once, unobserve the element after it's inView\n unobserve();\n unobserve = undefined;\n }\n },\n {\n root,\n rootMargin,\n threshold,\n // @ts-expect-error\n trackVisibility,\n delay,\n },\n fallbackInView,\n );\n\n return () => {\n if (unobserve) {\n unobserve();\n }\n };\n },\n // We break the rule here, because we aren't including the actual `threshold` variable\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n // If the threshold is an array, convert it to a string, so it won't change between renders.\n Array.isArray(threshold) ? threshold.toString() : threshold,\n ref,\n root,\n rootMargin,\n triggerOnce,\n skip,\n trackVisibility,\n fallbackInView,\n delay,\n ],\n );\n\n const entryTarget = state.entry?.target;\n const previousEntryTarget = React.useRef<Element | undefined>(undefined);\n if (\n !ref &&\n entryTarget &&\n !triggerOnce &&\n !skip &&\n previousEntryTarget.current !== entryTarget\n ) {\n // If we don't have a node ref, then reset the state (unless the hook is set to only `triggerOnce` or `skip`)\n // This ensures we correctly reflect the current state - If you aren't observing anything, then nothing is inView\n previousEntryTarget.current = entryTarget;\n setState({\n inView: !!initialInView,\n entry: undefined,\n });\n lastInViewRef.current = initialInView;\n }\n\n const result = [setRef, state.inView, state.entry] as InViewHookResponse;\n\n // Support object destructuring, by adding the specific values.\n result.ref = result[0];\n result.inView = result[1];\n result.entry = result[2];\n\n return result;\n}\n","import * as React from \"react\";\nimport type {\n IntersectionChangeEffect,\n IntersectionEffectOptions,\n} from \"./index\";\nimport { observe } from \"./observe\";\n\nconst useSyncEffect = ((\"useInsertionEffect\" in React\n ? (React as typeof React & { useInsertionEffect: typeof React.useEffect })\n .useInsertionEffect\n : undefined) ??\n React.useLayoutEffect ??\n React.useEffect) as typeof React.useEffect;\n\n/**\n * React Hooks make it easy to monitor when elements come into and leave view. Call\n * the `useOnInView` hook with your callback and (optional) [options](#options).\n * It will return a ref callback that you can assign to the DOM element you want to monitor.\n * When the element enters or leaves the viewport, your callback will be triggered.\n *\n * This hook triggers no re-renders, and is useful for performance-critical use-cases or\n * when you need to trigger render independent side effects like tracking or logging.\n *\n * @example\n * ```jsx\n * import React from 'react';\n * import { useOnInView } from 'react-intersection-observer';\n *\n * const Component = () => {\n * const inViewRef = useOnInView((inView, entry) => {\n * if (inView) {\n * console.log(\"Element is in view\", entry.target);\n * } else {\n * console.log(\"Element left view\", entry.target);\n * }\n * });\n *\n * return (\n * <div ref={inViewRef}>\n * <h2>This element is being monitored</h2>\n * </div>\n * );\n * };\n * ```\n */\nexport const useOnInView = <TElement extends Element>(\n onIntersectionChange: IntersectionChangeEffect<TElement>,\n {\n threshold,\n root,\n rootMargin,\n trackVisibility,\n delay,\n triggerOnce,\n skip,\n }: IntersectionEffectOptions = {},\n) => {\n const onIntersectionChangeRef = React.useRef(onIntersectionChange);\n const observedElementRef = React.useRef<TElement | null>(null);\n const observerCleanupRef = React.useRef<(() => void) | undefined>(undefined);\n const lastInViewRef = React.useRef<boolean | undefined>(undefined);\n\n useSyncEffect(() => {\n onIntersectionChangeRef.current = onIntersectionChange;\n }, [onIntersectionChange]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: Threshold arrays are normalized inside the callback\n return React.useCallback(\n (element: TElement | undefined | null) => {\n // React <19 never calls ref callbacks with `null` during unmount, so we\n // eagerly tear down existing observers manually whenever the target changes.\n const cleanupExisting = () => {\n if (observerCleanupRef.current) {\n const cleanup = observerCleanupRef.current;\n observerCleanupRef.current = undefined;\n cleanup();\n }\n };\n\n if (element === observedElementRef.current) {\n return observerCleanupRef.current;\n }\n\n if (!element || skip) {\n cleanupExisting();\n observedElementRef.current = null;\n lastInViewRef.current = undefined;\n return;\n }\n\n cleanupExisting();\n\n observedElementRef.current = element;\n let destroyed = false;\n\n const destroyObserver = observe(\n element,\n (inView, entry) => {\n const previousInView = lastInViewRef.current;\n lastInViewRef.current = inView;\n\n // Ignore the very first `false` notification so consumers only hear about actual state changes.\n if (previousInView === undefined && !inView) {\n return;\n }\n\n onIntersectionChangeRef.current(\n inView,\n entry as IntersectionObserverEntry & { target: TElement },\n );\n if (triggerOnce && inView) {\n stopObserving();\n }\n },\n {\n threshold,\n root,\n rootMargin,\n trackVisibility,\n delay,\n } as IntersectionObserverInit,\n );\n\n function stopObserving() {\n // Centralized teardown so both manual destroys and React ref updates share\n // the same cleanup path (needed for React versions that never call the ref with `null`).\n if (destroyed) return;\n destroyed = true;\n destroyObserver();\n observedElementRef.current = null;\n observerCleanupRef.current = undefined;\n lastInViewRef.current = undefined;\n }\n\n observerCleanupRef.current = stopObserving;\n\n return observerCleanupRef.current;\n },\n [\n Array.isArray(threshold) ? threshold.toString() : threshold,\n root,\n rootMargin,\n trackVisibility,\n delay,\n triggerOnce,\n skip,\n ],\n );\n};\n"],"mappings":";;;;;;AAAA,YAAY,WAAW;;;ACEvB,IAAM,cAAc,oBAAI,IAOtB;AAEF,IAAM,UAA+C,oBAAI,QAAQ;AACjE,IAAI,SAAS;AAEb,IAAI;AAQG,SAAS,sBAAsB,QAA6B;AACjE,qBAAmB;AACrB;AAMA,SAAS,UAAU,MAAwC;AACzD,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,QAAQ,IAAI,IAAI,EAAG,QAAO,QAAQ,IAAI,IAAI;AAC9C,YAAU;AACV,UAAQ,IAAI,MAAM,OAAO,SAAS,CAAC;AACnC,SAAO,QAAQ,IAAI,IAAI;AACzB;AAOO,SAAS,YAAY,SAAmC;AAC7D,SAAO,OAAO,KAAK,OAAO,EACvB,KAAK,EACL;AAAA,IACC,CAAC,QAAQ,QAAQ,GAAqC,MAAM;AAAA,EAC9D,EACC,IAAI,CAAC,QAAQ;AACZ,WAAO,GAAG,GAAG,IACX,QAAQ,SACJ,UAAU,QAAQ,IAAI,IACtB,QAAQ,GAAqC,CACnD;AAAA,EACF,CAAC,EACA,SAAS;AACd;AAEA,SAAS,eAAe,SAAmC;AAEzD,QAAM,KAAK,YAAY,OAAO;AAC9B,MAAI,WAAW,YAAY,IAAI,EAAE;AAEjC,MAAI,CAAC,UAAU;AAEb,UAAM,WAAW,oBAAI,IAA8C;AACnE,QAAI;AAEJ,UAAM,WAAW,IAAI,qBAAqB,CAAC,YAAY;AACrD,cAAQ,QAAQ,CAAC,UAAU;AAtEjC,YAAAA;AAyEQ,cAAM,SACJ,MAAM,kBACN,WAAW,KAAK,CAAC,cAAc,MAAM,qBAAqB,SAAS;AAGrE,YAAI,QAAQ,mBAAmB,OAAO,MAAM,cAAc,aAAa;AAGrE,gBAAM,YAAY;AAAA,QACpB;AAEA,SAAAA,MAAA,SAAS,IAAI,MAAM,MAAM,MAAzB,gBAAAA,IAA4B,QAAQ,CAAC,aAAa;AAChD,mBAAS,QAAQ,KAAK;AAAA,QACxB;AAAA,MACF,CAAC;AAAA,IACH,GAAG,OAAO;AAGV,iBACE,SAAS,eACR,MAAM,QAAQ,QAAQ,SAAS,IAC5B,QAAQ,YACR,CAAC,QAAQ,aAAa,CAAC;AAE7B,eAAW;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,gBAAY,IAAI,IAAI,QAAQ;AAAA,EAC9B;AAEA,SAAO;AACT;AASO,SAAS,QACd,SACA,UACA,UAAoC,CAAC,GACrC,iBAAiB,kBACjB;AACA,MACE,OAAO,OAAO,yBAAyB,eACvC,mBAAmB,QACnB;AACA,UAAM,SAAS,QAAQ,sBAAsB;AAC7C,aAAS,gBAAgB;AAAA,MACvB,gBAAgB;AAAA,MAChB,QAAQ;AAAA,MACR,mBACE,OAAO,QAAQ,cAAc,WAAW,QAAQ,YAAY;AAAA,MAC9D,MAAM;AAAA,MACN,oBAAoB;AAAA,MACpB,kBAAkB;AAAA,MAClB,YAAY;AAAA,IACd,CAAC;AACD,WAAO,MAAM;AAAA,IAEb;AAAA,EACF;AAEA,QAAM,EAAE,IAAI,UAAU,SAAS,IAAI,eAAe,OAAO;AAGzD,QAAM,YAAY,SAAS,IAAI,OAAO,KAAK,CAAC;AAC5C,MAAI,CAAC,SAAS,IAAI,OAAO,GAAG;AAC1B,aAAS,IAAI,SAAS,SAAS;AAAA,EACjC;AAEA,YAAU,KAAK,QAAQ;AACvB,WAAS,QAAQ,OAAO;AAExB,SAAO,SAAS,YAAY;AAE1B,cAAU,OAAO,UAAU,QAAQ,QAAQ,GAAG,CAAC;AAE/C,QAAI,UAAU,WAAW,GAAG;AAE1B,eAAS,OAAO,OAAO;AACvB,eAAS,UAAU,OAAO;AAAA,IAC5B;AAEA,QAAI,SAAS,SAAS,GAAG;AAEvB,eAAS,WAAW;AACpB,kBAAY,OAAO,EAAE;AAAA,IACvB;AAAA,EACF;AACF;;;ADhKA,SAAS,gBACP,OAC6B;AAC7B,SAAO,OAAO,MAAM,aAAa;AACnC;AAmDO,IAAM,SAAN,cAA2B,gBAGhC;AAAA,EAKA,YAAY,OAAuD;AACjE,UAAM,KAAK;AALb,gCAAuB;AACvB,wCAAoC;AACpC;AAuEA,sCAAa,CAAC,SAA0B;AACtC,UAAI,KAAK,MAAM;AAEb,aAAK,UAAU;AAEf,YAAI,CAAC,QAAQ,CAAC,KAAK,MAAM,eAAe,CAAC,KAAK,MAAM,MAAM;AAExD,eAAK,SAAS,EAAE,QAAQ,CAAC,CAAC,KAAK,MAAM,eAAe,OAAO,OAAU,CAAC;AACtE,eAAK,aAAa,KAAK,MAAM;AAAA,QAC/B;AAAA,MACF;AAEA,WAAK,OAAO,OAAO,OAAO;AAC1B,WAAK,YAAY;AAAA,IACnB;AAEA,wCAAe,CAAC,QAAiB,UAAqC;AACpE,YAAM,iBAAiB,KAAK;AAC5B,WAAK,aAAa;AAGlB,UAAI,mBAAmB,UAAa,CAAC,QAAQ;AAC3C;AAAA,MACF;AAEA,UAAI,UAAU,KAAK,MAAM,aAAa;AAEpC,aAAK,UAAU;AAAA,MACjB;AACA,UAAI,CAAC,gBAAgB,KAAK,KAAK,GAAG;AAGhC,aAAK,SAAS,EAAE,QAAQ,MAAM,CAAC;AAAA,MACjC;AACA,UAAI,KAAK,MAAM,UAAU;AAEvB,aAAK,MAAM,SAAS,QAAQ,KAAK;AAAA,MACnC;AAAA,IACF;AAzGE,SAAK,QAAQ;AAAA,MACX,QAAQ,CAAC,CAAC,MAAM;AAAA,MAChB,OAAO;AAAA,IACT;AACA,SAAK,aAAa,MAAM;AAAA,EAC1B;AAAA,EAEA,oBAAoB;AAClB,SAAK,UAAU;AACf,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,mBAAmB,WAAsC;AAEvD,QACE,UAAU,eAAe,KAAK,MAAM,cACpC,UAAU,SAAS,KAAK,MAAM,QAC9B,UAAU,cAAc,KAAK,MAAM,aACnC,UAAU,SAAS,KAAK,MAAM,QAC9B,UAAU,oBAAoB,KAAK,MAAM,mBACzC,UAAU,UAAU,KAAK,MAAM,OAC/B;AACA,WAAK,UAAU;AACf,WAAK,YAAY;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,uBAAuB;AACrB,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,cAAc;AACZ,QAAI,CAAC,KAAK,QAAQ,KAAK,MAAM,KAAM;AACnC,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI,KAAK;AAET,QAAI,KAAK,eAAe,QAAW;AACjC,WAAK,aAAa,KAAK,MAAM;AAAA,IAC/B;AACA,SAAK,eAAe;AAAA,MAClB,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA;AAAA,QAEA;AAAA,QACA;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,YAAY;AACV,QAAI,KAAK,cAAc;AACrB,WAAK,aAAa;AAClB,WAAK,eAAe;AAAA,IACtB;AAAA,EACF;AAAA,EA0CA,SAAS;AACP,UAAM,EAAE,SAAS,IAAI,KAAK;AAC1B,QAAI,OAAO,aAAa,YAAY;AAClC,YAAM,EAAE,QAAQ,MAAM,IAAI,KAAK;AAC/B,aAAO,SAAS,EAAE,QAAQ,OAAO,KAAK,KAAK,WAAW,CAAC;AAAA,IACzD;AAEA,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IACL,IAAI,KAAK;AAET,WAAa;AAAA,MACX,MAAM;AAAA,MACN,EAAE,KAAK,KAAK,YAAY,GAAG,MAAM;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AACF;;;AEjNA,YAAYC,YAAW;AAmChB,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,IAAyB,CAAC,GAAuB;AA9CjD,MAAAC;AA+CE,QAAM,CAAC,KAAK,MAAM,IAAU,gBAAyB,IAAI;AACzD,QAAM,WAAiB,cAAwC,QAAQ;AACvE,QAAM,gBAAsB,cAA4B,aAAa;AACrE,QAAM,CAAC,OAAO,QAAQ,IAAU,gBAAgB;AAAA,IAC9C,QAAQ,CAAC,CAAC;AAAA,IACV,OAAO;AAAA,EACT,CAAC;AAID,WAAS,UAAU;AAGnB,EAAM;AAAA,IACJ,MAAM;AACJ,UAAI,cAAc,YAAY,QAAW;AACvC,sBAAc,UAAU;AAAA,MAC1B;AAEA,UAAI,QAAQ,CAAC,IAAK;AAElB,UAAI;AACJ,kBAAY;AAAA,QACV;AAAA,QACA,CAAC,QAAQ,UAAU;AACjB,gBAAM,iBAAiB,cAAc;AACrC,wBAAc,UAAU;AAGxB,cAAI,mBAAmB,UAAa,CAAC,QAAQ;AAC3C;AAAA,UACF;AAEA,mBAAS;AAAA,YACP;AAAA,YACA;AAAA,UACF,CAAC;AACD,cAAI,SAAS,QAAS,UAAS,QAAQ,QAAQ,KAAK;AAEpD,cAAI,MAAM,kBAAkB,eAAe,WAAW;AAEpD,sBAAU;AACV,wBAAY;AAAA,UACd;AAAA,QACF;AAAA,QACA;AAAA,UACE;AAAA,UACA;AAAA,UACA;AAAA;AAAA,UAEA;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,MACF;AAEA,aAAO,MAAM;AACX,YAAI,WAAW;AACb,oBAAU;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AAAA;AAAA;AAAA,IAGA;AAAA;AAAA,MAEE,MAAM,QAAQ,SAAS,IAAI,UAAU,SAAS,IAAI;AAAA,MAClD;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,eAAcA,MAAA,MAAM,UAAN,gBAAAA,IAAa;AACjC,QAAM,sBAA4B,cAA4B,MAAS;AACvE,MACE,CAAC,OACD,eACA,CAAC,eACD,CAAC,QACD,oBAAoB,YAAY,aAChC;AAGA,wBAAoB,UAAU;AAC9B,aAAS;AAAA,MACP,QAAQ,CAAC,CAAC;AAAA,MACV,OAAO;AAAA,IACT,CAAC;AACD,kBAAc,UAAU;AAAA,EAC1B;AAEA,QAAM,SAAS,CAAC,QAAQ,MAAM,QAAQ,MAAM,KAAK;AAGjD,SAAO,MAAM,OAAO,CAAC;AACrB,SAAO,SAAS,OAAO,CAAC;AACxB,SAAO,QAAQ,OAAO,CAAC;AAEvB,SAAO;AACT;;;ACxJA,YAAYC,YAAW;AAAvB;AAOA,IAAM,iBAAkB,mCAAwBC,SAEzC,4BACH,WAHoB,YAIhB,2BAJgB,YAKhB;AAiCD,IAAM,cAAc,CACzB,sBACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,IAA+B,CAAC,MAC7B;AACH,QAAM,0BAAgC,cAAO,oBAAoB;AACjE,QAAM,qBAA2B,cAAwB,IAAI;AAC7D,QAAM,qBAA2B,cAAiC,MAAS;AAC3E,QAAM,gBAAsB,cAA4B,MAAS;AAEjE,gBAAc,MAAM;AAClB,4BAAwB,UAAU;AAAA,EACpC,GAAG,CAAC,oBAAoB,CAAC;AAGzB,SAAa;AAAA,IACX,CAAC,YAAyC;AAGxC,YAAM,kBAAkB,MAAM;AAC5B,YAAI,mBAAmB,SAAS;AAC9B,gBAAM,UAAU,mBAAmB;AACnC,6BAAmB,UAAU;AAC7B,kBAAQ;AAAA,QACV;AAAA,MACF;AAEA,UAAI,YAAY,mBAAmB,SAAS;AAC1C,eAAO,mBAAmB;AAAA,MAC5B;AAEA,UAAI,CAAC,WAAW,MAAM;AACpB,wBAAgB;AAChB,2BAAmB,UAAU;AAC7B,sBAAc,UAAU;AACxB;AAAA,MACF;AAEA,sBAAgB;AAEhB,yBAAmB,UAAU;AAC7B,UAAI,YAAY;AAEhB,YAAM,kBAAkB;AAAA,QACtB;AAAA,QACA,CAAC,QAAQ,UAAU;AACjB,gBAAM,iBAAiB,cAAc;AACrC,wBAAc,UAAU;AAGxB,cAAI,mBAAmB,UAAa,CAAC,QAAQ;AAC3C;AAAA,UACF;AAEA,kCAAwB;AAAA,YACtB;AAAA,YACA;AAAA,UACF;AACA,cAAI,eAAe,QAAQ;AACzB,0BAAc;AAAA,UAChB;AAAA,QACF;AAAA,QACA;AAAA,UACE;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAEA,eAAS,gBAAgB;AAGvB,YAAI,UAAW;AACf,oBAAY;AACZ,wBAAgB;AAChB,2BAAmB,UAAU;AAC7B,2BAAmB,UAAU;AAC7B,sBAAc,UAAU;AAAA,MAC1B;AAEA,yBAAmB,UAAU;AAE7B,aAAO,mBAAmB;AAAA,IAC5B;AAAA,IACA;AAAA,MACE,MAAM,QAAQ,SAAS,IAAI,UAAU,SAAS,IAAI;AAAA,MAClD;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;","names":["_a","React","_a","React","React"]}