migrate core to emotion
This commit is contained in:
.babelrcpackage-lock.jsonpackage.jsonbootstrap.jsindex.csspostcss.config.jsyarn.lock
packages
netlify-cms-core
example
package-lock.jsonpackage.jsonsrc
backends
git-gateway
github
gitlab
test-repo
components
App
Collection
Editor
Editor.cssEditor.js
EditorControlPane
EditorInterface.cssEditorInterface.jsEditorPreviewPane
EditorToggle.cssEditorToggle.jsEditorToolbar.cssEditorToolbar.jsEditorWidgets
Boolean
List
Markdown/MarkdownControl
Object
Relation
MediaLibrary
EmptyMessage.jsMediaLibrary.cssMediaLibrary.jsMediaLibraryActions.jsMediaLibraryCard.jsMediaLibraryCardGrid.jsMediaLibraryHeader.jsMediaLibraryModal.jsMediaLibrarySearch.js
UI
DragDrop.jsErrorBoundary.js
ErrorBoundary
FileUploadButton.jsFileUploadButton
Modal.jsModal
SettingsDropdown.jsToast.jsToast
UI.cssbase.cssindex.jsWorkflow
netlify-cms-lib-auth
netlify-cms-lib-util
netlify-cms-ui-default
115
packages/netlify-cms-ui-default/src/Dropdown.js
Normal file
115
packages/netlify-cms-ui-default/src/Dropdown.js
Normal file
@ -0,0 +1,115 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled, { css } from 'react-emotion';
|
||||
import { Wrapper, Button as DropdownButton, Menu, MenuItem } from 'react-aria-menubutton';
|
||||
import { shadows, colors, colorsRaw, lengths, buttons, components } from './styles';
|
||||
import Icon from './Icon';
|
||||
|
||||
const StyledWrapper = styled(Wrapper)`
|
||||
position: relative;
|
||||
font-size: 14px;
|
||||
user-select: none;
|
||||
`
|
||||
|
||||
const StyledDropdownButton = styled(DropdownButton)`
|
||||
${buttons.button};
|
||||
${buttons.default};
|
||||
display: block;
|
||||
padding-left: 20px;
|
||||
padding-right: 40px;
|
||||
|
||||
&:after {
|
||||
${components.caretDown};
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
color: currentColor;
|
||||
}
|
||||
`
|
||||
|
||||
const DropdownList = styled.ul`
|
||||
${shadows.dropDeep};
|
||||
background-color: ${colorsRaw.white};
|
||||
border-radius: ${lengths.borderRadius};
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
min-width: 100%;
|
||||
z-index: 1;
|
||||
|
||||
${props => css`
|
||||
width: ${props.width};
|
||||
top: ${props.top};
|
||||
left: ${props.position === 'left' ? 0 : 'auto'};
|
||||
right: ${props.position === 'right' ? 0 : 'auto'};
|
||||
`}
|
||||
`
|
||||
|
||||
const StyledMenuItem = styled(MenuItem)`
|
||||
${buttons.button};
|
||||
background-color: transparent;
|
||||
border-radius: 0;
|
||||
color: ${colorsRaw.gray};
|
||||
font-weight: 500;
|
||||
border-bottom: 1px solid #eaebf1;
|
||||
padding: 10px 14px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
&:last-of-type {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
color: ${colors.active};
|
||||
background-color: ${colors.activeBackground};
|
||||
}
|
||||
`
|
||||
|
||||
const MenuItemIconContainer = styled.div`
|
||||
flex: 1 0 32px;
|
||||
text-align: right;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
`
|
||||
|
||||
const Dropdown = ({
|
||||
renderButton,
|
||||
dropdownWidth = 'auto',
|
||||
dropdownPosition = 'left',
|
||||
dropdownTopOverlap = '0',
|
||||
children,
|
||||
}) => {
|
||||
return (
|
||||
<StyledWrapper onSelection={handler => handler()}>
|
||||
{renderButton()}
|
||||
<Menu>
|
||||
<DropdownList width={dropdownWidth} top={dropdownTopOverlap} position={dropdownPosition}>
|
||||
{children}
|
||||
</DropdownList>
|
||||
</Menu>
|
||||
</StyledWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
const DropdownItem = ({ label, icon, iconDirection, onClick }) => (
|
||||
<StyledMenuItem value={onClick}>
|
||||
<span>{label}</span>
|
||||
{
|
||||
icon
|
||||
? <MenuItemIconContainer>
|
||||
<Icon type={icon} direction={iconDirection} size="small"/>
|
||||
</MenuItemIconContainer>
|
||||
: null
|
||||
}
|
||||
</StyledMenuItem>
|
||||
);
|
||||
|
||||
export { Dropdown as default, DropdownItem, DropdownButton, StyledDropdownButton };
|
@ -1,77 +0,0 @@
|
||||
:root {
|
||||
--dropdownList: {
|
||||
@apply(--dropShadowDeep);
|
||||
background-color: #fff;
|
||||
border-radius: var(--borderRadius);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
--dropdownItem: {
|
||||
@apply --button;
|
||||
background-color: transparent;
|
||||
border-radius: 0;
|
||||
color: var(--colorText);
|
||||
font-weight: 500;
|
||||
border-bottom: 1px solid #eaebf1;
|
||||
padding: 10px 14px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
&:last-of-type {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
color: var(--colorBlue);
|
||||
background-color: var(--colorActiveBackground);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nc-dropdown {
|
||||
position: relative;
|
||||
font-size: 14px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.nc-dropdownButton {
|
||||
@apply --button;
|
||||
@apply --buttonDefault;
|
||||
display: block;
|
||||
padding-left: 20px;
|
||||
padding-right: 40px;
|
||||
|
||||
&:after {
|
||||
@apply(--caretDown);
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
color: currentColor;
|
||||
}
|
||||
}
|
||||
|
||||
.nc-dropdownList {
|
||||
@apply(--dropdownList);
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
min-width: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.nc-dropdownItem {
|
||||
@apply(--dropdownItem);
|
||||
}
|
||||
|
||||
.nc-dropdownItemIcon {
|
||||
flex: 1 0 32px;
|
||||
text-align: right;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import c from 'classnames';
|
||||
import { Wrapper, Button, Menu, MenuItem } from 'react-aria-menubutton';
|
||||
import { Icon } from '../Icon/Icon';
|
||||
|
||||
const Dropdown = ({
|
||||
label,
|
||||
button,
|
||||
className,
|
||||
classNameButton = '',
|
||||
dropdownWidth = 'auto',
|
||||
dropdownPosition = 'left',
|
||||
dropdownTopOverlap = '0',
|
||||
children
|
||||
}) => {
|
||||
const style = {
|
||||
width: dropdownWidth,
|
||||
top: dropdownTopOverlap,
|
||||
left: dropdownPosition === 'left' ? 0 : 'auto',
|
||||
right: dropdownPosition === 'right' ? 0 : 'auto',
|
||||
};
|
||||
return (
|
||||
<Wrapper className={c('nc-dropdown', className)} onSelection={handler => handler()}>
|
||||
{
|
||||
button
|
||||
? <Button>{button}</Button>
|
||||
: <Button className={c('nc-dropdownButton', classNameButton)}>{label}</Button>
|
||||
}
|
||||
<Menu>
|
||||
<ul className="nc-dropdownList" style={style}>
|
||||
{children}
|
||||
</ul>
|
||||
</Menu>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
const DropdownItem = ({ label, icon, iconDirection, onClick, className }) => (
|
||||
<MenuItem className={c('nc-dropdownItem', className)} value={onClick}>
|
||||
<span>{label}</span>
|
||||
{
|
||||
icon
|
||||
? <span className="nc-dropdownItemIcon">
|
||||
<Icon type={icon} direction={iconDirection} size="small"/>
|
||||
</span>
|
||||
: null
|
||||
}
|
||||
</MenuItem>
|
||||
);
|
||||
|
||||
|
||||
export { Dropdown, DropdownItem };
|
62
packages/netlify-cms-ui-default/src/Icon.js
Normal file
62
packages/netlify-cms-ui-default/src/Icon.js
Normal file
@ -0,0 +1,62 @@
|
||||
import React from 'react';
|
||||
import styled from 'react-emotion';
|
||||
import icons from './Icon/icons';
|
||||
|
||||
const IconWrapper = styled.span`
|
||||
display: inline-block;
|
||||
line-height: 0;
|
||||
width: ${props => props.size};
|
||||
height: ${props => props.size};
|
||||
transform: ${props => `rotation(${props.rotation})`};
|
||||
|
||||
& path:not(.no-fill),
|
||||
& circle:not(.no-fill),
|
||||
& polygon:not(.no-fill),
|
||||
& rect:not(.no-fill) {
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
& path.clipped {
|
||||
fill: transparent;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
`
|
||||
|
||||
/**
|
||||
* Calculates rotation for icons that have a `direction` property configured
|
||||
* in the imported icon definition object. If no direction is configured, a
|
||||
* neutral rotation value is returned.
|
||||
*
|
||||
* Returned value is a string of shape `${degrees}deg`, for use in a CSS
|
||||
* transform.
|
||||
*/
|
||||
const getRotation = (iconDirection, newDirection) => {
|
||||
if (!iconDirection || !newDirection) {
|
||||
return '0deg';
|
||||
}
|
||||
const rotations = { right: 90, down: 180, left: 270, up: 360 };
|
||||
const degrees = rotations[newDirection] - rotations[iconDirection];
|
||||
return `${degrees}deg`;
|
||||
}
|
||||
|
||||
const sizes = {
|
||||
xsmall: '12px',
|
||||
small: '18px',
|
||||
medium: '24px',
|
||||
large: '32px',
|
||||
};
|
||||
|
||||
const Icon = ({ type, direction, size = 'medium', width, height, className }) => (
|
||||
<IconWrapper
|
||||
className={className}
|
||||
dangerouslySetInnerHTML={{ __html: icons[type].image }}
|
||||
size={sizes[size] || size}
|
||||
rotation={getRotation(icons[type].direction, direction)}
|
||||
/>
|
||||
);
|
||||
|
||||
export default styled(Icon)``
|
@ -1,24 +0,0 @@
|
||||
.nc-icon {
|
||||
display: inline-block;
|
||||
line-height: 0;
|
||||
|
||||
& > span {
|
||||
display: block;
|
||||
}
|
||||
|
||||
& path:not(.no-fill),
|
||||
& circle:not(.no-fill),
|
||||
& polygon:not(.no-fill),
|
||||
& rect:not(.no-fill) {
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
& path.clipped {
|
||||
fill: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.nc-icon svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
import React from 'react';
|
||||
import icons from './icons';
|
||||
|
||||
/**
|
||||
* Calculates rotation for icons that have a `direction` property configured
|
||||
* in the imported icon definition object. If no direction is configured, a
|
||||
* neutral rotation value is returned.
|
||||
*
|
||||
* Returned value is a string of shape `${degrees}deg`, for use in a CSS
|
||||
* transform.
|
||||
*/
|
||||
const getRotation = (iconDirection, newDirection) => {
|
||||
if (!iconDirection || !newDirection) {
|
||||
return '0deg';
|
||||
}
|
||||
const rotations = { right: 90, down: 180, left: 270, up: 360 };
|
||||
const degrees = rotations[newDirection] - rotations[iconDirection];
|
||||
return `${degrees}deg`;
|
||||
}
|
||||
|
||||
const sizes = {
|
||||
xsmall: '12px',
|
||||
small: '18px',
|
||||
medium: '24px',
|
||||
large: '32px',
|
||||
};
|
||||
|
||||
export const Icon = props => {
|
||||
const {
|
||||
type,
|
||||
direction,
|
||||
size = 'medium',
|
||||
className = '',
|
||||
width,
|
||||
height,
|
||||
...remainingProps
|
||||
} = props;
|
||||
const icon = icons[type];
|
||||
const rotation = getRotation(icon.direction, direction)
|
||||
const transform = `rotate(${rotation})`;
|
||||
const sizeResolved = sizes[size] || size;
|
||||
const style = { width: sizeResolved, height: sizeResolved, transform };
|
||||
return (
|
||||
<span className={`nc-icon ${className}`} {...remainingProps}>
|
||||
<span dangerouslySetInnerHTML={{ __html: icon.image }} style={style}></span>
|
||||
</span>
|
||||
);
|
||||
}
|
61
packages/netlify-cms-ui-default/src/ListItemTopBar.js
Normal file
61
packages/netlify-cms-ui-default/src/ListItemTopBar.js
Normal file
@ -0,0 +1,61 @@
|
||||
import React from 'react';
|
||||
import styled from 'react-emotion';
|
||||
import Icon from './Icon';
|
||||
import { colors, lengths } from './styles';
|
||||
|
||||
const TopBarButton = styled.button`
|
||||
color: ${colors.controlLabel};
|
||||
background: transparent;
|
||||
font-size: 16px;
|
||||
line-height: 1;
|
||||
padding: 0;
|
||||
width: 32px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
`
|
||||
|
||||
const TopBarButtonSpan = TopBarButton.withComponent('span');
|
||||
|
||||
const DragIcon = styled(TopBarButtonSpan)`
|
||||
width: 100%;
|
||||
cursor: move;
|
||||
`
|
||||
|
||||
const ListItemTopBar = ({ collapsed, onCollapseToggle, onRemove, dragHandleHOC }) => (
|
||||
<div>
|
||||
{
|
||||
onCollapseToggle
|
||||
? <TopBarButton onClick={onCollapseToggle}>
|
||||
<Icon type="chevron" size="small" direction={collapsed ? 'right' : 'down'}/>
|
||||
</TopBarButton>
|
||||
: null
|
||||
}
|
||||
{
|
||||
dragHandleHOC
|
||||
? <DragIcon>
|
||||
<Icon type="drag-handle" size="small"/>
|
||||
</DragIcon>
|
||||
: null
|
||||
}
|
||||
{
|
||||
onRemove
|
||||
? <TopBarButton onClick={onRemove}>
|
||||
<Icon type="close" size="small"/>
|
||||
</TopBarButton>
|
||||
: null
|
||||
}
|
||||
</div>
|
||||
);
|
||||
|
||||
const StyledListItemTopBar = styled(ListItemTopBar)`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
height: 26px;
|
||||
border-radius: ${lengths.borderRadius} ${lengths.borderRadius} 0 0;
|
||||
position: relative;
|
||||
`
|
||||
|
||||
export default StyledListItemTopBar;
|
@ -1,29 +0,0 @@
|
||||
.nc-listItemTopBar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
height: 26px;
|
||||
border-radius: var(--borderRadius) var(--borderRadius) 0 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nc-listItemTopBar-toggleButton,
|
||||
.nc-listItemTopBar-dragIcon,
|
||||
.nc-listItemTopBar-removeButton {
|
||||
color: var(--controlLabelColor);
|
||||
background: transparent;
|
||||
font-size: 16px;
|
||||
line-height: 1;
|
||||
padding: 0;
|
||||
width: 32px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nc-listControl-dragIcon {
|
||||
width: 100%;
|
||||
cursor: move;
|
||||
}
|
||||
|
@ -1,32 +0,0 @@
|
||||
import React from 'react';
|
||||
import c from 'classnames';
|
||||
import { Icon } from '../Icon/Icon';
|
||||
|
||||
|
||||
export const ListItemTopBar = ({ collapsed, onCollapseToggle, onRemove, dragHandleHOC, className }) => {
|
||||
const DragHandle = dragHandleHOC && dragHandleHOC(() =>
|
||||
<span className="nc-listItemTopBar-dragIcon">
|
||||
<Icon type="drag-handle" size="small"/>
|
||||
</span>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={c('nc-listItemTopBar', className)}>
|
||||
{
|
||||
onCollapseToggle
|
||||
? <button className="nc-listItemTopBar-toggleButton" onClick={onCollapseToggle}>
|
||||
<Icon type="chevron" size="small" direction={collapsed ? 'right' : 'down'}/>
|
||||
</button>
|
||||
: null
|
||||
}
|
||||
{ dragHandleHOC ? <DragHandle/> : null }
|
||||
{
|
||||
onRemove
|
||||
? <button className="nc-listItemTopBar-removeButton" onClick={onRemove}>
|
||||
<Icon type="close" size="small"/>
|
||||
</button>
|
||||
: null
|
||||
}
|
||||
</div>
|
||||
);
|
||||
};
|
153
packages/netlify-cms-ui-default/src/Loader.js
Normal file
153
packages/netlify-cms-ui-default/src/Loader.js
Normal file
@ -0,0 +1,153 @@
|
||||
import React from 'react';
|
||||
import styled, { css, keyframes } from 'react-emotion';
|
||||
import CSSTransition from 'react-transition-group/CSSTransition';
|
||||
import { colors } from './styles';
|
||||
|
||||
const styles = {
|
||||
disabled: css`
|
||||
display: none;
|
||||
`,
|
||||
active: css`
|
||||
display: block;
|
||||
`,
|
||||
enter: css`
|
||||
opacity: 0.01;
|
||||
`,
|
||||
enterActive: css`
|
||||
opacity: 1;
|
||||
transition: opacity 500ms ease-in;
|
||||
`,
|
||||
exit: css`
|
||||
opacity: 1;
|
||||
`,
|
||||
exitActive: css`
|
||||
opacity: 0.01;
|
||||
transition: opacity 300ms ease-in;
|
||||
`,
|
||||
};
|
||||
|
||||
const animations = {
|
||||
loader: keyframes`
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
`,
|
||||
};
|
||||
|
||||
const LoaderText = styled.div`
|
||||
width: auto !important;
|
||||
height: auto !important;
|
||||
text-align: center;
|
||||
color: #767676;
|
||||
margin-top: 55px;
|
||||
line-height: 35px;
|
||||
`
|
||||
|
||||
const LoaderItem = styled.div`
|
||||
position: absolute;
|
||||
white-space: nowrap;
|
||||
transform: translateX(-50%);
|
||||
`
|
||||
|
||||
export class Loader extends React.Component {
|
||||
state = {
|
||||
currentItem: 0,
|
||||
};
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.interval) {
|
||||
clearInterval(this.interval);
|
||||
}
|
||||
}
|
||||
|
||||
setAnimation = () => {
|
||||
if (this.interval) return;
|
||||
const { children } = this.props;
|
||||
|
||||
this.interval = setInterval(() => {
|
||||
const nextItem = (this.state.currentItem === children.length - 1) ? 0 : this.state.currentItem + 1;
|
||||
this.setState({ currentItem: nextItem });
|
||||
}, 5000);
|
||||
};
|
||||
|
||||
renderChild = () => {
|
||||
const { children } = this.props;
|
||||
const { currentItem } = this.state;
|
||||
if (!children) {
|
||||
return null;
|
||||
} else if (typeof children == 'string') {
|
||||
return <LoaderText>{children}</LoaderText>;
|
||||
} else if (Array.isArray(children)) {
|
||||
this.setAnimation();
|
||||
return (
|
||||
<LoaderText>
|
||||
<CSSTransition
|
||||
classNames={{
|
||||
enter: styles.enter,
|
||||
enterActive: styles.enterActive,
|
||||
exit: styles.exit,
|
||||
exitActive: styles.exitActive,
|
||||
}}
|
||||
timeout={500}
|
||||
>
|
||||
<LoaderItem key={currentItem}>{children[currentItem]}</LoaderItem>
|
||||
</CSSTransition>
|
||||
</LoaderText>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { active, className } = this.props;
|
||||
return <div>{this.renderChild()}</div>;
|
||||
}
|
||||
}
|
||||
|
||||
const StyledLoader = styled(Loader)`
|
||||
display: ${props => props.active ? 'block' : 'none'};
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin: 0px;
|
||||
text-align: center;
|
||||
z-index: 1000;
|
||||
transform: translateX(-50%) translateY(-50%);
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
width: 2.28571429rem;
|
||||
height: 2.28571429rem;
|
||||
margin: 0em 0em 0em -1.14285714rem;
|
||||
}
|
||||
|
||||
/* Static Shape */
|
||||
&:before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
top: 0%;
|
||||
left: 50%;
|
||||
border-radius: 500rem;
|
||||
border: 0.2em solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* Active Shape */
|
||||
&:after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
top: 0%;
|
||||
left: 50%;
|
||||
animation: ${animations.loader} 0.6s linear;
|
||||
animation-iteration-count: infinite;
|
||||
border-radius: 500rem;
|
||||
border-color: ${colors.active} transparent transparent;
|
||||
border-style: solid;
|
||||
border-width: 0.2em;
|
||||
box-shadow: 0px 0px 0px 1px transparent;
|
||||
}
|
||||
`
|
||||
|
||||
export default StyledLoader;
|
@ -1,108 +0,0 @@
|
||||
/* Active Animation */
|
||||
|
||||
@-webkit-keyframes loader {
|
||||
from {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loader {
|
||||
from {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.nc-loader-root {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin: 0px;
|
||||
text-align: center;
|
||||
z-index: 1000;
|
||||
-webkit-transform: translateX(-50%) translateY(-50%);
|
||||
-ms-transform: translateX(-50%) translateY(-50%);
|
||||
transform: translateX(-50%) translateY(-50%);
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
@apply(--loaderSize);
|
||||
margin: 0em 0em 0em -1.14285714rem;
|
||||
}
|
||||
|
||||
/* Static Shape */
|
||||
&:before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
top: 0%;
|
||||
left: 50%;
|
||||
border-radius: 500rem;
|
||||
border: 0.2em solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* Active Shape */
|
||||
&:after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
top: 0%;
|
||||
left: 50%;
|
||||
animation: loader 0.6s linear;
|
||||
animation-iteration-count: infinite;
|
||||
border-radius: 500rem;
|
||||
border-color: #3A69C7 transparent transparent;
|
||||
border-style: solid;
|
||||
border-width: 0.2em;
|
||||
box-shadow: 0px 0px 0px 1px transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.nc-loader-text {
|
||||
width: auto !important;
|
||||
height: auto !important;
|
||||
text-align: center;
|
||||
color: #767676;
|
||||
margin-top: 55px;
|
||||
line-height: 35px;
|
||||
}
|
||||
|
||||
.nc-loader-active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.nc-loader-disabled {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*Animations*/
|
||||
.nc-loader-animateItem{
|
||||
position: absolute;
|
||||
white-space: nowrap;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.nc-loader-enter {
|
||||
opacity: 0.01;
|
||||
}
|
||||
.nc-loader-enter.nc-loader-enterActive {
|
||||
opacity: 1;
|
||||
transition: opacity 500ms ease-in;
|
||||
}
|
||||
.nc-loader-exit {
|
||||
opacity: 1;
|
||||
}
|
||||
.nc-loader-exit.nc-loader-exitActive {
|
||||
opacity: 0.01;
|
||||
transition: opacity 300ms ease-in;
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
import React from 'react';
|
||||
import CSSTransition from 'react-transition-group/CSSTransition';
|
||||
import c from 'classnames';
|
||||
|
||||
export class Loader extends React.Component {
|
||||
|
||||
state = {
|
||||
currentItem: 0,
|
||||
};
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.interval) {
|
||||
clearInterval(this.interval);
|
||||
}
|
||||
}
|
||||
|
||||
setAnimation = () => {
|
||||
if (this.interval) return;
|
||||
const { children } = this.props;
|
||||
|
||||
this.interval = setInterval(() => {
|
||||
const nextItem = (this.state.currentItem === children.length - 1) ? 0 : this.state.currentItem + 1;
|
||||
this.setState({ currentItem: nextItem });
|
||||
}, 5000);
|
||||
};
|
||||
|
||||
renderChild = () => {
|
||||
const { children } = this.props;
|
||||
const { currentItem } = this.state;
|
||||
if (!children) {
|
||||
return null;
|
||||
} else if (typeof children == 'string') {
|
||||
return <div className="nc-loader-text">{children}</div>;
|
||||
} else if (Array.isArray(children)) {
|
||||
this.setAnimation();
|
||||
return (<div className="nc-loader-text">
|
||||
<CSSTransition
|
||||
classNames={{
|
||||
enter: 'nc-loader-enter',
|
||||
enterActive: 'nc-loader-enterActive',
|
||||
exit: 'nc-loader-exit',
|
||||
exitActive: 'nc-loader-exitActive',
|
||||
}}
|
||||
timeout={500}
|
||||
>
|
||||
<div key={currentItem} className="nc-loader-animateItem">{children[currentItem]}</div>
|
||||
</CSSTransition>
|
||||
</div>);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { active, className } = this.props;
|
||||
const combinedClassName = c('nc-loader-root', { 'nc-loader-active': active }, className);
|
||||
return <div className={combinedClassName}>{this.renderChild()}</div>;
|
||||
}
|
||||
}
|
67
packages/netlify-cms-ui-default/src/Toggle.js
Normal file
67
packages/netlify-cms-ui-default/src/Toggle.js
Normal file
@ -0,0 +1,67 @@
|
||||
import React from 'react'
|
||||
import styled, { css, cx } from 'react-emotion';
|
||||
import ReactToggled from 'react-toggled';
|
||||
import { colors, colorsRaw, shadows, transitions } from './styles';
|
||||
|
||||
const styles = {
|
||||
switch: css`
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
cursor: pointer;
|
||||
`,
|
||||
switchHandle: css`
|
||||
${shadows.dropDeep};
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
background-color: ${colorsRaw.white};
|
||||
transition: transform ${transitions.main};
|
||||
`,
|
||||
switchHandleActive: css`
|
||||
transform: translateX(20px);
|
||||
`,
|
||||
switchBackground: css`
|
||||
width: 34px;
|
||||
height: 14px;
|
||||
border-radius: 10px;
|
||||
background-color: ${colors.active};
|
||||
`,
|
||||
};
|
||||
|
||||
const Toggle = ({
|
||||
active,
|
||||
onChange,
|
||||
className,
|
||||
classNameBackground,
|
||||
classNameSwitch,
|
||||
onFocus,
|
||||
onBlur
|
||||
}) =>
|
||||
<ReactToggled on={active} onToggle={onChange}>
|
||||
{({on, getElementTogglerProps}) => (
|
||||
<span
|
||||
className={cx(styles.switch, className)}
|
||||
role="switch"
|
||||
aria-checked={on.toString()}
|
||||
onFocus={onFocus}
|
||||
onBlur={onBlur}
|
||||
{...getElementTogglerProps()}
|
||||
>
|
||||
<span className={cx(styles.switchBackground, classNameBackground)}/>
|
||||
<span className={cx(
|
||||
styles.switchHandle,
|
||||
classNameSwitch,
|
||||
{ [styles.switchHandleActive]: on },
|
||||
)}/>
|
||||
</span>
|
||||
)}
|
||||
</ReactToggled>;
|
||||
|
||||
export default styled(Toggle)``
|
@ -1,32 +0,0 @@
|
||||
.nc-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nc-toggle-background {
|
||||
width: 34px;
|
||||
height: 14px;
|
||||
border-radius: 10px;
|
||||
background-color: #3a69c7;
|
||||
}
|
||||
|
||||
.nc-toggle-switch {
|
||||
@apply(--dropShadowDeep);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
background-color: white;
|
||||
transition: transform var(--transition);
|
||||
}
|
||||
|
||||
.nc-toggle-active .nc-toggle-switch {
|
||||
transform: translateX(20px);
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
import React from 'react'
|
||||
import ReactToggled from 'react-toggled';
|
||||
import c from 'classnames';
|
||||
|
||||
export const Toggle = ({
|
||||
active,
|
||||
onChange,
|
||||
className,
|
||||
classNameBackground,
|
||||
classNameSwitch,
|
||||
onFocus,
|
||||
onBlur
|
||||
}) =>
|
||||
<ReactToggled on={active} onToggle={onChange}>
|
||||
{({on, getElementTogglerProps}) => (
|
||||
<span
|
||||
className={c('nc-toggle', className, { 'nc-toggle-active': on })}
|
||||
role="switch"
|
||||
aria-checked={on.toString()}
|
||||
onFocus={onFocus}
|
||||
onBlur={onBlur}
|
||||
{...getElementTogglerProps()}
|
||||
>
|
||||
<span className={`nc-toggle-background ${classNameBackground}`}/>
|
||||
<span className={`nc-toggle-switch ${classNameSwitch}`}/>
|
||||
</span>
|
||||
)}
|
||||
</ReactToggled>;
|
@ -1,7 +0,0 @@
|
||||
import { Dropdown, DropdownItem } from './Dropdown/Dropdown';
|
||||
import { Icon } from './Icon/Icon';
|
||||
import { ListItemTopBar } from './ListItemTopBar/ListItemTopBar';
|
||||
import { Loader } from './Loader/Loader';
|
||||
import { Toggle } from './Toggle/Toggle';
|
||||
|
||||
export { Dropdown, DropdownItem, Icon, ListItemTopBar, Loader, Toggle };
|
310
packages/netlify-cms-ui-default/src/styles.js
Normal file
310
packages/netlify-cms-ui-default/src/styles.js
Normal file
@ -0,0 +1,310 @@
|
||||
import { css, injectGlobal } from 'react-emotion';
|
||||
|
||||
/**
|
||||
* Font Stacks
|
||||
*/
|
||||
export const fonts = {
|
||||
primary: `
|
||||
-apple-system,
|
||||
BlinkMacSystemFont,
|
||||
"Segoe UI",
|
||||
Roboto,
|
||||
Helvetica,
|
||||
Arial,
|
||||
sans-serif,
|
||||
"Apple Color Emoji",
|
||||
"Segoe UI Emoji",
|
||||
"Segoe UI Symbol"
|
||||
`,
|
||||
mono: `
|
||||
'SFMono-Regular',
|
||||
Consolas,
|
||||
"Liberation Mono",
|
||||
Menlo,
|
||||
Courier,
|
||||
monospace;
|
||||
`,
|
||||
};
|
||||
|
||||
/**
|
||||
* Theme Colors
|
||||
*/
|
||||
export const colorsRaw = {
|
||||
white: '#fff',
|
||||
grayLight: '#eff0f4',
|
||||
gray: '#798291',
|
||||
grayDark: '#313d3e',
|
||||
blue: '#3a69c7',
|
||||
blueLight: '#e8f5fe',
|
||||
green: '#005614',
|
||||
greenLight: '#caef6f',
|
||||
brown: '#754e00',
|
||||
yellow: '#ffee9c',
|
||||
red: '#ff003b',
|
||||
redLight: '#fcefea',
|
||||
purple: '#70399f',
|
||||
purpleLight: '#f6d8ff',
|
||||
teal: '#17a2b8',
|
||||
tealLight: '#ddf5f9',
|
||||
};
|
||||
|
||||
export const colors = {
|
||||
statusDraftText: colorsRaw.purple,
|
||||
statusDraftBackground: colorsRaw.purpleLight,
|
||||
statusReviewText: colorsRaw.Brown,
|
||||
statusReviewBackground: colorsRaw.yellow,
|
||||
statusReadyText: colorsRaw.green,
|
||||
statusReadyBackground: colorsRaw.greenLight,
|
||||
text: colorsRaw.gray,
|
||||
textLight: colorsRaw.white,
|
||||
textLead: colorsRaw.grayDark,
|
||||
background: colorsRaw.grayLight,
|
||||
foreground: colorsRaw.white,
|
||||
active: colorsRaw.blue,
|
||||
activeBackground: colorsRaw.blueLight,
|
||||
inactive: colorsRaw.gray,
|
||||
button: colorsRaw.gray,
|
||||
buttonText: colorsRaw.white,
|
||||
inputBackground: colorsRaw.white,
|
||||
infoText: colorsRaw.blue,
|
||||
infoBackground: colorsRaw.blueLight,
|
||||
successText: colorsRaw.green,
|
||||
successBackground: colorsRaw.greenLight,
|
||||
warnText: colorsRaw.brown,
|
||||
warnBackground: colorsRaw.yellow,
|
||||
errorText: colorsRaw.red,
|
||||
errorBackground: colorsRaw.redLight,
|
||||
textFieldBorder: '#dfdfe3',
|
||||
controlLabel: '#7a8291',
|
||||
};
|
||||
|
||||
export const lengths = {
|
||||
topBarHeight: '56px',
|
||||
inputPadding: '16px 20px',
|
||||
borderRadius: '5px',
|
||||
richTextEditorMinHeight: '300px',
|
||||
borderWidth: '2px',
|
||||
topCardWidth: '682px',
|
||||
pageMargin: '84px 18px',
|
||||
};
|
||||
|
||||
export const borders = {
|
||||
textField: `solid ${lengths.borderWidth} ${colors.textFieldBorder}`,
|
||||
};
|
||||
|
||||
export const transitions = {
|
||||
main: '.2s ease',
|
||||
};
|
||||
|
||||
export const shadows = {
|
||||
drop: css`
|
||||
box-shadow: 0 2px 4px 0 rgba(19, 39, 48, .12);
|
||||
`,
|
||||
dropMain: css`
|
||||
box-shadow: 0 2px 6px 0 rgba(68, 74, 87, 0.05),
|
||||
0 1px 3px 0 rgba(68, 74, 87, 0.10);
|
||||
`,
|
||||
dropMiddle: css`
|
||||
box-shadow: 0 2px 6px 0 rgba(68, 74, 87, 0.15),
|
||||
0 1px 3px 0 rgba(68, 74, 87, 0.30);
|
||||
`,
|
||||
dropDeep: css`
|
||||
box-shadow: 0 4px 12px 0 rgba(68, 74, 87, 0.15),
|
||||
0 1px 3px 0 rgba(68, 74, 87, 0.25);
|
||||
`,
|
||||
};
|
||||
|
||||
const textBadge = css`
|
||||
font-size: 13px;
|
||||
border-radius: ${lengths.borderRadius};
|
||||
padding: 4px 10px;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
`;
|
||||
|
||||
const card = css`
|
||||
${shadows.dropMain};
|
||||
border-radius: 5px;
|
||||
background-color: #fff;
|
||||
`;
|
||||
|
||||
export const buttons = {
|
||||
button: css`
|
||||
border: 0;
|
||||
border-radius: ${lengths.borderRadius};
|
||||
cursor: pointer;
|
||||
`,
|
||||
default: css`
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
font-weight: 500;
|
||||
padding: 0 15px;
|
||||
background-color: ${colorsRaw.gray};
|
||||
color: ${colorsRaw.white};
|
||||
`,
|
||||
medium: css`
|
||||
height: 27px;
|
||||
line-height: 27px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
border-radius: 3px;
|
||||
padding: 0 24px 0 14px;
|
||||
`,
|
||||
small: css`
|
||||
height: 23px;
|
||||
line-height: 23px;
|
||||
`,
|
||||
gray: css`
|
||||
background-color: ${colors.button};
|
||||
color: ${colors.buttonText};
|
||||
|
||||
&:focus,
|
||||
&:hover {
|
||||
color: ${colors.white};
|
||||
background-color: #555a65;
|
||||
}
|
||||
`,
|
||||
green: css`
|
||||
background-color: #aae31f;
|
||||
color: ${colorsRaw.green};
|
||||
`,
|
||||
lightRed: css`
|
||||
background-color: ${colorsRaw.redLight};
|
||||
color: ${colorsRaw.red};
|
||||
`,
|
||||
lightBlue: css`
|
||||
background-color: ${colorsRaw.blueLight};
|
||||
color: ${colorsRaw.blue};
|
||||
`,
|
||||
lightTeal: css`
|
||||
background-color: ${colorsRaw.tealLight};
|
||||
color: #1195aa;
|
||||
`,
|
||||
teal: css`
|
||||
background-color: ${colorsRaw.teal};
|
||||
color: ${colorsRaw.white};
|
||||
`,
|
||||
disabled: css`
|
||||
background-color: ${colorsRaw.grayLight};
|
||||
color: ${colorsRaw.gray};
|
||||
`,
|
||||
};
|
||||
|
||||
export const components = {
|
||||
card,
|
||||
caretDown: css`
|
||||
color: ${colorsRaw.white};
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 5px solid transparent;
|
||||
border-right: 5px solid transparent;
|
||||
border-top: 6px solid currentColor;
|
||||
border-radius: 2px;
|
||||
`,
|
||||
textBadgeSuccess: css`
|
||||
${textBadge};
|
||||
color: ${colorsRaw.green};
|
||||
background-color: ${colorsRaw.greenLight};
|
||||
`,
|
||||
textBadgeDanger: css`
|
||||
${textBadge};
|
||||
color: ${colorsRaw.red};
|
||||
background-color: #fbe0d7;
|
||||
`,
|
||||
loaderSize: css`
|
||||
width: 2.28571429rem;
|
||||
height: 2.28571429rem;
|
||||
`,
|
||||
cardTop: css`
|
||||
${card};
|
||||
width: ${lengths.topCardWidth};
|
||||
max-width: 100%;
|
||||
padding: 18px 20px;
|
||||
margin-bottom: 28px;
|
||||
`,
|
||||
cardTopHeading: css`
|
||||
font-size: 22px;
|
||||
font-weight: 600;
|
||||
line-height: 37px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
`,
|
||||
cardTopDescription: css`
|
||||
max-width: 480px;
|
||||
color: ${colors.text};
|
||||
font-size: 14px;
|
||||
margin-top: 8px;
|
||||
`,
|
||||
}
|
||||
|
||||
injectGlobal`
|
||||
*, *:before, *:after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:focus {
|
||||
outline: -webkit-focus-ring-color auto ${lengths.borderRadius};
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't show outlines if the user is utilizing mouse rather than keyboard.
|
||||
*/
|
||||
[data-whatintent="mouse"] *:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
|
||||
input {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: ${fonts.primary};
|
||||
font-weight: normal;
|
||||
background-color: ${colors.background};
|
||||
color: ${colors.text};
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6, p {
|
||||
font-family: ${fonts.primary};
|
||||
color: ${colors.textLead};
|
||||
font-size: 15px;
|
||||
line-height: 1.5;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
letter-spacing: 0.4px;
|
||||
color: ${colors.textLead};
|
||||
}
|
||||
|
||||
a,
|
||||
button {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
a {
|
||||
color: ${colors.text};
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: none;
|
||||
}
|
||||
`;
|
Reference in New Issue
Block a user