mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-04-14 04:50:26 +00:00
DiscreteSelectInput component implemented
This commit is contained in:
parent
4e28aebc33
commit
bd428e3ec1
5 changed files with 123 additions and 86 deletions
|
|
@ -0,0 +1,45 @@
|
|||
const React = require('react');
|
||||
const PropTypes = require('prop-types');
|
||||
const classnames = require('classnames');
|
||||
const Icon = require('stremio-icons/dom');
|
||||
const { Button } = require('stremio/common');
|
||||
const styles = require('./styles');
|
||||
|
||||
const DiscreteSelectInput = ({ className, value, label, disabled, dataset, onChange }) => {
|
||||
const buttonOnClick = React.useCallback((event) => {
|
||||
if (typeof onChange === 'function') {
|
||||
onChange({
|
||||
type: 'change',
|
||||
value: event.currentTarget.dataset.type,
|
||||
dataset: dataset,
|
||||
reactEvent: event,
|
||||
nativeEvent: event.nativeEvent
|
||||
});
|
||||
}
|
||||
}, [dataset, onChange]);
|
||||
return (
|
||||
<div className={classnames(className, styles['discrete-input-container'], { 'disabled': disabled })}>
|
||||
<div className={styles['header']}>{label}</div>
|
||||
<div className={styles['input-container']} title={disabled ? `${label} is not configurable` : null}>
|
||||
<Button className={classnames(styles['button-container'], { 'disabled': disabled })} data-type={'decrement'} onClick={buttonOnClick}>
|
||||
<Icon className={styles['icon']} icon={'ic_minus'} />
|
||||
</Button>
|
||||
<div className={styles['option-label']} title={value}>{value}</div>
|
||||
<Button className={classnames(styles['button-container'], { 'disabled': disabled })} data-type={'increment'} onClick={buttonOnClick}>
|
||||
<Icon className={styles['icon']} icon={'ic_plus'} />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
DiscreteSelectInput.propTypes = {
|
||||
className: PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
label: PropTypes.string,
|
||||
disabled: PropTypes.bool,
|
||||
dataset: PropTypes.object,
|
||||
onChange: PropTypes.func
|
||||
};
|
||||
|
||||
module.exports = DiscreteSelectInput;
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
const DiscreteSelectInput = require('./DiscreteSelectInput');
|
||||
|
||||
module.exports = DiscreteSelectInput;
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
@import (reference) '~stremio-colors/dist/less/stremio-colors.less';
|
||||
|
||||
.discrete-input-container {
|
||||
&:global(.disabled) {
|
||||
.header {
|
||||
color: @color-surface-90;
|
||||
}
|
||||
|
||||
.input-container {
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
max-height: 2.4em;
|
||||
margin-bottom: 0.5rem;
|
||||
color: @color-surface-light5-90;
|
||||
}
|
||||
|
||||
.input-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
background: @color-background-dark1;
|
||||
|
||||
.button-container {
|
||||
flex: none;
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
padding: 1rem;
|
||||
background-color: @color-background-light2;
|
||||
|
||||
.icon {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
fill: @color-surface-light5;
|
||||
}
|
||||
}
|
||||
|
||||
.option-label {
|
||||
flex: 1;
|
||||
max-height: 2.4em;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
color: @color-surface-light5-90;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ const PropTypes = require('prop-types');
|
|||
const classnames = require('classnames');
|
||||
const Icon = require('stremio-icons/dom');
|
||||
const { Button, ColorInput } = require('stremio/common');
|
||||
const DiscreteSelectInput = require('./DiscreteSelectInput');
|
||||
const styles = require('./styles');
|
||||
|
||||
const SUBTITLES_SIZES = [75, 100, 125, 150, 175, 200, 250];
|
||||
|
|
@ -57,11 +58,6 @@ const SubtitlesPicker = (props) => {
|
|||
:
|
||||
[];
|
||||
}, [props.tracks, selectedLanguage]);
|
||||
const offsetDisabled = React.useMemo(() => {
|
||||
return typeof selectedLanguage !== 'string' ||
|
||||
props.offset === null ||
|
||||
isNaN(props.offset);
|
||||
}, [selectedLanguage, props.offset]);
|
||||
const onMouseDown = React.useCallback((event) => {
|
||||
event.nativeEvent.subtitlesPickerClosePrevented = true;
|
||||
}, []);
|
||||
|
|
@ -81,9 +77,10 @@ const SubtitlesPicker = (props) => {
|
|||
const trackOnClick = React.useCallback((event) => {
|
||||
props.onTrackSelected(event.currentTarget.dataset.trackId);
|
||||
}, [props.onTrackSelected]);
|
||||
const onOffsetButtonClicked = React.useCallback((event) => {
|
||||
const onOffsetChange = React.useCallback((event) => {
|
||||
if (props.offset !== null && !isNaN(props.offset)) {
|
||||
const offset = props.offset + parseInt(event.currentTarget.dataset.offset);
|
||||
const delta = event.value === 'increment' ? 1 : -1;
|
||||
const offset = props.offset + delta;
|
||||
if (typeof props.onOffsetChanged === 'function') {
|
||||
props.onOffsetChanged(offset);
|
||||
}
|
||||
|
|
@ -143,38 +140,25 @@ const SubtitlesPicker = (props) => {
|
|||
</div>
|
||||
<div className={styles['subtitles-settings-container']}>
|
||||
<div className={styles['settings-header']}>Settings</div>
|
||||
<div className={styles['option-header']}>Delay</div>
|
||||
<div className={styles['option-container']}>
|
||||
<Button className={styles['button-container']}>
|
||||
<Icon className={styles['icon']} icon={'ic_minus'} />
|
||||
</Button>
|
||||
<div className={styles['option-label']} title={'150s'}>150s</div>
|
||||
<Button className={styles['button-container']}>
|
||||
<Icon className={styles['icon']} icon={'ic_plus'} />
|
||||
</Button>
|
||||
</div>
|
||||
<div className={styles['option-header']}>Size</div>
|
||||
<div className={styles['option-container']}>
|
||||
<Button className={styles['button-container']}>
|
||||
<Icon className={styles['icon']} icon={'ic_minus'} />
|
||||
</Button>
|
||||
<div className={styles['option-label']} title={'100%'}>100%</div>
|
||||
<Button className={styles['button-container']}>
|
||||
<Icon className={styles['icon']} icon={'ic_plus'} />
|
||||
</Button>
|
||||
</div>
|
||||
<div className={classnames(styles['option-header'], { 'disabled': offsetDisabled })}>Vertical position</div>
|
||||
<div className={classnames(styles['option-container'], { 'disabled': offsetDisabled })} title={offsetDisabled ? 'Vertical position is not configurable' : null}>
|
||||
<Button className={classnames(styles['button-container'], { 'disabled': offsetDisabled })} data-offset={-1} onClick={onOffsetButtonClicked}>
|
||||
<Icon className={styles['icon']} icon={'ic_minus'} />
|
||||
</Button>
|
||||
<div className={styles['option-label']} title={props.offset !== null && !isNaN(props.offset) ? `${props.offset}%` : null}>
|
||||
{props.offset !== null && !isNaN(props.offset) ? `${props.offset}%` : '--'}
|
||||
</div>
|
||||
<Button className={classnames(styles['button-container'], { 'disabled': offsetDisabled })} data-offset={1} onClick={onOffsetButtonClicked}>
|
||||
<Icon className={styles['icon']} icon={'ic_plus'} />
|
||||
</Button>
|
||||
</div>
|
||||
<DiscreteSelectInput
|
||||
className={styles['discrete-input']}
|
||||
label={'Delay'}
|
||||
value={props.delay !== null && !isNaN(props.delay) ? `${props.delay}ms` : '--'}
|
||||
disabled={typeof selectedLanguage !== 'string' || props.delay === null || isNaN(props.delay)}
|
||||
/>
|
||||
<DiscreteSelectInput
|
||||
className={styles['discrete-input']}
|
||||
label={'Size'}
|
||||
value={props.size !== null && !isNaN(props.size) ? `${props.size}ms` : '--'}
|
||||
disabled={typeof selectedLanguage !== 'string' || props.size === null || isNaN(props.size)}
|
||||
/>
|
||||
<DiscreteSelectInput
|
||||
className={styles['discrete-input']}
|
||||
label={'Vertical position'}
|
||||
value={props.offset !== null && !isNaN(props.offset) ? `${props.offset}%` : '--'}
|
||||
disabled={typeof selectedLanguage !== 'string' || props.offset === null || isNaN(props.offset)}
|
||||
onChange={onOffsetChange}
|
||||
/>
|
||||
<div className={styles['spacing']} />
|
||||
<Button className={styles['advanced-button']}>Advanced</Button>
|
||||
</div>
|
||||
|
|
@ -192,7 +176,7 @@ SubtitlesPicker.propTypes = {
|
|||
selectedTrackId: PropTypes.string,
|
||||
offset: PropTypes.number,
|
||||
size: PropTypes.number,
|
||||
felay: PropTypes.number,
|
||||
delay: PropTypes.number,
|
||||
textColor: PropTypes.string,
|
||||
backgroundColor: PropTypes.string,
|
||||
outlineColor: PropTypes.string,
|
||||
|
|
|
|||
|
|
@ -92,53 +92,9 @@
|
|||
flex: 1;
|
||||
}
|
||||
|
||||
.option-header {
|
||||
flex: none;
|
||||
align-self: stretch;
|
||||
max-height: 2.4em;
|
||||
margin: 0 3rem;
|
||||
color: @color-surface-light5-90;
|
||||
.discrete-input {
|
||||
margin: 0 3rem 1rem;
|
||||
|
||||
&:global(.disabled) {
|
||||
color: @color-surface-90;
|
||||
}
|
||||
}
|
||||
|
||||
.option-container {
|
||||
flex: none;
|
||||
align-self: stretch;
|
||||
margin: 0.5rem 3rem 1rem;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
background: @color-background-dark1;
|
||||
|
||||
&:global(.disabled) {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.button-container {
|
||||
flex: none;
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
padding: 1rem;
|
||||
background-color: @color-background-light2;
|
||||
|
||||
.icon {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
fill: @color-surface-light5;
|
||||
}
|
||||
}
|
||||
|
||||
.option-label {
|
||||
flex: 1;
|
||||
max-height: 2.4em;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
color: @color-surface-light5-90;
|
||||
}
|
||||
}
|
||||
|
||||
.advanced-button {
|
||||
|
|
|
|||
Loading…
Reference in a new issue