👌 restore Console.jsx classes

This commit is contained in:
ghalestrilo 2020-07-28 10:53:28 -03:00
commit d2dcc1fee2
15 changed files with 7874 additions and 12723 deletions

View file

@ -1,64 +1,86 @@
import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router'; import { Link } from 'react-router';
import styled from 'styled-components';
import { remSize, prop, common } from '../theme';
import IconButton from './mobile/IconButton';
import Button from '../common/Button';
const DropdownWrapper = styled.ul`
background-color: ${prop('Modal.background')};
border: 1px solid ${prop('Modal.border')};
box-shadow: 0 0 18px 0 ${prop('shadowColor')};
color: ${prop('primaryTextColor')};
// <ul className="nav__dropdown"> position: absolute;
top: ${remSize(64)};
right: ${remSize(16)};
text-align: left;
width: ${remSize(180)};
display: flex;
flex-direction: column;
height: auto;
z-index: 9999;
border-radius: ${remSize(6)};
// <ul className="nav__dropdown"> & li:first-child { border-radius: ${remSize(5)} ${remSize(5)} 0 0; }
& li:last-child { border-radius: 0 0 ${remSize(5)} ${remSize(5)}; }
// <li className="nav__dropdown-item"> & li:hover {
// <button
// onFocus={this.handleFocusForLang}
// onBlur={this.handleBlur}
// value="it"
// onClick={e => this.handleLangSelection(e)}
// >
// Italian (Test Fallback)
// </button>
// </li>
// <li className="nav__dropdown-item">
// <button
// onFocus={this.handleFocusForLang}
// onBlur={this.handleBlur}
// value="en-US"
// onClick={e => this.handleLangSelection(e)}
// >English
// </button>
// </li>
// <li className="nav__dropdown-item">
// <button
// onFocus={this.handleFocusForLang}
// onBlur={this.handleBlur}
// value="es-419"
// onClick={e => this.handleLangSelection(e)}
// >
// Español
// </button>
// </li>
// </ul>
// 'nav__item--open' background-color: ${prop('Button.hover.background')};
color: ${prop('Button.hover.foreground')};
& button, & a {
color: ${prop('Button.hover.foreground')};
}
}
li {
height: ${remSize(36)};
cursor: pointer;
display: flex;
align-items: center;
& button,
& a {
color: ${prop('primaryTextColor')};
width: 100%;
text-align: left;
padding: ${remSize(8)} ${remSize(16)};
}
}
`;
// TODO: Add Icon to the left of the items in the menu
// const MaybeIcon = (Element, label) => Element && <Element aria-label={label} />;
const Dropdown = ({ items }) => ( const Dropdown = ({ items }) => (
<ul className="nav__dropdown"> <DropdownWrapper>
{items && items.map(item => ( {/* className="nav__items-left" */}
<li className="nav__dropdown-item"> {items && items.map(({ title, icon, href }) => (
<li key={`nav-${title && title.toLowerCase()}`}>
<Link to={href}>
{/* {MaybeIcon(icon, `Navigate to ${title}`)} */}
{title}
</Link>
</li> </li>
)) ))
} }
</ul> </DropdownWrapper>
); );
Dropdown.propTypes = { Dropdown.propTypes = {
items: PropTypes.arrayOf(PropTypes.shape({ items: PropTypes.arrayOf(PropTypes.shape({
action: PropTypes.func action: PropTypes.func,
})) icon: PropTypes.func,
href: PropTypes.string
})),
}; };
Dropdown.defaultProps = { Dropdown.defaultProps = {
items: [] items: [],
}; };
export default Dropdown; export default Dropdown;

View file

@ -0,0 +1,57 @@
import React, { useRef, useEffect } from 'react';
import PropTypes from 'prop-types';
import { createPortal } from 'react-dom';
import Dropdown from './Dropdown';
import { PreferencesIcon } from '../common/icons';
const OverlayManager = ({ overlay, hideOverlay }) => {
const ref = useRef({});
const handleClickOutside = ({ target }) => {
if (ref && ref.current && !ref.current.contains(target)) {
hideOverlay();
}
};
useEffect(() => {
document.addEventListener('mousedown', handleClickOutside);
return () => document.removeEventListener('mousedown', handleClickOutside);
}, [ref]);
const headerNavOptions = [
{
icon: PreferencesIcon,
title: 'Preferences',
href: '/mobile/preferences',
},
{ icon: PreferencesIcon, title: 'Examples', href: '/mobile/examples' },
{
icon: PreferencesIcon,
title: 'Original Editor',
href: '/mobile/preferences',
},
];
const jsx = (
<React.Fragment>
<div ref={(r) => { ref.current = r; }} >
{overlay === 'dropdown' && <Dropdown items={headerNavOptions} />}
</div>
</React.Fragment>
);
return jsx && createPortal(jsx, document.body);
};
OverlayManager.propTypes = {
overlay: PropTypes.string,
hideOverlay: PropTypes.func.isRequired,
};
OverlayManager.defaultProps = { overlay: null };
export default OverlayManager;

