mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-04-20 23:12:13 +00:00
Seasons bar uses multiselect instead of Popup
This commit is contained in:
parent
cf9423cd7a
commit
6f86c105e5
2 changed files with 85 additions and 84 deletions
|
|
@ -2,77 +2,72 @@ const React = require('react');
|
|||
const PropTypes = require('prop-types');
|
||||
const classnames = require('classnames');
|
||||
const Icon = require('stremio-icons/dom');
|
||||
const { Button, Popup, useBinaryState } = require('stremio/common');
|
||||
const { Button, Multiselect } = require('stremio/common');
|
||||
const styles = require('./styles');
|
||||
|
||||
const SeasonsBar = ({ className, season, seasons, onSeasonChange }) => {
|
||||
const [menuOpen, openMenu, closeMenu, toggleMenu] = useBinaryState(false);
|
||||
const setPrevSeason = React.useCallback(() => {
|
||||
if (Array.isArray(seasons) && typeof onSeasonChange === 'function') {
|
||||
const SeasonsBar = ({ className, season, seasons, onSelect }) => {
|
||||
const options = React.useMemo(() => {
|
||||
return Array.isArray(seasons) ?
|
||||
seasons.map((season) => ({
|
||||
value: String(season),
|
||||
label: `Season ${season}`
|
||||
}))
|
||||
:
|
||||
[];
|
||||
}, [seasons]);
|
||||
const selected = React.useMemo(() => {
|
||||
return [String(season)];
|
||||
}, [season]);
|
||||
const renderMultiselectLabelText = React.useMemo(() => {
|
||||
return () => `Season ${season}`;
|
||||
}, [season]);
|
||||
const prevNextButtonOnClick = React.useCallback((event) => {
|
||||
if (Array.isArray(seasons) && typeof onSelect === 'function') {
|
||||
const seasonIndex = seasons.indexOf(season);
|
||||
if (seasonIndex > 0) {
|
||||
onSeasonChange(seasons[seasonIndex - 1]);
|
||||
}
|
||||
const valueIndex = event.currentTarget.dataset.action === 'next' ?
|
||||
seasonIndex + 1
|
||||
:
|
||||
seasonIndex - 1;
|
||||
const value = valueIndex >= 0 && valueIndex < seasons.length ?
|
||||
seasons[valueIndex]
|
||||
:
|
||||
seasons[0];
|
||||
onSelect({
|
||||
type: 'select',
|
||||
value: value,
|
||||
reactEvent: event,
|
||||
nativeEvent: event.nativeEvent
|
||||
});
|
||||
}
|
||||
}, [season, seasons, onSeasonChange]);
|
||||
const setNextSeason = React.useCallback(() => {
|
||||
if (Array.isArray(seasons) && typeof onSeasonChange === 'function') {
|
||||
const seasonIndex = seasons.indexOf(season);
|
||||
if (seasonIndex < seasons.length - 1) {
|
||||
onSeasonChange(seasons[seasonIndex + 1]);
|
||||
}
|
||||
}, [season, seasons, onSelect]);
|
||||
const seasonOnSelect = React.useCallback((event) => {
|
||||
const value = parseInt(event.value);
|
||||
if (!isNaN(value) && typeof onSelect === 'function') {
|
||||
onSelect({
|
||||
type: 'select',
|
||||
value: value,
|
||||
reactEvent: event.reactEvent,
|
||||
nativeEvent: event.nativeEvent
|
||||
});
|
||||
}
|
||||
}, [season, seasons, onSeasonChange]);
|
||||
const seasonOnClick = React.useCallback((event) => {
|
||||
closeMenu();
|
||||
const season = parseInt(event.currentTarget.dataset.season);
|
||||
if (!isNaN(season) && typeof onSeasonChange === 'function') {
|
||||
onSeasonChange(season);
|
||||
}
|
||||
}, [onSeasonChange]);
|
||||
}, [onSelect]);
|
||||
return (
|
||||
<div className={classnames(className, styles['seasons-bar-container'])}>
|
||||
<Button className={styles['prev-season-button']} onClick={setPrevSeason}>
|
||||
<Button className={styles['prev-season-button']} data-action={'prev'} onClick={prevNextButtonOnClick}>
|
||||
<Icon className={styles['icon']} icon={'ic_arrow_left'} />
|
||||
</Button>
|
||||
<Popup
|
||||
open={menuOpen}
|
||||
menuMatchLabelWidth={true}
|
||||
onCloseRequest={closeMenu}
|
||||
renderLabel={(ref) => (
|
||||
<Button ref={ref} className={classnames(styles['seasons-popup-label-container'], { 'active': menuOpen })} title={season !== null && !isNaN(season) ? `Season ${season}` : 'Season'} onClick={toggleMenu}>
|
||||
<div className={styles['season-label']}>Season</div>
|
||||
{
|
||||
season !== null && !isNaN(season) ?
|
||||
<div className={styles['number-label']}>{season}</div>
|
||||
:
|
||||
null
|
||||
}
|
||||
</Button>
|
||||
)}
|
||||
renderMenu={() => (
|
||||
<div className={styles['seasons-menu-container']}>
|
||||
{
|
||||
Array.isArray(seasons) ?
|
||||
seasons.map((season) => (
|
||||
<Button key={season} className={styles['season-option-container']} data-season={season} title={season !== null && !isNaN(season) ? `Season ${season}` : 'Season'} onClick={seasonOnClick}>
|
||||
<div className={styles['season-label']}>Season</div>
|
||||
{
|
||||
season !== null && !isNaN(season) ?
|
||||
<div className={styles['number-label']}>{season}</div>
|
||||
:
|
||||
null
|
||||
}
|
||||
</Button>
|
||||
))
|
||||
:
|
||||
null
|
||||
}
|
||||
</div>
|
||||
)}
|
||||
<Multiselect
|
||||
className={styles['seasons-popup-label-container']}
|
||||
direction={'bottom'}
|
||||
title={season !== null && !isNaN(season) ? `Season ${season}` : 'Season'}
|
||||
options={options}
|
||||
selected={selected}
|
||||
disabled={false}
|
||||
renderLabelText={renderMultiselectLabelText}
|
||||
onSelect={seasonOnSelect}
|
||||
/>
|
||||
<Button className={styles['next-season-button']} onClick={setNextSeason}>
|
||||
<Icon className={styles['icon']} icon={'ic_arrow_right'} />
|
||||
<Button className={styles['next-season-button']} data-action={'next'} onClick={prevNextButtonOnClick}>
|
||||
<Icon className={styseasonles['icon']} icon={'ic_arrow_right'} />
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -80,9 +75,9 @@ const SeasonsBar = ({ className, season, seasons, onSeasonChange }) => {
|
|||
|
||||
SeasonsBar.propTypes = {
|
||||
className: PropTypes.string,
|
||||
season: PropTypes.number,
|
||||
selected: PropTypes.number,
|
||||
seasons: PropTypes.arrayOf(PropTypes.number),
|
||||
onSeasonChange: PropTypes.func
|
||||
onSelect: PropTypes.func
|
||||
};
|
||||
|
||||
module.exports = SeasonsBar;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
.seasons-bar-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
overflow: visible;
|
||||
|
||||
.prev-season-button, .next-season-button {
|
||||
flex: none;
|
||||
|
|
@ -27,6 +28,7 @@
|
|||
justify-content: center;
|
||||
margin: 0 1rem;
|
||||
background-color: var(--color-surfacedarker60);
|
||||
overflow: visible;
|
||||
|
||||
&:hover, &:focus, &:global(.active) {
|
||||
background-color: var(--color-surfacedarker);
|
||||
|
|
@ -37,33 +39,37 @@
|
|||
max-width: 50%;
|
||||
max-height: 3.6em;
|
||||
padding: 0 0.2rem;
|
||||
font-size: 1.2rem;
|
||||
font-size: 1.1rem;
|
||||
color: var(--color-surfacelighter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.seasons-menu-container {
|
||||
background-color: var(--color-surfacelighter);
|
||||
.popup-menu-container {
|
||||
width: 100%;
|
||||
|
||||
.season-option-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 4rem;
|
||||
.seasons-menu-container {
|
||||
background-color: var(--color-surfacelighter);
|
||||
|
||||
&:hover, &:focus {
|
||||
outline: none;
|
||||
background-color: var(--color-surfacelight);
|
||||
}
|
||||
.season-option-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 4rem;
|
||||
|
||||
.season-label, .number-label {
|
||||
flex: none;
|
||||
max-width: 50%;
|
||||
max-height: 3.6em;
|
||||
padding: 0 0.2rem;
|
||||
font-size: 1.2rem;
|
||||
color: var(--color-backgrounddarker);
|
||||
&:hover, &:focus {
|
||||
outline: none;
|
||||
background-color: var(--color-surfacelight);
|
||||
}
|
||||
|
||||
.season-label, .number-label {
|
||||
flex: none;
|
||||
max-width: 50%;
|
||||
max-height: 3.6em;
|
||||
padding: 0 0.2rem;
|
||||
font-size: 1.2rem;
|
||||
color: var(--color-backgrounddarker);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue