pl-fe: Allow adjusting interface size
Signed-off-by: Nicole Mikołajczyk <git@mkljczk.pl>
This commit is contained in:
@@ -59,12 +59,15 @@ const Avatar = (props: IAvatar) => {
|
||||
}).catch(() => setColor(undefined));
|
||||
}, [src, isCat]);
|
||||
|
||||
const style: React.CSSProperties = React.useMemo(() => ({
|
||||
width: size,
|
||||
height: size,
|
||||
fontSize: size,
|
||||
color,
|
||||
}), [size, color]);
|
||||
const style: React.CSSProperties = React.useMemo(() => {
|
||||
const value = `${size / 16}rem`;
|
||||
return {
|
||||
width: value,
|
||||
height: value,
|
||||
fontSize: value,
|
||||
color,
|
||||
};
|
||||
}, [size, color]);
|
||||
|
||||
if (disableUserProvidedMedia) {
|
||||
if (isAvatarMissing || !alt || isDefaultAvatar(src)) return null;
|
||||
|
||||
81
packages/pl-fe/src/components/ui/step-slider.tsx
Normal file
81
packages/pl-fe/src/components/ui/step-slider.tsx
Normal file
@@ -0,0 +1,81 @@
|
||||
import throttle from 'lodash/throttle';
|
||||
import React, { useRef } from 'react';
|
||||
|
||||
import { getPointerPosition } from 'pl-fe/features/video';
|
||||
|
||||
interface IStepSlider {
|
||||
/** Value between 0 and the amount of steps minus one. */
|
||||
value: number;
|
||||
/** Steps available in the slider. */
|
||||
steps: number;
|
||||
/** Callback when the value changes. */
|
||||
onChange(value: number): void;
|
||||
}
|
||||
|
||||
/** Slider allowing selecting integers in a given range. */
|
||||
const StepSlider: React.FC<IStepSlider> = ({ value, steps, onChange }) => {
|
||||
const node = useRef<HTMLDivElement>(null);
|
||||
|
||||
const handleMouseDown: React.MouseEventHandler = e => {
|
||||
document.addEventListener('mousemove', handleMouseSlide, true);
|
||||
document.addEventListener('mouseup', handleMouseUp, true);
|
||||
document.addEventListener('touchmove', handleMouseSlide, true);
|
||||
document.addEventListener('touchend', handleMouseUp, true);
|
||||
|
||||
handleMouseSlide(e);
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
const handleMouseUp = () => {
|
||||
document.removeEventListener('mousemove', handleMouseSlide, true);
|
||||
document.removeEventListener('mouseup', handleMouseUp, true);
|
||||
document.removeEventListener('touchmove', handleMouseSlide, true);
|
||||
document.removeEventListener('touchend', handleMouseUp, true);
|
||||
};
|
||||
|
||||
const handleMouseSlide = throttle(e => {
|
||||
if (node.current) {
|
||||
const { x } = getPointerPosition(node.current, e);
|
||||
|
||||
if (!isNaN(x)) {
|
||||
let slideamt = x;
|
||||
|
||||
if (x > 1) {
|
||||
slideamt = 1;
|
||||
} else if (x < 0) {
|
||||
slideamt = 0;
|
||||
}
|
||||
|
||||
slideamt = Math.floor((slideamt + 0.5 / steps) * (steps - 1));
|
||||
onChange(slideamt);
|
||||
}
|
||||
}
|
||||
}, 60);
|
||||
|
||||
return (
|
||||
<div
|
||||
className='relative inline-flex h-6 cursor-pointer transition'
|
||||
onMouseDown={handleMouseDown}
|
||||
ref={node}
|
||||
>
|
||||
<div className='absolute top-1/2 h-1 w-full -translate-y-1/2 rounded-full bg-primary-200 dark:bg-primary-700' />
|
||||
<div className='absolute top-1/2 h-1 -translate-y-1/2 rounded-full bg-accent-500' style={{ width: `${value / (steps - 1) * 100}%` }} />
|
||||
{[...Array(steps).fill(undefined)].map((_, step) => (
|
||||
<span
|
||||
key={step}
|
||||
className='absolute top-1/2 z-10 h-3 w-1 -translate-y-1/2 bg-accent-300'
|
||||
style={{ left: `${(step) / (steps - 1) * 100}%` }}
|
||||
/>
|
||||
))}
|
||||
<span
|
||||
className='absolute top-1/2 z-10 -ml-1.5 size-3 -translate-y-1/2 rounded-full bg-accent-500 shadow'
|
||||
tabIndex={0}
|
||||
style={{ left: `${value / (steps - 1) * 100}%` }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export { StepSlider as default };
|
||||
Reference in New Issue
Block a user