{"version":3,"sources":["Video.tsx"],"sourcesContent":["import {\n    addPropertyControls,\n    ControlType,\n    useIsInCurrentNavigationTarget,\n    RenderTarget,\n} from \"framer\"\nimport { isMotionValue, MotionValue, useInView } from \"framer-motion\"\nimport {\n    borderRadiusControl,\n    defaultEvents,\n    useIsBrowserSafari,\n    useIsOnCanvas,\n    useOnEnter,\n    useOnExit,\n    useRadius,\n    useRenderTarget,\n} from \"https://framerusercontent.com/modules/G4IfyjvwmaeSBpdb4TWu/OIjZRBmWDcIE2B6qgG1j/index.js\" // https://framer.com/m/framer/default-utils.js@^0.45.0\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from \"react\"\n\nexport interface VideoProps {\n    backgroundColor?: string\n    bottomLeft?: number\n    bottomRight?: number\n    controls?: boolean\n    isMixed?: boolean\n    loop?: boolean\n    muted?: boolean\n    objectFit?: ObjectFitType\n    onClick?: (Event: React.SyntheticEvent<HTMLElement>) => void\n    onEnd?: (Event: React.SyntheticEvent<HTMLElement>) => void\n    onMouseDown?: (Event: React.SyntheticEvent<HTMLElement>) => void\n    onMouseEnter?: (Event: React.SyntheticEvent<HTMLElement>) => void\n    onMouseLeave?: (Event: React.SyntheticEvent<HTMLElement>) => void\n    onMouseUp?: (Event: React.SyntheticEvent<HTMLElement>) => void\n    onPause?: (Event: React.SyntheticEvent<HTMLElement>) => void\n    onPlay?: (Event: React.SyntheticEvent<HTMLElement>) => void\n    onSeeked?: (Event: React.SyntheticEvent<HTMLElement>) => void\n    playing?: boolean\n    playsinline?: boolean\n    poster?: string\n    posterEnabled?: boolean\n    progress?: number | MotionValue\n    radius?: number\n    restartOnEnter?: boolean\n    srcFile?: string\n    srcType?: SrcType\n    srcUrl?: string\n    startTime?: number\n    topLeft?: number\n    topRight?: number\n    volume?: number\n}\n\nenum ObjectFitType {\n    Fill = \"fill\",\n    Contain = \"contain\",\n    Cover = \"cover\",\n    None = \"none\",\n    ScaleDown = \"scale-down\",\n}\n\nenum SrcType {\n    Video = \"Upload\",\n    Url = \"URL\",\n}\n\nconst defaultVideo =\n    \"https://framerusercontent.com/assets/MLWPbW1dUQawJLhhun3dBwpgJak.mp4\"\n\n// Reduce renders\nfunction getProps(props: any): any {\n    const {\n        width,\n        height,\n        topLeft,\n        topRight,\n        bottomRight,\n        bottomLeft,\n        id,\n        children,\n        ...rest\n    } = props\n    return rest\n}\n\n/**\n * VIDEO\n *\n * @framerIntrinsicWidth 200\n * @framerIntrinsicHeight 112\n *\n * @framerSupportedLayoutWidth fixed\n * @framerSupportedLayoutHeight any-prefer-fixed\n */\nexport function Video(props) {\n    const newProps = getProps(props)\n    return <VideoMemo {...newProps} />\n}\n\nfunction usePlaybackControls(\n    videoRef: React.MutableRefObject<HTMLVideoElement | undefined>\n) {\n    const isInCurrentNavigationTarget = useIsInCurrentNavigationTarget()\n    const requestingPlay = useRef<boolean>(false)\n    const isPlayingRef = useRef<boolean>(false)\n\n    const setProgress = useCallback((rawProgress) => {\n        if (!videoRef.current) return\n\n        const newProgress =\n            (rawProgress === 1 ? 0.999 : rawProgress) *\n            videoRef.current.duration\n\n        const isAlreadySet =\n            Math.abs(videoRef.current.currentTime - newProgress) < 0.1\n\n        if (videoRef.current.duration > 0 && !isAlreadySet) {\n            videoRef.current.currentTime = newProgress\n        }\n    }, [])\n\n    const play = useCallback(() => {\n        const video = videoRef.current\n        if (!video) return\n\n        video.preload = \"auto\" // makes sure browsers don't throttle: https://html.spec.whatwg.org/multipage/media.html#:~:text=When%20the%20media%20resource%20is%20playing%2C%20hints%20to%20the%20user%20agent%20that%20bandwidth%20is%20to%20be%20considered%20scarce%2C%20e.g.%20suggesting%20throttling%20the%20download%20so%20that%20the%20media%20data%20is%20obtained%20at%20the%20slowest%20possible%20rate%20that%20still%20maintains%20consistent%20playback.\n\n        const isPlaying =\n            video.currentTime > 0 &&\n            video.onplaying &&\n            !video.paused &&\n            !video.ended &&\n            video.readyState >= video.HAVE_CURRENT_DATA\n\n        if (\n            !isPlaying &&\n            video &&\n            !requestingPlay.current &&\n            isInCurrentNavigationTarget\n        ) {\n            requestingPlay.current = true\n            isPlayingRef.current = true\n            video\n                .play()\n                .catch((e) => {}) // It's likely fine, swallow error\n                .finally(() => (requestingPlay.current = false))\n        }\n    }, [])\n\n    const pause = useCallback(() => {\n        if (!videoRef.current || requestingPlay.current) return\n        videoRef.current.pause()\n        isPlayingRef.current = false\n    }, [])\n\n    return { play, pause, setProgress, isPlaying: isPlayingRef }\n}\n\nfunction useAutoplayBehavior({\n    playingProp,\n    muted,\n    loop,\n    playsinline,\n    controls,\n}: {\n    playingProp: boolean | undefined\n    muted: boolean | undefined\n    loop: boolean | undefined\n    playsinline: boolean | undefined\n    controls: boolean | undefined\n}) {\n    const [initialPlayingProp] = useState(() => playingProp)\n    const [hasPlayingPropChanged, setHasPlayingPropChanged] = useState(false)\n    if (playingProp !== initialPlayingProp && !hasPlayingPropChanged) {\n        setHasPlayingPropChanged(true)\n    }\n\n    const behavesAsGif =\n        // passing `playing === true` on mount indicates that the video should\n        // autoplay, like a GIF\n        initialPlayingProp &&\n        muted &&\n        loop &&\n        playsinline &&\n        !controls &&\n        // Some users of the <Video> component use it by wrapping it with\n        // another smart component and adding their own controls on top. (The\n        // controls use transitions to control the video: e.g., when clicking\n        // the play button, the smart component will transition to a state with\n        // <Video playing={true} />.) In this case, we don't want the video to\n        // behave as a gif, as it will be weird if the video suddenly started\n        // acting as such (and auto-pausing when leaving the viewport) as soon\n        // as the site visitor mutes it and clicks “Play”.\n        !hasPlayingPropChanged\n\n    let autoplay: \"on-mount\" | \"on-viewport\" | \"no-autoplay\"\n    if (behavesAsGif) autoplay = \"on-viewport\"\n    else if (initialPlayingProp) autoplay = \"on-mount\"\n    else autoplay = \"no-autoplay\"\n\n    return autoplay\n}\n\nconst VideoMemo = memo(function VideoInner(props: VideoProps) {\n    const {\n        // default props\n        srcType = SrcType.Url,\n        srcUrl,\n        srcFile = \"\",\n        posterEnabled = false,\n        controls = false,\n        playing = true,\n        loop = true,\n        muted = true,\n        playsinline = true,\n        restartOnEnter = false,\n        objectFit = ObjectFitType.Cover,\n        backgroundColor = \"rgba(0,0,0,0)\",\n        radius = 0,\n        volume = 25,\n        startTime: startTimeProp = 0,\n        poster,\n\n        playing: playingProp,\n        progress,\n        onSeeked,\n        onPause,\n        onPlay,\n        onEnd,\n        onClick,\n        onMouseEnter,\n        onMouseLeave,\n        onMouseDown,\n        onMouseUp,\n    } = props\n\n    const videoRef = useRef<HTMLVideoElement>()\n    const isSafari = useIsBrowserSafari()\n    const wasPausedOnLeave = useRef<boolean | null>(null)\n    const wasEndedOnLeave = useRef<boolean | null>(null)\n    const isOnCanvas = useIsOnCanvas()\n    const renderTarget = useRenderTarget()\n    const isStaticRenderer = isOnCanvas || renderTarget === RenderTarget.export\n    const borderRadius = useRadius(props)\n\n    // Hard-coding `autoplayBehavior` and `isInViewport` when on canvas as a\n    // tiny perf optimization. isStaticRenderer won’t change through the lifecycle of\n    // the component, so using these hooks conditionally should be safe\n    const autoplayBehavior = isStaticRenderer\n        ? \"no-autoplay\"\n        : useAutoplayBehavior({\n              playingProp,\n              muted,\n              loop,\n              playsinline,\n              controls,\n          })\n    const isInViewport = isStaticRenderer ? true : useInView(videoRef)\n    const isCloseToViewport = isStaticRenderer\n        ? false\n        : // trigger a bit earlier\n          useInView(videoRef, { margin: \"10%\", once: true })\n\n    // Video elements behave oddly at 100% duration\n    const startTime = startTimeProp === 100 ? 99.9 : startTimeProp\n\n    const { play, pause, setProgress, isPlaying } =\n        usePlaybackControls(videoRef)\n\n    // Pause/play via props\n    useEffect(() => {\n        if (isStaticRenderer) return\n        if (autoplayBehavior === \"on-viewport\") return\n\n        if (playingProp) play()\n        else pause()\n    }, [autoplayBehavior, playingProp])\n\n    // Pause/play via viewport\n    useEffect(() => {\n        if (isStaticRenderer) return\n\n        // this also explicitly retries playing for videos that play on-mount, which could fail if they're not muted for example\n        if (isInViewport && playingProp && autoplayBehavior !== \"no-autoplay\")\n            play()\n\n        if (autoplayBehavior !== \"on-viewport\") return\n        pause()\n    }, [autoplayBehavior, isInViewport, playingProp])\n\n    useEffect(() => {\n        if (\n            !isOnCanvas ||\n            poster ||\n            posterEnabled ||\n            startTime ||\n            !videoRef.current\n        )\n            return\n\n        // forces a poster to show up when the video is in an iframe; this is needed when `poster` changes\n        videoRef.current.currentTime = 0.01\n    }, [posterEnabled, poster, startTime])\n\n    /**\n     * The Video component has some effects that sync the video element with props\n     * like `startTime`, `progress`, etc. React calls these effects whenever these\n     * props change. However, it also calls them on the first mount, and this is\n     * troublesome – if we’re doing SSR, and the user changed the video state before\n     * the video was hydrated, the initial `useEffect` call will reset the video\n     * state. To avoid this, we use this flag.\n     */\n    const isMountedAndReadyForProgressChanges = useRef(false)\n    // Allow scrubbling via progress prop\n    // 1) Handle cases when the progress prop itself changes\n    useEffect(() => {\n        if (!isMountedAndReadyForProgressChanges.current) {\n            isMountedAndReadyForProgressChanges.current = true\n            return\n        }\n\n        const rawProgressValue = isMotionValue(progress)\n            ? // The motion value is from 0 to 1\n              progress.get()\n            : // The raw progress prop is from 0 to 100\n              (progress ?? 0) * 0.01\n        setProgress(\n            // When the progress value exists (e.g. <Video startTime={10}\n            // progress={50} />), we respect the `progress` value over\n            // `startTime`, even if `startTime` changes. That’s because\n            // `startTime` == start == changing it shouldn’t affect the current\n            // progress\n            (rawProgressValue ?? 0) ||\n                // Then why fall back to `startTime` when `progress` doesn’t exist,\n                // you might ask? Now, that’s for\n                // - canvas UX: we want the video progress to change when the user\n                //   is scrobbling the “Start Time” in component settings.\n                // - backwards compatibility: maybe some users *are* scrobbling\n                //   using `startTime` instead of `progress`? We don’t know, and it\n                //   always supported it, so let’s not break it\n                (startTime ?? 0) / 100\n        )\n    }, [startTime, srcFile, srcUrl, progress])\n\n    // 2) Handle cases when the motion value inside the progress prop changes\n    useEffect(() => {\n        if (!isMotionValue(progress)) return\n\n        return progress.on(\"change\", (value) => setProgress(value))\n    }, [progress])\n\n    // (Prototyping) Checking if we need to play on navigation enter\n    useOnEnter(() => {\n        if (wasPausedOnLeave.current === null) return\n        if (videoRef.current) {\n            // if (restartOnEnter) setProgress(0)\n            if ((!wasEndedOnLeave && loop) || !wasPausedOnLeave.current) play()\n        }\n    })\n\n    // (Prototyping) Pausing & saving playing state on navigation exit\n    useOnExit(() => {\n        if (videoRef.current) {\n            wasEndedOnLeave.current = videoRef.current.ended\n            wasPausedOnLeave.current = videoRef.current.paused\n            pause()\n        }\n    })\n\n    const src = useMemo(() => {\n        let fragment = \"\"\n        // if (\n        //     startTime > 0 &&\n        //     videoRef.current &&\n        //     !isNaN(videoRef.current.duration) &&\n        //     !isStaticRenderer\n        // ) {\n        //     console.log(startTime, videoRef.current.duration)\n        //     fragment = `#t=${startTime * videoRef.current.duration}`\n        // }\n\n        if (srcType === SrcType.Url) return srcUrl + fragment\n        if (srcType === SrcType.Video) return srcFile + fragment\n    }, [srcType, srcFile, srcUrl, startTime])\n\n    // Autoplay via JS to work in Safari\n    useEffect(() => {\n        if (isSafari && videoRef.current && autoplayBehavior === \"on-mount\") {\n            setTimeout(() => play(), 50)\n        }\n    }, [])\n\n    // Volume Control\n    useEffect(() => {\n        if (videoRef.current && !muted)\n            videoRef.current.volume = (volume ?? 0) / 100\n    }, [volume])\n\n    // When video is ready, set start-time, then autoplay if needed\n    const handleReady = () => {\n        const video = videoRef.current\n        if (!video) return\n\n        if (video.currentTime < 0.3 && startTime > 0)\n            setProgress((startTime ?? 0) * 0.01)\n        if (\n            // when the component updates (e.g. only srcFile/url changes), and the video was already playing, keep playing\n            isPlaying.current ||\n            autoplayBehavior === \"on-mount\" ||\n            (playingProp && autoplayBehavior === \"on-viewport\" && isInViewport)\n        )\n            play()\n    }\n\n    return (\n        <video\n            {...{\n                onClick,\n                onMouseEnter,\n                onMouseLeave,\n                onMouseDown,\n                onMouseUp,\n            }}\n            src={src}\n            loop={loop}\n            ref={videoRef}\n            onSeeked={(e) => onSeeked?.(e)}\n            onPause={(e) => onPause?.(e)}\n            onPlay={(e) => onPlay?.(e)}\n            onEnded={(e) => onEnd?.(e)}\n            autoPlay={\n                isPlaying.current ||\n                autoplayBehavior === \"on-mount\" ||\n                (playingProp &&\n                    autoplayBehavior === \"on-viewport\" &&\n                    isInViewport)\n            }\n            preload={\n                isPlaying.current\n                    ? \"auto\"\n                    : // ensure we always have a thumbnail on the canvas\n                      isStaticRenderer && !poster\n                      ? \"metadata\"\n                      : autoplayBehavior !== \"on-mount\" && !isCloseToViewport\n                        ? \"none\"\n                        : // metadata ensures a thumbnail is shown & dimensions are downloaded\n                          // `autoplay` overrides this too\n                          \"metadata\"\n            }\n            poster={\n                posterEnabled && !srcFile && srcUrl === defaultVideo\n                    ? \"https://framerusercontent.com/images/5ILRvlYXf72kHSVHqpa3snGzjU.jpg\"\n                    : posterEnabled && poster\n                      ? poster\n                      : undefined\n            }\n            onLoadedData={handleReady}\n            controls={controls}\n            muted={isStaticRenderer ? true : muted}\n            playsInline={playsinline}\n            style={{\n                cursor: !!onClick ? \"pointer\" : \"auto\",\n                width: \"100%\",\n                height: \"100%\",\n                borderRadius,\n                display: \"block\",\n                objectFit: objectFit,\n                backgroundColor: backgroundColor,\n                objectPosition: \"50% 50%\",\n            }}\n        />\n    )\n})\n\nVideo.displayName = \"Video\"\n\nfunction capitalizeFirstLetter(value: string) {\n    return value.charAt(0).toUpperCase() + value.slice(1)\n}\nexport function titleCase(value: string): string {\n    const groups = value.match(/[A-Z]{2,}|[A-Z][a-z]+|[a-z]+|[A-Z]|\\d+/gu) || []\n\n    return groups.map(capitalizeFirstLetter).join(\" \")\n}\n\nconst objectFitOptions = [\n    ObjectFitType.Cover,\n    ObjectFitType.Fill,\n    ObjectFitType.Contain,\n    ObjectFitType.ScaleDown,\n    ObjectFitType.None,\n]\n\naddPropertyControls(Video, {\n    srcType: {\n        type: ControlType.Enum,\n        displaySegmentedControl: true,\n        title: \"Source\",\n        options: [SrcType.Url, SrcType.Video],\n    },\n    srcUrl: {\n        type: ControlType.String,\n        title: \"URL\",\n        defaultValue:\n            \"https://framerusercontent.com/assets/MLWPbW1dUQawJLhhun3dBwpgJak.mp4\",\n        hidden(props) {\n            return props.srcType === SrcType.Video\n        },\n    },\n    srcFile: {\n        type: ControlType.File,\n        title: \"File\",\n        allowedFileTypes: [\"mp4\", \"webm\"],\n        hidden(props) {\n            return props.srcType === SrcType.Url\n        },\n    },\n    playing: {\n        type: ControlType.Boolean,\n        title: \"Playing\",\n        enabledTitle: \"Yes\",\n        disabledTitle: \"No\",\n    },\n    ...borderRadiusControl,\n    posterEnabled: {\n        type: ControlType.Boolean,\n        title: \"Poster\",\n        enabledTitle: \"Yes\",\n        disabledTitle: \"No\",\n    },\n    poster: {\n        type: ControlType.Image,\n        title: \"Image\",\n        hidden: ({ posterEnabled }) => !posterEnabled,\n        description:\n            \"We recommend adding a poster. [Learn more](https://www.framer.com/help/articles/how-are-videos-optimized-in-framer/).\",\n    },\n    backgroundColor: {\n        type: ControlType.Color,\n        title: \"Background\",\n        defaultValue: \"rgba(0,0,0,0)\",\n    },\n    startTime: {\n        title: \"Start Time\",\n        type: ControlType.Number,\n        min: 0,\n        max: 100,\n        step: 0.1,\n        unit: \"%\",\n    },\n    loop: {\n        type: ControlType.Boolean,\n        title: \"Loop\",\n        enabledTitle: \"Yes\",\n        disabledTitle: \"No\",\n    },\n    objectFit: {\n        type: ControlType.Enum,\n        title: \"Fit\",\n        options: objectFitOptions,\n        optionTitles: objectFitOptions.map(titleCase),\n    },\n    // restartOnEnter: {\n    //     type: ControlType.Boolean,\n    //     title: \"On ReEnter\",\n    //     enabledTitle: \"Restart\",\n    //     disabledTitle: \"Resume\",\n    // },\n    controls: {\n        type: ControlType.Boolean,\n        title: \"Controls\",\n        enabledTitle: \"Show\",\n        disabledTitle: \"Hide\",\n        defaultValue: false,\n    },\n    muted: {\n        type: ControlType.Boolean,\n        title: \"Muted\",\n        enabledTitle: \"Yes\",\n        disabledTitle: \"No\",\n    },\n    volume: {\n        type: ControlType.Number,\n        max: 100,\n        min: 0,\n        unit: \"%\",\n        hidden: ({ muted }) => muted,\n        defaultValue: 25,\n    },\n    onEnd: { type: ControlType.EventHandler },\n    onSeeked: { type: ControlType.EventHandler },\n    onPause: { type: ControlType.EventHandler },\n    onPlay: { type: ControlType.EventHandler },\n    ...defaultEvents,\n})\n"],"names":[],"mappings":"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"}