View file

@ -88,8 +88,6 @@ const Console = () => {
const cm = useRef({}); const cm = useRef({});
useDidUpdate(() => { cm.current.scrollTop = cm.current.scrollHeight; });
const consoleClass = classNames({ const consoleClass = classNames({
'preview-console': true, 'preview-console': true,
'preview-console--collapsed': !isExpanded 'preview-console--collapsed': !isExpanded

View file

@ -48,7 +48,7 @@ class NewFileForm extends React.Component {
NewFileForm.propTypes = { NewFileForm.propTypes = {
fields: PropTypes.shape({ fields: PropTypes.shape({
name: PropTypes.object.isRequired name: PropTypes.object.isRequired // eslint-disable-line
}).isRequired, }).isRequired,
handleSubmit: PropTypes.func.isRequired, handleSubmit: PropTypes.func.isRequired,
createFile: PropTypes.func.isRequired, createFile: PropTypes.func.isRequired,

View file

@ -49,7 +49,7 @@ class NewFolderForm extends React.Component {
NewFolderForm.propTypes = { NewFolderForm.propTypes = {
fields: PropTypes.shape({ fields: PropTypes.shape({
name: PropTypes.object.isRequired name: PropTypes.object.isRequired // eslint-disable-line
}).isRequired, }).isRequired,
handleSubmit: PropTypes.func.isRequired, handleSubmit: PropTypes.func.isRequired,
createFolder: PropTypes.func.isRequired, createFolder: PropTypes.func.isRequired,

View file

@ -478,7 +478,7 @@ IDEView.propTypes = {
ide: PropTypes.shape({ ide: PropTypes.shape({
isPlaying: PropTypes.bool.isRequired, isPlaying: PropTypes.bool.isRequired,
isAccessibleOutputPlaying: PropTypes.bool.isRequired, isAccessibleOutputPlaying: PropTypes.bool.isRequired,
consoleEvent: PropTypes.array, consoleEvent: PropTypes.array, // eslint-disable-line
modalIsVisible: PropTypes.bool.isRequired, modalIsVisible: PropTypes.bool.isRequired,
sidebarIsExpanded: PropTypes.bool.isRequired, sidebarIsExpanded: PropTypes.bool.isRequired,
consoleIsExpanded: PropTypes.bool.isRequired, consoleIsExpanded: PropTypes.bool.isRequired,
@ -513,7 +513,7 @@ IDEView.propTypes = {
updatedAt: PropTypes.string updatedAt: PropTypes.string
}).isRequired, }).isRequired,
editorAccessibility: PropTypes.shape({ editorAccessibility: PropTypes.shape({
lintMessages: PropTypes.array.isRequired, lintMessages: PropTypes.array.isRequired, // eslint-disable-line
}).isRequired, }).isRequired,
updateLintMessage: PropTypes.func.isRequired, updateLintMessage: PropTypes.func.isRequired,
clearLintMessage: PropTypes.func.isRequired, clearLintMessage: PropTypes.func.isRequired,

View file

@ -7,6 +7,7 @@ import styled from 'styled-components';
// Imports to be Refactored // Imports to be Refactored
import { bindActionCreators } from 'redux'; import { bindActionCreators } from 'redux';
import * as FileActions from '../actions/files'; import * as FileActions from '../actions/files';
import * as IDEActions from '../actions/ide'; import * as IDEActions from '../actions/ide';
import * as ProjectActions from '../actions/project'; import * as ProjectActions from '../actions/project';
@ -19,7 +20,7 @@ import { getHTMLFile } from '../reducers/files';
// Local Imports // Local Imports
import Editor from '../components/Editor'; import Editor from '../components/Editor';
import { PreferencesIcon, PlayIcon, ExitIcon, MoreIcon } from '../../../common/icons'; import { PlayIcon, ExitIcon, MoreIcon } from '../../../common/icons';
import IconButton from '../../../components/mobile/IconButton'; import IconButton from '../../../components/mobile/IconButton';
import Header from '../../../components/mobile/Header'; import Header from '../../../components/mobile/Header';
@ -28,7 +29,7 @@ import Footer from '../../../components/mobile/Footer';
import IDEWrapper from '../../../components/mobile/IDEWrapper'; import IDEWrapper from '../../../components/mobile/IDEWrapper';
import Console from '../components/Console'; import Console from '../components/Console';
import { remSize } from '../../../theme'; import { remSize } from '../../../theme';
import Dropdown from '../../../components/Dropdown'; import OverlayManager from '../../../components/OverlayManager';
import ActionStrip from '../../../components/mobile/ActionStrip'; import ActionStrip from '../../../components/mobile/ActionStrip';
const isUserOwner = ({ project, user }) => (project.owner && project.owner.id === user.id); const isUserOwner = ({ project, user }) => (project.owner && project.owner.id === user.id);
@ -39,15 +40,6 @@ const Expander = styled.div`
`; `;
// TODO: Move to new file?
// const overlays = {};
// const OverlayManager = name => overlays[name] || null;
const headerNavOptions = [
{ icon: PreferencesIcon, title: 'Preferences', route: '/mobile/preferences' }
];
const MobileIDEView = (props) => { const MobileIDEView = (props) => {
const { const {
preferences, ide, editorAccessibility, project, updateLintMessage, clearLintMessage, preferences, ide, editorAccessibility, project, updateLintMessage, clearLintMessage,
@ -58,9 +50,11 @@ const MobileIDEView = (props) => {
} = props; } = props;
const [tmController, setTmController] = useState(null); // eslint-disable-line const [tmController, setTmController] = useState(null); // eslint-disable-line
const [overlay, setOverlay] = useState(null); // eslint-disable-line const [overlayName, setOverlay] = useState(null); // eslint-disable-line
// const overlayActive = name => (overlay === name); // TODO: Move this to OverlayController (?)
const hideOverlay = () => setOverlay(null);
// const overlayRef = useRef({});
return ( return (
<Screen fullscreen> <Screen fullscreen>
@ -72,7 +66,6 @@ const MobileIDEView = (props) => {
} }
> >
<IconButton <IconButton
// to="/mobile/preferences"
onClick={() => setOverlay('dropdown')} onClick={() => setOverlay('dropdown')}
icon={MoreIcon} icon={MoreIcon}
aria-label="Options" aria-label="Options"
@ -116,18 +109,21 @@ const MobileIDEView = (props) => {
provideController={setTmController} provideController={setTmController}
/> />
</IDEWrapper> </IDEWrapper>
<Footer> <Footer>
{ide.consoleIsExpanded && <Expander expanded><Console /></Expander>} {ide.consoleIsExpanded && <Expander expanded><Console /></Expander>}
<ActionStrip /> <ActionStrip />
</Footer> </Footer>
{/* Overlays */} <OverlayManager
<Dropdown hidden={overlay !== 'dropdown'} items={headerNavOptions} /> // ref={overlayRef}
overlay={overlayName}
hideOverlay={hideOverlay}
/>
</Screen> </Screen>
); );
}; };
MobileIDEView.propTypes = { MobileIDEView.propTypes = {
preferences: PropTypes.shape({ preferences: PropTypes.shape({
@ -146,7 +142,7 @@ MobileIDEView.propTypes = {
ide: PropTypes.shape({ ide: PropTypes.shape({
isPlaying: PropTypes.bool.isRequired, isPlaying: PropTypes.bool.isRequired,
isAccessibleOutputPlaying: PropTypes.bool.isRequired, isAccessibleOutputPlaying: PropTypes.bool.isRequired,
consoleEvent: PropTypes.array, consoleEvent: PropTypes.arrayOf(PropTypes.shape({})),
modalIsVisible: PropTypes.bool.isRequired, modalIsVisible: PropTypes.bool.isRequired,
sidebarIsExpanded: PropTypes.bool.isRequired, sidebarIsExpanded: PropTypes.bool.isRequired,
consoleIsExpanded: PropTypes.bool.isRequired, consoleIsExpanded: PropTypes.bool.isRequired,
@ -172,7 +168,7 @@ MobileIDEView.propTypes = {
}).isRequired, }).isRequired,
editorAccessibility: PropTypes.shape({ editorAccessibility: PropTypes.shape({
lintMessages: PropTypes.array.isRequired, lintMessages: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
}).isRequired, }).isRequired,
project: PropTypes.shape({ project: PropTypes.shape({

View file

@ -8,8 +8,8 @@ import CopyableInput from '../../IDE/components/CopyableInput';
import APIKeyList from './APIKeyList'; import APIKeyList from './APIKeyList';
export const APIKeyPropType = PropTypes.shape({ export const APIKeyPropType = PropTypes.shape({
id: PropTypes.object.isRequired, id: PropTypes.object.isRequired, // eslint-disable-line
token: PropTypes.object, token: PropTypes.object, // eslint-disable-line
label: PropTypes.string.isRequired, label: PropTypes.string.isRequired,
createdAt: PropTypes.string.isRequired, createdAt: PropTypes.string.isRequired,
lastUsedAt: PropTypes.string, lastUsedAt: PropTypes.string,

View file

@ -103,10 +103,10 @@ function AccountForm(props) {
AccountForm.propTypes = { AccountForm.propTypes = {
fields: PropTypes.shape({ fields: PropTypes.shape({
username: PropTypes.object.isRequired, username: PropTypes.object.isRequired, // eslint-disable-line
email: PropTypes.object.isRequired, email: PropTypes.object.isRequired, // eslint-disable-line
currentPassword: PropTypes.object.isRequired, currentPassword: PropTypes.object.isRequired, // eslint-disable-line
newPassword: PropTypes.object.isRequired, newPassword: PropTypes.object.isRequired, // eslint-disable-line
}).isRequired, }).isRequired,
user: PropTypes.shape({ user: PropTypes.shape({
verified: PropTypes.number.isRequired, verified: PropTypes.number.isRequired,

View file

@ -44,8 +44,8 @@ function LoginForm(props) {
LoginForm.propTypes = { LoginForm.propTypes = {
fields: PropTypes.shape({ fields: PropTypes.shape({
email: PropTypes.object.isRequired, email: PropTypes.object.isRequired, // eslint-disable-line
password: PropTypes.object.isRequired password: PropTypes.object.isRequired // eslint-disable-line
}).isRequired, }).isRequired,
handleSubmit: PropTypes.func.isRequired, handleSubmit: PropTypes.func.isRequired,
validateAndLoginUser: PropTypes.func.isRequired, validateAndLoginUser: PropTypes.func.isRequired,

View file

@ -43,8 +43,8 @@ function NewPasswordForm(props) {
NewPasswordForm.propTypes = { NewPasswordForm.propTypes = {
fields: PropTypes.shape({ fields: PropTypes.shape({
password: PropTypes.object.isRequired, password: PropTypes.object.isRequired, // eslint-disable-line
confirmPassword: PropTypes.object.isRequired confirmPassword: PropTypes.object.isRequired // eslint-disable-line
}).isRequired, }).isRequired,
handleSubmit: PropTypes.func.isRequired, handleSubmit: PropTypes.func.isRequired,
updatePassword: PropTypes.func.isRequired, updatePassword: PropTypes.func.isRequired,

View file

@ -32,7 +32,7 @@ function ResetPasswordForm(props) {
ResetPasswordForm.propTypes = { ResetPasswordForm.propTypes = {
fields: PropTypes.shape({ fields: PropTypes.shape({
email: PropTypes.object.isRequired email: PropTypes.object.isRequired // eslint-disable-line
}).isRequired, }).isRequired,
handleSubmit: PropTypes.func.isRequired, handleSubmit: PropTypes.func.isRequired,
initiateResetPassword: PropTypes.func.isRequired, initiateResetPassword: PropTypes.func.isRequired,

View file

@ -71,10 +71,10 @@ function SignupForm(props) {
SignupForm.propTypes = { SignupForm.propTypes = {
fields: PropTypes.shape({ fields: PropTypes.shape({
username: PropTypes.object.isRequired, username: PropTypes.object.isRequired, // eslint-disable-line
email: PropTypes.object.isRequired, email: PropTypes.object.isRequired, // eslint-disable-line
password: PropTypes.object.isRequired, password: PropTypes.object.isRequired, // eslint-disable-line
confirmPassword: PropTypes.object.isRequired confirmPassword: PropTypes.object.isRequired // eslint-disable-line
}).isRequired, }).isRequired,
handleSubmit: PropTypes.func.isRequired, handleSubmit: PropTypes.func.isRequired,
signUpUser: PropTypes.func.isRequired, signUpUser: PropTypes.func.isRequired,

View file

@ -41,7 +41,8 @@ export const grays = {
}; };
export const common = { export const common = {
baseFontSize: 12 baseFontSize: 12,
shadowColor: 'rgba(0, 0, 0, 0.16)'
}; };
export const remSize = size => `${size / common.baseFontSize}rem`; export const remSize = size => `${size / common.baseFontSize}rem`;
@ -97,6 +98,10 @@ export default {
border: grays.middleLight, border: grays.middleLight,
}, },
}, },
Modal: {
background: grays.light,
border: grays.middleLight
},
Separator: grays.middleLight, Separator: grays.middleLight,
}, },
[Theme.dark]: { [Theme.dark]: {
@ -138,6 +143,10 @@ export default {
border: grays.middleDark, border: grays.middleDark,
}, },
}, },
Modal: {
background: grays.dark,
border: grays.middleDark
},
Separator: grays.middleDark, Separator: grays.middleDark,
}, },
[Theme.contrast]: { [Theme.contrast]: {
@ -179,6 +188,10 @@ export default {
border: grays.middleDark, border: grays.middleDark,
}, },
}, },
Modal: {
background: grays.dark,
border: grays.middleDark
},
Separator: grays.middleDark, Separator: grays.middleDark,
}, },
}; };

20501
package-lock.json generated

File diff suppressed because it is too large Load diff