mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-04-21 07:32:02 +00:00
commit
a1a06d64af
12 changed files with 226 additions and 202 deletions
|
|
@ -12,6 +12,7 @@
|
||||||
--scroll-bar-width: 6px;
|
--scroll-bar-width: 6px;
|
||||||
--focus-outline-size: 2px;
|
--focus-outline-size: 2px;
|
||||||
--color-facebook: #4267b2;
|
--color-facebook: #4267b2;
|
||||||
|
--color-twitter: #1DA1F2;
|
||||||
--color-placeholder: #60606080;
|
--color-placeholder: #60606080;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
import React, { useRef } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import classnames from 'classnames';
|
|
||||||
import { Input, Modal } from 'stremio/common';
|
|
||||||
import Icon from 'stremio-icons/dom';
|
|
||||||
import styles from './styles';
|
|
||||||
|
|
||||||
const renderInput = ({ className, href, icon, label }) => {
|
|
||||||
return (
|
|
||||||
<Input className={classnames(styles['button'], className)} type={'link'} href={href} target={'_blank'}>
|
|
||||||
<Icon className={styles['icon']} icon={icon} />{label}
|
|
||||||
</Input>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderUrl = (url) => {
|
|
||||||
const inputRef = useRef(null);
|
|
||||||
const copyToClipboard = () => {
|
|
||||||
inputRef.current.select();
|
|
||||||
document.execCommand('copy');
|
|
||||||
};
|
|
||||||
|
|
||||||
if (url.length === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={styles['url-container']}>
|
|
||||||
<input ref={inputRef} className={styles['url']} type={'text'} tabIndex={'-1'} defaultValue={url} readOnly />
|
|
||||||
<Input className={styles['copy-button']} type={'button'} onClick={copyToClipboard}>
|
|
||||||
<Icon className={styles['icon']} icon={'ic_link'} />
|
|
||||||
<div className={styles['label']}>Copy</div>
|
|
||||||
</Input>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const ShareModal = (props) => {
|
|
||||||
return (
|
|
||||||
<Modal>
|
|
||||||
<div className={styles['share-modal']}>
|
|
||||||
<Input className={styles['x-container']} type={'button'}>
|
|
||||||
<Icon className={styles['icon']} icon={'ic_x'} onClick={props.onClose} />
|
|
||||||
</Input>
|
|
||||||
<div className={styles['info-container']}>
|
|
||||||
<div className={styles['share-label']}>Share</div>
|
|
||||||
<div className={styles['buttons']}>
|
|
||||||
{renderInput({ className: styles['facebook-button'], href: `https://www.facebook.com/sharer/sharer.php?u=${props.url}`, icon: 'ic_facebook', label: 'FACEBOOK' })}
|
|
||||||
{renderInput({ className: styles['twitter-button'], href: `https://twitter.com/home?status=${props.url}`, icon: 'ic_twitter', label: 'TWITTER' })}
|
|
||||||
</div>
|
|
||||||
{renderUrl(props.url)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
ShareModal.propTypes = {
|
|
||||||
url: PropTypes.string.isRequired,
|
|
||||||
onClose: PropTypes.func
|
|
||||||
};
|
|
||||||
ShareModal.defaultProps = {
|
|
||||||
url: ''
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ShareModal;
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
import ShareModal from './ShareModal';
|
|
||||||
|
|
||||||
export default ShareModal;
|
|
||||||
|
|
@ -1,131 +0,0 @@
|
||||||
.share-modal {
|
|
||||||
--share-modal-width: 350px;
|
|
||||||
--spacing: 20px;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.share-modal {
|
|
||||||
padding: calc(var(--spacing) * 0.5);
|
|
||||||
width: var(--share-modal-width);
|
|
||||||
color: var(--color-surfacelighter);
|
|
||||||
background-color: var(--color-surfacelighter);
|
|
||||||
|
|
||||||
.x-container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: flex-end;
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
padding: 0.2em;
|
|
||||||
width: 1.2em;
|
|
||||||
height: 1.2em;
|
|
||||||
fill: var(--color-surfacedark);
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
fill: var(--color-surface);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
.icon {
|
|
||||||
background-color: var(--color-surfacelight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
.icon {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-container {
|
|
||||||
padding: 0 var(--spacing) calc(var(--spacing) * 1.2) var(--spacing);
|
|
||||||
|
|
||||||
.share-label {
|
|
||||||
font-size: 1.1em;
|
|
||||||
color: var(--color-backgrounddarker);
|
|
||||||
}
|
|
||||||
|
|
||||||
.buttons {
|
|
||||||
padding: var(--spacing) 0;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
|
|
||||||
.button {
|
|
||||||
flex: 1;
|
|
||||||
height: 3.2em;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
font-size: 0.8em;
|
|
||||||
color: var(--color-surfacelighter);
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
margin-right: 0.6em;
|
|
||||||
width: 1.4em;
|
|
||||||
height: 1.4em;
|
|
||||||
fill: var(--color-surfacelighter);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus, &:hover {
|
|
||||||
filter: brightness(1.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(:last-child) {
|
|
||||||
margin-right: 2em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.facebook-button {
|
|
||||||
background-color: var(--color-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.twitter-button {
|
|
||||||
background-color: var(--color-secondarylighter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.url-container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
border: calc(var(--focusable-border-size) * 0.5) solid var(--color-surface);
|
|
||||||
|
|
||||||
.url {
|
|
||||||
flex: 4;
|
|
||||||
padding: calc(var(--spacing) * 0.5);
|
|
||||||
font-size: 0.9em;
|
|
||||||
text-align: center;
|
|
||||||
color: var(--color-surfacedark);
|
|
||||||
}
|
|
||||||
|
|
||||||
.copy-button {
|
|
||||||
flex: 1;
|
|
||||||
padding: calc(var(--spacing) * 0.5);
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: center;
|
|
||||||
background-color: var(--color-surface);
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
margin-right: 0.4em;
|
|
||||||
width: 1em;
|
|
||||||
height: 1em;
|
|
||||||
fill: var(--color-surfacedarker);
|
|
||||||
}
|
|
||||||
|
|
||||||
.label {
|
|
||||||
color: var(--color-surfacedarker);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus, &:hover {
|
|
||||||
background-color: var(--color-surface60);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
66
src/common/SharePrompt/SharePrompt.js
Normal file
66
src/common/SharePrompt/SharePrompt.js
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
const React = require('react');
|
||||||
|
const PropTypes = require('prop-types');
|
||||||
|
const classnames = require('classnames');
|
||||||
|
const Icon = require('stremio-icons/dom');
|
||||||
|
const { useFocusable } = require('stremio-router');
|
||||||
|
const Button = require('stremio/common/Button');
|
||||||
|
const TextInput = require('stremio/common/TextInput');
|
||||||
|
const styles = require('./styles');
|
||||||
|
|
||||||
|
const SharePrompt = ({ className, label, url, close }) => {
|
||||||
|
const inputRef = React.useRef(null);
|
||||||
|
const focusable = useFocusable();
|
||||||
|
const copyToClipboard = React.useCallback(() => {
|
||||||
|
inputRef.current.select();
|
||||||
|
document.execCommand('copy');
|
||||||
|
}, []);
|
||||||
|
React.useEffect(() => {
|
||||||
|
const onKeyUp = (event) => {
|
||||||
|
if (event.key === 'Escape' && typeof close === 'function') {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (focusable) {
|
||||||
|
window.addEventListener('keyup', onKeyUp);
|
||||||
|
}
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('keyup', onKeyUp);
|
||||||
|
};
|
||||||
|
}, [close, focusable]);
|
||||||
|
return (
|
||||||
|
<div className={classnames(className, styles['share-prompt-container'])}>
|
||||||
|
<Button className={styles['close-button-container']}>
|
||||||
|
<Icon className={styles['icon']} icon={'ic_x'} onClick={close} />
|
||||||
|
</Button>
|
||||||
|
<div className={styles['share-prompt-content']}>
|
||||||
|
<div className={styles['share-prompt-label']}>{label}</div>
|
||||||
|
<div className={styles['buttons-container']}>
|
||||||
|
<Button className={classnames(styles['button-container'], styles['facebook-button'])} href={`https://www.facebook.com/sharer/sharer.php?u=${url}`} target={'_blank'}>
|
||||||
|
<Icon className={styles['icon']} icon={'ic_facebook'} />
|
||||||
|
<div className={styles['label']}>FACEBOOK</div>
|
||||||
|
</Button>
|
||||||
|
<Button className={classnames(styles['button-container'], styles['twitter-button'])} href={`https://twitter.com/home?status=${url}`} target={'_blank'}>
|
||||||
|
<Icon className={styles['icon']} icon={'ic_twitter'} />
|
||||||
|
<div className={styles['label']}>TWITTER</div>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className={styles['url-container']}>
|
||||||
|
<TextInput ref={inputRef} className={styles['url-content']} type={'text'} tabIndex={'-1'} defaultValue={url} readOnly />
|
||||||
|
<Button className={styles['copy-button']} onClick={copyToClipboard}>
|
||||||
|
<Icon className={styles['icon']} icon={'ic_link'} />
|
||||||
|
<div className={styles['label']}>Copy</div>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
SharePrompt.propTypes = {
|
||||||
|
className: PropTypes.string,
|
||||||
|
label: PropTypes.string.isRequired,
|
||||||
|
url: PropTypes.string.isRequired,
|
||||||
|
close: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = SharePrompt;
|
||||||
3
src/common/SharePrompt/index.js
Normal file
3
src/common/SharePrompt/index.js
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
const SharePrompt = require('./SharePrompt');
|
||||||
|
|
||||||
|
module.exports = SharePrompt;
|
||||||
134
src/common/SharePrompt/styles.less
Normal file
134
src/common/SharePrompt/styles.less
Normal file
|
|
@ -0,0 +1,134 @@
|
||||||
|
.share-prompt-container {
|
||||||
|
position: relative;
|
||||||
|
z-index: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 2.4rem 0;
|
||||||
|
background-color: var(--color-surfacelighter);
|
||||||
|
|
||||||
|
.close-button-container {
|
||||||
|
position: absolute;
|
||||||
|
top: 0.4rem;
|
||||||
|
right: 0.4rem;
|
||||||
|
z-index: 1;
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
padding: 0.4rem;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--color-surfacelight);
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
fill: var(--color-backgrounddarker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-prompt-content {
|
||||||
|
padding: 0 2.4rem;
|
||||||
|
|
||||||
|
.share-prompt-label {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
color: var(--color-backgrounddarker);
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons-container {
|
||||||
|
flex: none;
|
||||||
|
align-self: stretch;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin: 1.4rem 0;
|
||||||
|
|
||||||
|
.button-container {
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 1;
|
||||||
|
flex-basis: 14rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0.6rem 1rem;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
flex: none;
|
||||||
|
width: 1.4rem;
|
||||||
|
height: 1.4rem;
|
||||||
|
margin-right: 0.6rem;
|
||||||
|
fill: var(--color-surfacelighter);
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 1;
|
||||||
|
flex-basis: auto;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--color-surfacelighter);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover, &:focus {
|
||||||
|
filter: brightness(1.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-right: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.facebook-button {
|
||||||
|
background-color: var(--color-facebook);
|
||||||
|
}
|
||||||
|
|
||||||
|
.twitter-button {
|
||||||
|
background-color: var(--color-twitter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.url-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border: thin solid var(--color-surface);
|
||||||
|
|
||||||
|
.url-content {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 12rem;
|
||||||
|
padding: 0.6rem 1rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--color-surfacedark);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-button {
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 1;
|
||||||
|
flex-basis: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0.6rem 1rem;
|
||||||
|
background-color: var(--color-surface);
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
flex: none;
|
||||||
|
width: 1.4rem;
|
||||||
|
height: 1.4rem;
|
||||||
|
margin-right: 0.6rem;
|
||||||
|
fill: var(--color-surfacedarker);
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
color: var(--color-surfacedarker);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover, &:focus {
|
||||||
|
filter: brightness(1.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -12,7 +12,7 @@ const MetaRowPlaceholder = require('./MetaRowPlaceholder');
|
||||||
const NavBar = require('./NavBar');
|
const NavBar = require('./NavBar');
|
||||||
const PlayIconCircleCentered = require('./PlayIconCircleCentered');
|
const PlayIconCircleCentered = require('./PlayIconCircleCentered');
|
||||||
const Popup = require('./Popup');
|
const Popup = require('./Popup');
|
||||||
const ShareModal = require('./ShareModal');
|
const SharePrompt = require('./SharePrompt');
|
||||||
const Slider = require('./Slider');
|
const Slider = require('./Slider');
|
||||||
const TextInput = require('./TextInput');
|
const TextInput = require('./TextInput');
|
||||||
const routesRegexp = require('./routesRegexp');
|
const routesRegexp = require('./routesRegexp');
|
||||||
|
|
@ -37,7 +37,7 @@ module.exports = {
|
||||||
NavBar,
|
NavBar,
|
||||||
PlayIconCircleCentered,
|
PlayIconCircleCentered,
|
||||||
Popup,
|
Popup,
|
||||||
ShareModal,
|
SharePrompt,
|
||||||
Slider,
|
Slider,
|
||||||
TextInput,
|
TextInput,
|
||||||
routesRegexp,
|
routesRegexp,
|
||||||
|
|
|
||||||
14
storybook/stories/SharePrompt/SharePrompt.js
Normal file
14
storybook/stories/SharePrompt/SharePrompt.js
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
const React = require('react');
|
||||||
|
const { storiesOf } = require('@storybook/react');
|
||||||
|
const { action } = require('@storybook/addon-actions');
|
||||||
|
const { SharePrompt } = require('stremio/common');
|
||||||
|
const styles = require('./styles');
|
||||||
|
|
||||||
|
storiesOf('SharePrompt', module).add('SharePrompt', () => (
|
||||||
|
<SharePrompt
|
||||||
|
className={styles['share-prompt-container']}
|
||||||
|
label={'Demo label'}
|
||||||
|
url={'Demo url'}
|
||||||
|
close={action('Demo item closed')}
|
||||||
|
/>
|
||||||
|
));
|
||||||
1
storybook/stories/SharePrompt/index.js
Normal file
1
storybook/stories/SharePrompt/index.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
require('./SharePrompt');
|
||||||
4
storybook/stories/SharePrompt/styles.less
Normal file
4
storybook/stories/SharePrompt/styles.less
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
.share-prompt-container {
|
||||||
|
width: 24rem;
|
||||||
|
margin: 1rem;
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
require('./Addon');
|
require('./Addon');
|
||||||
require('./MetaItem');
|
require('./MetaItem');
|
||||||
require('./ColorPicker');
|
require('./ColorPicker');
|
||||||
|
require('./SharePrompt');
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue