diff --git a/packages/custoplayer/cypress/component/ProgressBars.cy.tsx b/packages/custoplayer/cypress/component/ProgressBars.cy.tsx
index 05528dd..d803adc 100644
--- a/packages/custoplayer/cypress/component/ProgressBars.cy.tsx
+++ b/packages/custoplayer/cypress/component/ProgressBars.cy.tsx
@@ -10,6 +10,15 @@ describe('ProgressBars.cy.tsx', () => {
cy.dataCy('progressBar3').should('exist');
});
+ it("renders topProgressBars", () => {
+ cy.mount();
+ cy.dataCy('progressBar1').should('exist').should('have.css', 'align-items', 'flex-end');
+ cy.mount();
+ cy.dataCy('progressBar2').should('exist').should('have.css', 'align-items', 'flex-end');
+ cy.mount();
+ cy.dataCy('progressBar3').should('exist').should('have.css', 'align-items', 'flex-end');
+ })
+
it('renders progressBars buffered color', () => {
let bufferedColor = 'rgb(82, 158, 233)'
cy.mount(
diff --git a/packages/custoplayer/package.json b/packages/custoplayer/package.json
index 7c3915a..5484ecf 100644
--- a/packages/custoplayer/package.json
+++ b/packages/custoplayer/package.json
@@ -1,95 +1,95 @@
{
- "name": "custoplayer",
- "version": "0.1.2",
- "scripts": {
- "dev": "vite",
- "build": "tsc && vite build",
- "preview": "vite preview",
- "cy:open-e2e": "cypress open --e2e --browser chrome",
- "cy:open-unit": "cypress open --component --browser chrome",
- "cy:run-e2e": "cypress run --e2e",
- "cy:run-unit": "cypress run --component",
- "prepack": "json -f package.json -I -e \"delete this.devDependencies; delete this.dependencies\"",
- "lint": "eslint './src/**/*.{tsx,ts}'",
- "lint-fix": "eslint './src/**/*.{tsx,ts}' --fix"
- },
- "license": "MIT",
- "files": [
- "dist"
- ],
- "keywords": [
- "video",
- "videoplayer",
- "video-player",
- "react"
- ],
- "main": "./dist/custoplayer.umd.js",
- "module": "./dist/custoplayer.es.js",
- "types": "./dist/index.d.ts",
- "exports": {
- ".": {
- "import": "./dist/custoplayer.es.js",
- "require": "./dist/custoplayer.umd.js"
- }
- },
- "nyc": {
- "reporter": [
- "html"
- ]
- },
- "resolutions": {
- "minimist": "^1.2.5"
- },
- "dependencies": {
- "color": "^4.2.3",
- "framer-motion": "^8.5.0",
- "jotai": "^1.13.1",
- "minimist": "^1.2.8",
- "react": "^18.2.0",
- "react-dom": "^18.2.0",
- "screenfull": "^6.0.2",
- "styled-components": "5.3.5"
- },
- "peerDependencies": {
- "framer-motion": "8.5.0",
- "jotai": "1.13.1",
- "react": "17.x || 18.x",
- "react-dom": " 17.x || 18.x",
- "styled-components": "5.0.0"
- },
- "devDependencies": {
- "@babel/core": "^7.20.12",
- "@babel/preset-react": "^7.18.6",
- "@babel/preset-typescript": "^7.21.0",
- "@cypress/code-coverage": "^3.10.0",
- "@cypress/vite-dev-server": "^5.0.4",
- "@istanbuljs/nyc-config-typescript": "^1.0.2",
- "@types/color": "^3.0.3",
- "@types/node": "^18.11.18",
- "@types/react": "^18.0.27",
- "@types/react-dom": "^18.0.10",
- "@types/styled-components": "^5.1.26",
- "@typescript-eslint/eslint-plugin": "^5.54.0",
- "@typescript-eslint/parser": "^5.54.0",
- "@vitejs/plugin-react": "1.3.2",
- "acorn-jsx": "5.3.2",
- "babel-loader": "8.2.4",
- "babel-plugin-istanbul": "^6.1.1",
- "cypress": "^12.7.0",
- "eslint-config-prettier": "^8.6.0",
- "eslint-plugin-import": "^2.27.5",
- "eslint-plugin-prettier": "^4.2.1",
- "eslint-plugin-react": "^7.32.2",
- "eslint-plugin-react-hooks": "^4.6.0",
- "eslint-plugin-sonarjs": "^0.18.0",
- "json": "11.0.0",
- "nyc": "^15.1.0",
- "prettier": "^2.8.4",
- "prettier-eslint": "^15.0.1",
- "storybook-builder-vite": "0.1.21",
- "typescript": "^4.9.4",
- "vite": "^2.9.13",
- "vite-plugin-dts": "^1.7.1",
- "vite-plugin-istanbul": "^4.0.1"
+ "name": "custoplayer",
+ "version": "0.2.0",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc && vite build",
+ "preview": "vite preview",
+ "cy:open-e2e": "cypress open --e2e --browser chrome",
+ "cy:open-unit": "cypress open --component --browser chrome",
+ "cy:run-e2e": "cypress run --e2e",
+ "cy:run-unit": "cypress run --component",
+ "prepack": "json -f package.json -I -e \"delete this.devDependencies; delete this.dependencies\"",
+ "lint": "eslint './src/**/*.{tsx,ts}'",
+ "lint-fix": "eslint './src/**/*.{tsx,ts}' --fix"
+ },
+ "license": "MIT",
+ "files": [
+ "dist"
+ ],
+ "keywords": [
+ "video",
+ "videoplayer",
+ "video-player",
+ "react"
+ ],
+ "main": "./dist/custoplayer.umd.js",
+ "module": "./dist/custoplayer.es.js",
+ "types": "./dist/index.d.ts",
+ "exports": {
+ ".": {
+ "import": "./dist/custoplayer.es.js",
+ "require": "./dist/custoplayer.umd.js"
}
+ },
+ "nyc": {
+ "reporter": [
+ "html"
+ ]
+ },
+ "resolutions": {
+ "minimist": "^1.2.5"
+ },
+ "dependencies": {
+ "color": "^4.2.3",
+ "framer-motion": "^8.5.0",
+ "jotai": "^1.13.1",
+ "minimist": "^1.2.8",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "screenfull": "^6.0.2",
+ "styled-components": "5.3.5"
+ },
+ "peerDependencies": {
+ "framer-motion": "8.5.0",
+ "jotai": "1.13.1",
+ "react": "17.x || 18.x",
+ "react-dom": " 17.x || 18.x",
+ "styled-components": "5.0.0"
+ },
+ "devDependencies": {
+ "@babel/core": "^7.20.12",
+ "@babel/preset-react": "^7.18.6",
+ "@babel/preset-typescript": "^7.21.0",
+ "@cypress/code-coverage": "^3.10.0",
+ "@cypress/vite-dev-server": "^5.0.4",
+ "@istanbuljs/nyc-config-typescript": "^1.0.2",
+ "@types/color": "^3.0.3",
+ "@types/node": "^18.11.18",
+ "@types/react": "^18.0.27",
+ "@types/react-dom": "^18.0.10",
+ "@types/styled-components": "^5.1.26",
+ "@typescript-eslint/eslint-plugin": "^5.54.0",
+ "@typescript-eslint/parser": "^5.54.0",
+ "@vitejs/plugin-react": "1.3.2",
+ "acorn-jsx": "5.3.2",
+ "babel-loader": "8.2.4",
+ "babel-plugin-istanbul": "^6.1.1",
+ "cypress": "^12.7.0",
+ "eslint-config-prettier": "^8.6.0",
+ "eslint-plugin-import": "^2.27.5",
+ "eslint-plugin-prettier": "^4.2.1",
+ "eslint-plugin-react": "^7.32.2",
+ "eslint-plugin-react-hooks": "^4.6.0",
+ "eslint-plugin-sonarjs": "^0.18.0",
+ "json": "11.0.0",
+ "nyc": "^15.1.0",
+ "prettier": "^2.8.4",
+ "prettier-eslint": "^15.0.1",
+ "storybook-builder-vite": "0.1.21",
+ "typescript": "^4.9.4",
+ "vite": "^2.9.13",
+ "vite-plugin-dts": "^1.7.1",
+ "vite-plugin-istanbul": "^4.0.1"
+ }
}
diff --git a/packages/custoplayer/src/lib/components/ControlsBar.tsx b/packages/custoplayer/src/lib/components/ControlsBar.tsx
index 20367d2..fd47b9d 100644
--- a/packages/custoplayer/src/lib/components/ControlsBar.tsx
+++ b/packages/custoplayer/src/lib/components/ControlsBar.tsx
@@ -26,6 +26,7 @@ import {
controlsBarMovementAnimation,
controlsBarOpacityAnimation,
} from '@root/lib/variants';
+import ProgressBars from './ProgressBars/index';
function extractColor(curItem: CustoplayerItem) {
if (
@@ -81,6 +82,12 @@ function ControlsBar() {
exit='exit'
data-cy='controlsBar'
>
+ {videoValues.topProgressBar && (
+
+
+
+ )}
+
`
}
`;
+export const TopProgressBarContainer = styled.div`
+ width: 100%;
+ height: 3rem;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-end;
+`;
+
export default ControlsBar;
diff --git a/packages/custoplayer/src/lib/components/ProgressBars/ProgressBar2.tsx b/packages/custoplayer/src/lib/components/ProgressBars/ProgressBar2.tsx
index 1af23b3..df94be8 100644
--- a/packages/custoplayer/src/lib/components/ProgressBars/ProgressBar2.tsx
+++ b/packages/custoplayer/src/lib/components/ProgressBars/ProgressBar2.tsx
@@ -59,7 +59,7 @@ const Bar2 = styled(motion.div)<{ barColor: string | undefined }>`
display: flex;
background-color: ${(props) => (props.barColor ? props.barColor : '#f2f2f2')};
width: 100%;
- height: 65%;
+ height: 1.25rem;
justify-content: flex-start;
position: relative;
`;
diff --git a/packages/custoplayer/src/lib/components/ProgressBars/ProgressBar3.tsx b/packages/custoplayer/src/lib/components/ProgressBars/ProgressBar3.tsx
index e83bcec..0e070b8 100644
--- a/packages/custoplayer/src/lib/components/ProgressBars/ProgressBar3.tsx
+++ b/packages/custoplayer/src/lib/components/ProgressBars/ProgressBar3.tsx
@@ -49,6 +49,7 @@ const ProgressBar3 = forwardRef[((props, ref) => {
}}
progressColor={props.item.progressColor}
/>
+
{values.previewTooltip && (
props.barColor ? props.barColor : 'transparent'};
width: 100%;
- height: 65%;
+ height: 1.25rem;
justify-content: flex-start;
border-radius: 1rem;
align-items: center;
diff --git a/packages/custoplayer/src/lib/components/ProgressBars/index.tsx b/packages/custoplayer/src/lib/components/ProgressBars/index.tsx
index f0c9270..9de0304 100644
--- a/packages/custoplayer/src/lib/components/ProgressBars/index.tsx
+++ b/packages/custoplayer/src/lib/components/ProgressBars/index.tsx
@@ -4,19 +4,15 @@ import {
playStateAtom,
previewTooltipPositionAtom,
previewTooltipStrAtom,
- previewTooltipWidth,
progressAtom,
videoContainerAtom,
videoElemAtom,
} from '@root/lib/atoms';
import {
+ barMouseDown,
BarMouseEvent,
- barMouseEvent,
- clamp,
- formatTime,
- getLargestProgressBarMousePos,
- isMouseFunc,
- isTouchscreenFunc,
+ handleProgressBarMouseMove,
+ showPreviewThumbnail,
} from '@root/lib/utils';
import { ProgressBarItem } from '@root/lib/types';
import { useAtom, useAtomValue, useSetAtom } from 'jotai';
@@ -25,13 +21,14 @@ import styled from 'styled-components';
import { useProgressDragging } from '../../hooks';
import ProgressBar1 from './ProgressBar1';
import ProgressBar2 from './ProgressBar2';
-import ProgressBar3 from '@root/lib/components/ProgressBars/ProgressBar3';
+import ProgressBar3 from './ProgressBar3';
interface ProgressBarsProps {
item: ProgressBarItem;
+ onTop?: boolean;
}
-function ProgressBars({ item }: ProgressBarsProps) {
+function ProgressBars({ item, onTop = false }: ProgressBarsProps) {
const progressBarRef = useRef(null);
const [isHovered, setIsHovered] = useState(false);
const videoElem = useAtomValue(videoElemAtom, myScope);
@@ -51,84 +48,27 @@ function ProgressBars({ item }: ProgressBarsProps) {
);
const setTooltipStr = useSetAtom(previewTooltipStrAtom, myScope);
- function handleProgressMouseMove(
+ /**
+ A wrapper function for handleProgressBarMouseMove that passes in the
+ video container's bounding rect. It is the callback function for
+ the barMouseDown
+ */
+ function handleProgressBarMouseMoveWrapper(
e: BarMouseEvent,
videoContainerRect: DOMRect,
) {
- setIsProgressDragging(true);
- if (progressBarRef && progressBarRef.current) {
- let xPos = 0;
- if (isTouchscreenFunc(e)) xPos = e.touches[0].clientX;
- else if (isMouseFunc(e)) xPos = e.clientX;
- const progressBarRect = progressBarRef.current.getBoundingClientRect();
- const [largestProgressBarMousePos, distLeftOfProgressBar, _] =
- getLargestProgressBarMousePos(videoContainerRect, progressBarRect);
-
- const updatedMousePos = xPos - videoContainerRect.left;
-
- handleMouseMove(e);
- const adjustedMousePos = updatedMousePos - distLeftOfProgressBar;
- const clampedMousePos = clamp(
- adjustedMousePos,
- 0,
- largestProgressBarMousePos,
- );
-
- const ratio = clampedMousePos / progressBarRef.current.clientWidth;
- if (videoElem && videoElem.duration) {
- const currentTime = videoElem.duration * ratio;
- videoElem.currentTime = currentTime;
- setTooltipStr(formatTime(currentTime));
- }
-
- setProgress(ratio);
- }
- }
- /* Shows the preview thumbnail when mouse is over progress bar */
- function handleMouseMove(e: BarMouseEvent) {
- if (
- isProgressDragging ||
- !progressBarRef ||
- !progressBarRef.current ||
- !videoContainer
- )
- return;
- let xPos = 0;
- if (isTouchscreenFunc(e)) xPos = e.touches[0].clientX;
- else if (isMouseFunc(e)) xPos = e.clientX;
- const progressBarRect = progressBarRef.current.getBoundingClientRect();
- const widthOfItemsToLeftOfProgressBar =
- progressBarRef.current.getBoundingClientRect().left -
- videoContainer?.getBoundingClientRect().left;
- const widthOfItemsToRightOfProgressBar =
- videoContainer?.getBoundingClientRect().right -
- progressBarRef.current.getBoundingClientRect().right;
- const defaultHoverPos = xPos - progressBarRect.left;
- let hoverPos = xPos - progressBarRect.left - previewTooltipWidth / 2;
- const modifiedUpperBound =
- progressBarRef.current?.clientWidth -
- previewTooltipWidth / 2 +
- widthOfItemsToRightOfProgressBar;
- const maxHoverPos =
- progressBarRef.current.clientWidth - previewTooltipWidth / 2;
- const minHoverPos = Math.max(
- (-1 * previewTooltipWidth) / 2,
- -1 * widthOfItemsToLeftOfProgressBar,
+ handleProgressBarMouseMove(
+ e,
+ videoContainerRect,
+ isProgressDragging,
+ progressBarRef,
+ videoContainer,
+ videoElem,
+ setProgress,
+ setIsProgressDragging,
+ setTooltipStr,
+ setPreviewTooltipPosition,
);
-
- if (defaultHoverPos > modifiedUpperBound) {
- hoverPos = modifiedUpperBound - previewTooltipWidth / 2;
- }
- hoverPos = clamp(hoverPos, minHoverPos, maxHoverPos);
- setPreviewTooltipPosition(hoverPos);
-
- const leftDist = progressBarRef.current.getBoundingClientRect().left;
- const timePos = xPos - leftDist;
- if (videoElem && videoElem.duration) {
- const ratio = clamp(timePos / progressBarRef.current.clientWidth, 0, 1);
- const currentTime = videoElem.duration * ratio;
- setTooltipStr(formatTime(currentTime));
- }
}
// Handles play state when progress bar is being dragged
@@ -147,13 +87,14 @@ function ProgressBars({ item }: ProgressBarsProps) {
return (
{
setIsHovered(true);
- barMouseEvent(
+ barMouseDown(
e,
- handleProgressMouseMove,
+ handleProgressBarMouseMoveWrapper,
videoContainer,
setIsProgressDragging,
true,
@@ -161,12 +102,22 @@ function ProgressBars({ item }: ProgressBarsProps) {
}}
onTouchEnd={() => setIsHovered(false)}
onMouseEnter={() => setIsHovered(true)}
- onMouseMove={handleMouseMove}
+ onMouseMove={(e) =>
+ showPreviewThumbnail(
+ e,
+ isProgressDragging,
+ progressBarRef,
+ videoContainer,
+ videoElem,
+ setTooltipStr,
+ setPreviewTooltipPosition,
+ )
+ }
onMouseLeave={() => setIsHovered(false)}
onMouseDown={(e) =>
- barMouseEvent(
+ barMouseDown(
e,
- handleProgressMouseMove,
+ handleProgressBarMouseMoveWrapper,
videoContainer,
setIsProgressDragging,
false,
@@ -209,11 +160,14 @@ function ProgressBars({ item }: ProgressBarsProps) {
);
}
-const ProgressBarContainer = styled.div<{ isDragging: boolean }>`
+const ProgressBarContainer = styled.div<{
+ isDragging: boolean;
+ onTop: boolean;
+}>`
height: 100%;
width: 100%;
display: flex;
- align-items: center;
+ align-items: ${(props) => (props.onTop ? 'flex-end' : 'center')};
cursor: ${(props) => (props.isDragging ? 'col-resize' : 'pointer')};
`;
diff --git a/packages/custoplayer/src/lib/components/VolumeButtons.tsx b/packages/custoplayer/src/lib/components/VolumeButtons.tsx
index 3d56450..7d7b960 100644
--- a/packages/custoplayer/src/lib/components/VolumeButtons.tsx
+++ b/packages/custoplayer/src/lib/components/VolumeButtons.tsx
@@ -12,12 +12,12 @@ import {
volumeAtom,
} from '@root/lib/atoms';
import {
- barMouseEvent,
clamp,
BarMouseEvent,
isTouchscreenFunc,
isMouseFunc,
isTouchscreen,
+ barMouseDown,
} from '@root/lib/utils';
import VolumeBars from './VolumeBars';
import { motion, AnimatePresence } from 'framer-motion';
@@ -170,7 +170,7 @@ function VolumeButtons({ item }: VolumeButtonsProps) {
onMouseEnter={() => setIsBarHovered(true)}
onMouseLeave={() => setIsBarHovered(false)}
onMouseDown={(e) =>
- barMouseEvent(
+ barMouseDown(
e,
handleProgressMouse,
videoContainer,
@@ -180,7 +180,7 @@ function VolumeButtons({ item }: VolumeButtonsProps) {
}
onTouchStart={(e) => {
setIsBarHovered(true);
- barMouseEvent(
+ barMouseDown(
e,
handleProgressMouse,
videoContainer,
diff --git a/packages/custoplayer/src/lib/types.ts b/packages/custoplayer/src/lib/types.ts
index f7088da..efe0f95 100644
--- a/packages/custoplayer/src/lib/types.ts
+++ b/packages/custoplayer/src/lib/types.ts
@@ -45,6 +45,13 @@ export interface CustoplayerValues {
animate: "movement"
} */
controlsBar?: ControlsBarItem;
+ /** You can define your progress bar to be on top of your controls bar here:
+ @example
+ topProgressBar: {
+ id: 'progressBar1',
+ progressColor: 'rgb(137, 178, 245)'
+ } */
+ topProgressBar?: ProgressBarItem;
// playIndicator?: {
// id?: number;
// color?: string;
@@ -76,7 +83,8 @@ export interface CustoplayerValues {
@example
item3: {
id: 'progressBar1',
- progressColor: 'rgb(137, 178, 245)'
+ progressColor: 'rgb(137, 178, 245)',
+ barColor: "white"
} */
item3?: CustoplayerItem;
/** You can define a component in this item container. This container is the fourth container from the left.
diff --git a/packages/custoplayer/src/lib/utils.tsx b/packages/custoplayer/src/lib/utils.tsx
index 6e19ed4..ccb942c 100644
--- a/packages/custoplayer/src/lib/utils.tsx
+++ b/packages/custoplayer/src/lib/utils.tsx
@@ -7,7 +7,7 @@ import {
VolumeItem,
} from '@root/lib/types';
import { SetStateAction } from 'react';
-import { isVolumeDraggingType } from '@root/lib/atoms';
+import { isVolumeDraggingType, previewTooltipWidth } from '@root/lib/atoms';
import Color from 'color';
export const debounce = (fn: (...args: any[]) => void, ms = 300) => {
@@ -79,6 +79,11 @@ export function isFullscreenButton(
return (curItem as FullscreenItem).id.startsWith('fullscreenButton');
}
+/**
+ Changes the play state of the video.
+ This is ran when the user clicks the video
+ or presses the spacebar or k key
+*/
export function handlePlayState(video: HTMLVideoElement | null) {
if (video === null) return;
const isPlaying = !video.paused && !video.ended && video.currentTime > 0;
@@ -116,18 +121,9 @@ export function handleKeyPress(
}
}
-export function getSvgPath(path: string, strokeWidth = '1.8') {
- return (
-
- );
-}
-
+/**
+ Clamps val in between min and max
+*/
export function clamp(val: number, min: number, max: number) {
return Math.min(Math.max(val, min), max);
}
@@ -154,7 +150,14 @@ function getMousePos(
}
}
-export function barMouseEvent(
+/**
+ Runs when the user mousedown/touchstart on the
+ progress or volume bar.
+
+ The function runs sthe mouseMoveCallback function
+ when the mouse moves while the mouse is down as well
+*/
+export function barMouseDown(
e: BarMouseEvent,
mouseMoveCallback: MouseMoveCallback,
videoContainer: HTMLDivElement | null,
@@ -192,6 +195,117 @@ export function barMouseEvent(
}
}
+export function handleProgressBarMouseMove(
+ e: BarMouseEvent,
+ videoContainerRect: DOMRect,
+ isProgressDragging: boolean,
+ progressBarRef: React.MutableRefObject,
+ videoContainer: HTMLDivElement | null,
+ videoElem: HTMLVideoElement | null,
+ setProgress: (update: SetStateAction) => void,
+ setIsProgressDragging: (update: SetStateAction) => void,
+ setTooltipStr: (update: SetStateAction) => void,
+ setPreviewTooltipPosition: (update: SetStateAction) => void,
+) {
+ setIsProgressDragging(true);
+ if (progressBarRef && progressBarRef.current) {
+ let xPos = 0;
+ if (isTouchscreenFunc(e)) xPos = e.touches[0].clientX;
+ else if (isMouseFunc(e)) xPos = e.clientX;
+ const progressBarRect = progressBarRef.current.getBoundingClientRect();
+ const [largestProgressBarMousePos, distLeftOfProgressBar, _] =
+ getLargestProgressBarMousePos(videoContainerRect, progressBarRect);
+
+ const updatedMousePos = xPos - videoContainerRect.left;
+
+ showPreviewThumbnail(
+ e,
+ isProgressDragging,
+ progressBarRef,
+ videoContainer,
+ videoElem,
+ setTooltipStr,
+ setPreviewTooltipPosition,
+ );
+ const adjustedMousePos = updatedMousePos - distLeftOfProgressBar;
+ const clampedMousePos = clamp(
+ adjustedMousePos,
+ 0,
+ largestProgressBarMousePos,
+ );
+
+ const ratio = clampedMousePos / progressBarRef.current.clientWidth;
+ if (videoElem && videoElem.duration) {
+ const currentTime = videoElem.duration * ratio;
+ videoElem.currentTime = currentTime;
+ setTooltipStr(formatTime(currentTime));
+ }
+
+ setProgress(ratio);
+ }
+}
+
+/**
+ Shows the preview thumbnail when mouse is over progress bar
+*/
+export function showPreviewThumbnail(
+ e: BarMouseEvent,
+ isProgressDragging: boolean,
+ progressBarRef: React.MutableRefObject,
+ videoContainer: HTMLDivElement | null,
+ videoElem: HTMLVideoElement | null,
+ setTooltipStr: (update: SetStateAction) => void,
+ setPreviewTooltipPosition: (update: SetStateAction) => void,
+) {
+ if (
+ isProgressDragging ||
+ !progressBarRef ||
+ !progressBarRef.current ||
+ !videoContainer
+ )
+ return;
+ let xPos = 0;
+ if (isTouchscreenFunc(e)) xPos = e.touches[0].clientX;
+ else if (isMouseFunc(e)) xPos = e.clientX;
+ const progressBarRect = progressBarRef.current.getBoundingClientRect();
+ const widthOfItemsToLeftOfProgressBar =
+ progressBarRef.current.getBoundingClientRect().left -
+ videoContainer?.getBoundingClientRect().left;
+ const widthOfItemsToRightOfProgressBar =
+ videoContainer?.getBoundingClientRect().right -
+ progressBarRef.current.getBoundingClientRect().right;
+ const defaultHoverPos = xPos - progressBarRect.left;
+ let hoverPos = xPos - progressBarRect.left - previewTooltipWidth / 2;
+ const modifiedUpperBound =
+ progressBarRef.current?.clientWidth -
+ previewTooltipWidth / 2 +
+ widthOfItemsToRightOfProgressBar;
+ const maxHoverPos =
+ progressBarRef.current.clientWidth - previewTooltipWidth / 2;
+ const minHoverPos = Math.max(
+ (-1 * previewTooltipWidth) / 2,
+ -1 * widthOfItemsToLeftOfProgressBar,
+ );
+
+ if (defaultHoverPos > modifiedUpperBound) {
+ hoverPos = modifiedUpperBound - previewTooltipWidth / 2;
+ }
+ hoverPos = clamp(hoverPos, minHoverPos, maxHoverPos);
+ setPreviewTooltipPosition(hoverPos);
+
+ const leftDist = progressBarRef.current.getBoundingClientRect().left;
+ const timePos = xPos - leftDist;
+ if (videoElem && videoElem.duration) {
+ const ratio = clamp(timePos / progressBarRef.current.clientWidth, 0, 1);
+ const currentTime = videoElem.duration * ratio;
+ setTooltipStr(formatTime(currentTime));
+ }
+}
+
+/**
+ Formats time for currentTime and duration components.
+ ex: 120 -> 2:00
+*/
export function formatTime(durationInSeconds: number) {
const hours = Math.floor(durationInSeconds / 3600);
const minutes = Math.floor((durationInSeconds - hours * 3600) / 60);
@@ -252,12 +366,22 @@ export function getLargestProgressBarMousePos(
];
}
+/**
+ Used to determine if the device is a
+ touchscreen by checking if TouchEvent
+ exists
+*/
export function isTouchscreenFunc(
event: BarMouseEvent,
): event is React.TouchEvent {
return (event as React.TouchEvent).touches !== undefined;
}
+/**
+ Used to determine if the device is not a
+ touchscreen by checking if MouseEvent
+ exists
+*/
export function isMouseFunc(
event: BarMouseEvent,
): event is React.MouseEvent {
@@ -272,6 +396,10 @@ export function isTouchscreen() {
return false;
}
+/**
+ Lightens a color by using the Color.js library
+ Used for setting default progressColor on progressBar
+*/
export function lightenColor(color: string | undefined) {
const lightenedColor = Color(color).lighten(0.3);
return lightenedColor;
diff --git a/sites/custoplayer-docs/docs/components/progress-bars.mdx b/sites/custoplayer-docs/docs/components/progress-bars.mdx
index 4a9aa48..6572bcd 100644
--- a/sites/custoplayer-docs/docs/components/progress-bars.mdx
+++ b/sites/custoplayer-docs/docs/components/progress-bars.mdx
@@ -1,13 +1,24 @@
# Progress Bars
-There is currently one progress bar component
+There are currently three progress bar components
1. `"progressBar1"`
+2. `"progressBar2"`
+3. `"progressBar3"`
## Demo of `progressBar1`
+## Demo of `progressBar2`
+
+
+
+## Demo of `progressBar3`
+
+
+
+
## Usage
```jsx
item1: {
@@ -15,17 +26,42 @@ item1: {
progressColor: '#a4c3f5',
scrubberColor: "#a4c3f5",
scrubberBorderColor: "white",
-},
+ bufferedColor: "#B7B7B7"
+}
```
* The `"progressColor"` property changes the color of the progress in the progress bar
* Accepts any hex or rgb color code
+
* The `scrubberColor` property changes the color of the scrubber (the circle at the end of the progress).
* Accepts any hex or rgb color code
- * If no `scrubberColor` is defined, the `scrubberColor` is defaulted to the same as the `progressColor`
+ * If no `scrubberColor` is defined, the `scrubberColor` is defaulted to the
+ same as the `progressColor`
-* The `scrubberBorder` property changes the border color of the scrubber (the circle at the end of the progress).
+* The `scrubberBorderColor` property changes the border color of the scrubber (the circle at the end of the progress).
* Accepts any hex or rgb color code
* If no `scrubberBorderColor` is defined, the `scrubberBorderColor` is defaulted to a lightened version of the `scrubberColor`
+* The `bufferedColor` property changes the color of the buffered part of the progress bar (the content that is already loaded).
+ * Accepts any hex or rgb color code
+
* The `hideOnMobile` property hides the progressBar component when the video's width is less than 768px.
* Accepts values of `true` or `false`
+
+
+# Top Progress Bar
+
+Instead of putting the progress bar in the controls bar, it can be put above the controls bar. This is a good way of saving space in the controls bar.
+
+## Demo of `topProgressBar`
+
+
+## Usage
+```jsx
+topProgressBar: {
+ id: 'progressBar1',
+ progressColor: '#a4c3f5',
+ scrubberColor: "#a4c3f5",
+ scrubberBorderColor: "white",
+ bufferedColor: "#B7B7B7"
+}
+```
]