1
0
mirror of https://github.com/yldio/copilot.git synced 2024-11-14 23:30:05 +02:00

feat(joyent-cp-frontend,joyent-ui-toolkit,joyent-cp-gql-mock-data): Scaling and delete modals

This commit is contained in:
JUDIT GRESKOVITS 2017-06-16 15:12:28 +01:00 committed by Judit Greskovits
parent e0dc31610d
commit bd2bf728c6
113 changed files with 1542 additions and 23898 deletions

View File

@ -0,0 +1,257 @@
import { find, filter } from 'lodash';
import data from './mock-data';
import { normalMetricData, leakMetricData } from './mock-data/metrics';
// TMP / Util
const datacenter = {
id: 'datacenter-id',
region: 'us-east-1'
};
const user = {
id: 'unique-user-id',
firstName: 'Judit',
lastName: 'Greskovits',
email: 'name@email.com',
login: 'juditgreskovits'
};
const portal = { user, host: 'dockerhost', datacenter };
const deploymentGroups = data.projects.data.map(p => {
p.slug = p.id;
p.id = p.uuid;
return p;
});
const services = data.services.data.map(s => {
s.slug = s.id;
s.id = s.uuid;
return s;
});
const instances = data.instances.data.map(i => {
i.slug = i.id;
i.id = i.uuid;
return i;
});
const metricTypes = data.metrics.data.types;
const count = 10;
let index = 0;
const getInstanceMetricData = (dataset, type) => {
return dataset[type].slice(index, index + count);
};
const tick = setInterval(() => index++, 15 * 1000);
// GraphQL
const queries = {
portal() {
return portal;
},
deploymentGroups(_, { name, slug }) {
return deploymentGroups;
},
deploymentGroup(_, { id, name, slug }) {
if (id) {
return find(deploymentGroups, { id: id });
}
if (slug) {
return find(deploymentGroups, { slug: slug });
}
return null;
},
serviceScales(_, { serviceName, versionUuid }) {
// : [ServiceScale]
return [];
},
serviceScale(_, { id }) {
// : ServiceScale
return {};
},
convergenceActions(_, { type, service, versionUuid }) {
// : [ConvergenceAction]
return [];
},
convergenceAction(id) {
// : ConvergenceAction
return {};
},
stateConvergencePlans(_, { running, versionUuid }) {
// : [StateConvergencePlan]
return [];
},
stateConvergencePlan(_, { id }) {
// : StateConvergencePlan
return [];
},
versions(_, { manifestUuid, deploymentGroupUuid }) {
// : [Version]
return [];
},
version(_, { id, manifestUuid }) {
// : Version
return null;
},
manifests(_, { type, deploymentGroupUuid }) {
// : [Manifest]
return [];
},
manifest(_, { id }) {
// : Manifest
return null;
},
services(
_,
{ name, slug, parentUuid, deploymentGroupUuid, deploymentGroupSlug }
) {
// }: [Service]
if (deploymentGroupUuid) {
return filter(services, { project: deploymentGroupUuid });
}
if (deploymentGroupSlug) {
const deploymentGroup = find(deploymentGroups, {
slug: deploymentGroupSlug
});
if (deploymentGroup) {
if (slug) {
return filter(services, { project: deploymentGroup.id, slug: slug });
}
return filter(services, { project: deploymentGroup.id });
}
return null;
}
return services;
},
service(_, { id, hash }) {
// : Service
if (id) {
return find(services, { id: id });
}
if (hash) {
return find(services, { hash: hash });
}
return null;
},
packages(_, { name, type, memory, disk, swap, lwps, vcpus, version, group }) {
// : [Package]
return [];
},
package(_, { id }) {
// : Package
return {};
},
instances(
_,
{
name,
machineId,
status,
serviceUuid,
serviceSlug,
deploymentGroupUuid,
deploymentGroupSlug
}
) {
// : [Instance]
if (serviceUuid) {
return filter(instances, { service: serviceUuid });
}
if (serviceSlug) {
const service = find(services, { slug: serviceSlug });
if (service) {
return filter(instances, { service: service.id });
}
return null;
}
return instances;
},
instance(_, { id }) {
// : Instance
if (id) {
return find(instances, { id: id });
}
},
datacenter() {
return datacenter;
}
/*metricTypes() {
return metricTypes;
},
// tmp test
instanceMetric() {
return {
type: {
id: 'node_memory_rss_bytes',
id: 'node_memory_rss_bytes',
name: 'node_memory_rss_bytes',
},
data: getInstanceMetricData(leakMetricData, 'node_memory_rss_bytes')
};
}*/
};
const resolveFunctions = {
Query: queries,
Portal: {
deploymentGroups(portal, args, context) {
return deploymentGroups;
}
},
DeploymentGroup: {
services(deploymentGroup, args, context) {
const a = Object.assign({}, args, {
deploymentGroupSlug: deploymentGroup.slug
});
return queries.services(null, a);
}
},
Service: {
instances(service, args, context) {
return filter(instances, { service: service.id });
}
/*metrics(service) {
return service.metrics ?
service.metrics.map((metric) =>
find(metricTypes, { id: metric.type })) : [];
},*/
/*currentMetrics(service) {
// tmp
return [{
"name": "CPU",
"value": 50,
"measurement": "%",
}, {
"name": "Memory",
"value": 20,
"measurement": "%",
}, {
"name": "Network",
"value": 2.9,
"measurement": "Kb/sec",
}];
},*/
}
/*Instance: {
metrics(instance) {
return ([{
type: {
id: 'metric-type-id',
id: 'metric-type-id',
name: 'metric-type-name'
},
data: normalMetricData.node_memory_rss_bytes
}]);
}
}*/
};
export default resolveFunctions;

View File

@ -0,0 +1,213 @@
scalar Date
scalar Object
type Portal {
user: User!
datacenter: Datacenter!
deploymentGroups: [DeploymentGroup]!
}
type User {
id: ID!
firstName: String!
lastName: String!
email: String!
login: String!
}
type DeploymentGroup {
id: ID!
name: String!
slug: String!
services(slug: String): [Service]!
version: Version!
history: [Version]!
}
type ServiceScale {
id: ID!
serviceName: String!
replicas: Int!
}
enum ConvergenceActionType {
NOOP
CREATE
RECREATE
START
}
type ConvergenceAction {
id: String!
type: ConvergenceActionType!
service: String! # service name
machines: [String]! # instance machine ids
}
type StateConvergencePlan {
id: String!
running: Boolean!
actions: [ConvergenceAction]!
}
type Version {
created: Date! # Either Int or define scalar
manifest: Manifest!
scale: [ServiceScale]!
plan: StateConvergencePlan
}
enum ManifestType {
COMPOSE
MARIPOSA
}
enum ManifestFormat {
JSON
YAML
}
type Manifest {
id: String!
created: Date!
type: ManifestType!
format: ManifestFormat!
raw: String!
obj: Object!
}
# immutable
type Service {
id: String! # unique id for db row
hash: String! # unique id for version of service
name: String! # human readable name
slug: String!
instances: [Instance]!
# metrics: [MetricType]!
currentMetrics: [CurrentMetric]!
connections: [String!] # list of serviceUuids
parent: ID # parent service id
package: Package! # we don't have this in current mock data
}
# for metrics max / min (I guess)
type Package {
id: ID!
name: String!
type: String!
memory: Float!
disk: Float!
swap: Float!
lwps: Int!
vcpus: Int!
version: String!
group: String!
}
enum InstanceStatus {
CREATED
RESTARTING
RUNNING
PAUSED
EXITED
DELETED
}
type Instance {
id: String!
name: String!
machineId: String!
status: InstanceStatus!
# metrics: [InstanceMetric]!
}
type Datacenter {
id: String!
# name: String! # Do we have 'official' human readable names?
region: String!
}
type InstanceMetric {
type: MetricType!
data: [MetricData]!
}
type CurrentMetric {
name: String!
value: Float!
measurement: String!
}
type MetricType {
id: String!
name: String!
id: String!
}
type MetricData {
timestamp: Int!
value: Float!
}
# Need to review queries
type Query {
portal: Portal
deploymentGroups: [DeploymentGroup]
deploymentGroup(id: String, slug: String): DeploymentGroup
services(deploymentGroupUuid: String, deploymentGroupSlug: String): [Service]
service(id: String, slug: String): Service
instances(serviceUuid: String, serviceSlug: String): [Instance]
instance(id: String, machineId: String): Instance
metricTypes: [MetricType]
metricData(instanceUuid: String!, metricType: String!, from: Date!, to: Date!): [InstanceMetric]!
package: Package
datacenters: [Datacenter]
# tmp test
instanceMetric: InstanceMetric!
}
# we probably wont use some of these queries or arguments
# but this way we expose the entire db through gql
type Query {
portal: Portal
user: User
deploymentGroups(name: String, slug: String): [DeploymentGroup]
deploymentGroup(id: ID, name: String, slug: String): DeploymentGroup
serviceScales(serviceName: String, versionUuid: ID): [ServiceScale]
serviceScale(id: ID!): ServiceScale
convergenceActions(type: ConvergenceActionType, service: String, versionUuid: ID): [ConvergenceAction]
convergenceAction(id: ID!): ConvergenceAction
stateConvergencePlans(running: Boolean, versionUuid: ID): [StateConvergencePlan]
stateConvergencePlan(id: ID!): StateConvergencePlan
versions(manifestUuid: ID, deploymentGroupUuid: ID): [Version]
version(id: ID, manifestUuid: ID): Version
manifests(type: String, deploymentGroupUuid: ID): [Manifest]
manifest(id: ID!): Manifest
services(name: String, slug: String, parentUuid: ID, deploymentGroupUuid: ID, deploymentGroupSlug: String): [Service]
service(id: ID, hash: ID): Service
packages(name: String, type: String, memory: Int, disk: Int, swap: Int, lwps: Int, vcpus: Int, version: String, group: String): [Package]
package(id: ID!): Package
instances(name: String!, machineId: ID, status: InstanceStatus, serviceUuid: ID, serviceSlug: String, deploymentGroupUuid: ID, deploymentGroupSlug: String): [Instance]
instance(id: ID!): Instance
datacenter(id: ID, region: String): Datacenter
}
type Mutation {
createDeploymentGroup(name: String!) : DeploymentGroup
updateDeploymentGroup(id: ID!, name: String!) : DeploymentGroup
provisionManifest(deploymentGroupUuid: ID!, type: ManifestType!, format: ManifestFormat!, raw: String!) : Version
scale(service: ID!, replicas: Int!) : Version
stopServices(ids: [ID]!) : [Service]
startServices(ids: [ID]!) : [Service]
restartServices(ids: [ID]!) : [Service]
deleteServices(ids: [ID]!) : [Service]
stopInstances(ids: [ID]!) : [Instance]
startInstances(ids: [ID]!) : [Instance]
restartInstances(ids: [ID]!) : [Instance]
# reprovision() ???
}

View File

@ -87,5 +87,8 @@
"portal-api", "portal-api",
"control-tower" "control-tower"
] ]
},
"dependencies": {
"styled-components": "^2.0.0"
} }
} }

View File

@ -1,3 +0,0 @@
{
"extends": "joyent-portal"
}

View File

@ -1,9 +0,0 @@
{
"libs": [
"ecmascript"
],
"plugins": {
"doc_comment": true,
"local-scope": true
}
}

View File

@ -1,30 +0,0 @@
# babel-preset-joyent-portal
[![License: MPL 2.0](https://img.shields.io/badge/License-MPL%202.0-brightgreen.svg)](https://opensource.org/licenses/MPL-2.0)
[![standard-readme compliant](https://img.shields.io/badge/standard--readme-OK-green.svg)](https://github.com/RichardLitt/standard-readme)
[`babel`](http://github.com/babel/babel) preset to be used across this repo. At the moment it only extends the one used by [`create-react-app`](https://github.com/facebookincubator/create-react-app/tree/master/packages/babel-preset-react-app) but it can be extended as needed.
## Table of Contents
- [Install](#install)
- [Usage](#usage)
- [License](#license)
## Install
```
yarn add --dev babel-preset-joyent-portal
```
## Usage
```json
{
"presets": "joyent-portal"
}
```
## License
MPL-2.0

View File

@ -1,3 +0,0 @@
module.exports = (ctx, opts) => ({
presets: [require('babel-preset-react-app')]
});

View File

@ -1,20 +0,0 @@
{
"name": "babel-preset-joyent-portal",
"version": "1.0.0",
"license": "MPL-2.0",
"repository": "github:yldio/joyent-portal",
"main": "index.js",
"scripts": {
"lint": "eslint . --fix",
"lint-ci": "eslint . --format junit --output-file $CIRCLE_TEST_REPORTS/lint/babel-preset-joyent-portal.xml",
"test": "echo 0",
"test-ci": "echo 0"
},
"dependencies": {
"babel-preset-react-app": "^3.0.0"
},
"devDependencies": {
"eslint": "^3.19.0",
"eslint-config-joyent-portal": "1.0.0"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,37 @@
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import { H2, Button, P } from 'joyent-ui-toolkit';
const ModalHeading = styled(H2)`
line-height: 1.25;
color: ${props => props.theme.secondary};
`;
const ModalText = styled(P)`
color: ${props => props.theme.secondary};
`;
const propTypes = {
service: PropTypes.object,
onCancelClick: PropTypes.func.isRequired,
onConfirmClick: PropTypes.func.isRequired
};
const ServiceDelete = ({ service, onCancelClick, onConfirmClick }) => (
<div>
<ModalHeading>
Deleting a service: <br /> {service.name}
</ModalHeading>
<ModalText marginBottom="3">
Deleting a service can lead to irreverasable loss of data and failures
in your application. Are you sure you want to continue?
</ModalText>
<Button onClick={onCancelClick} secondary>Cancel</Button>
<Button onClick={onConfirmClick}>Delete service</Button>
</div>
);
ServiceDelete.propTypes = propTypes;
export default ServiceDelete;

View File

@ -0,0 +1,2 @@
export { default as ServiceScale } from './scale';
export { default as ServiceDelete } from './delete';

View File

@ -0,0 +1,36 @@
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import unitcalc from 'unitcalc';
import { H2, P, Button } from 'joyent-ui-toolkit';
import { FormGroup, Input, NumberInput } from 'joyent-ui-toolkit';
const StyledH2 = styled(H2)`
margin: 0 0 ${unitcalc(2)} 0;
`;
const ServiceScale = ({ service, onConfirmClick, onCancelClick }) => {
const handleScaleClick = () => {
onConfirmClick(2);
};
return (
<div>
<StyledH2>Scaling a service: <br />{service.name}</StyledH2>
<P>Choose how many instances of a service you want to have running.</P>
<form onSubmit={() => {}}>
<NumberInput />
<Button secondary onClick={onCancelClick}>Cancel</Button>
<Button secondary onClick={handleScaleClick}>Scale</Button>
</form>
</div>
);
};
ServiceScale.propTypes = {
service: PropTypes.object,
onScaleClick: PropTypes.func,
onCancelClick: PropTypes.func
};
export default ServiceScale;

View File

@ -21,8 +21,6 @@ import {
// InstancesMultipleIcon // InstancesMultipleIcon
} from 'joyent-ui-toolkit'; } from 'joyent-ui-toolkit';
import { ServicesQuickActions } from '@components/services';
const StyledCardHeader = styled(CardHeader)` const StyledCardHeader = styled(CardHeader)`
position: relative; position: relative;
`; `;
@ -35,9 +33,7 @@ const TitleInnerContainer = styled.div`
`; `;
const ServiceListItem = ({ const ServiceListItem = ({
showQuickActions,
onQuickActionsClick = () => {}, onQuickActionsClick = () => {},
onQuickActionsBlur = () => {},
deploymentGroup = '', deploymentGroup = '',
service = {} service = {}
}) => { }) => {
@ -73,10 +69,6 @@ const ServiceListItem = ({
onQuickActionsClick({ service }); onQuickActionsClick({ service });
}; };
const handleQuickActionsBlur = evt => {
onQuickActionsBlur({ show: false });
};
const header = isChild const header = isChild
? null ? null
: <StyledCardHeader> : <StyledCardHeader>
@ -95,12 +87,6 @@ const ServiceListItem = ({
</CardDescription> </CardDescription>
</CardMeta> </CardMeta>
<CardOptions onClick={handleCardOptionsClick} /> <CardOptions onClick={handleCardOptionsClick} />
<ServicesQuickActions
position={{ top: '47px', right: '-98px' }}
service={service}
show={showQuickActions}
onBlur={handleQuickActionsBlur}
/>
</StyledCardHeader>; </StyledCardHeader>;
const view = children const view = children
@ -135,9 +121,7 @@ const ServiceListItem = ({
}; };
ServiceListItem.propTypes = { ServiceListItem.propTypes = {
showQuickActions: PropTypes.bool,
onQuickActionsClick: PropTypes.func, onQuickActionsClick: PropTypes.func,
onQuickActionsBlur: PropTypes.func,
deploymentGroup: PropTypes.string, deploymentGroup: PropTypes.string,
service: PropTypes.object.isRequired // Define better service: PropTypes.object.isRequired // Define better
}; };

View File

@ -2,7 +2,8 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Tooltip, TooltipButton, TooltipDivider } from 'joyent-ui-toolkit'; import { Tooltip, TooltipButton, TooltipDivider } from 'joyent-ui-toolkit';
const ServicesQuickActions = ({ show, position, service, onBlur }) => { const ServicesQuickActions = ({ show, position, service, url, onBlur }) => {
if (!show) { if (!show) {
return null; return null;
} }
@ -16,19 +17,23 @@ const ServicesQuickActions = ({ show, position, service, onBlur }) => {
return p; return p;
}, {}); }, {});
const scaleUrl = `${url}/${service.slug}/scale`;
const deleteUrl = `${url}/${service.slug}/delete`;
return ( return (
<Tooltip {...p} onBlur={onBlur}> <Tooltip {...p} onBlur={onBlur}>
<TooltipButton onClick={() => {}}>Scale</TooltipButton> <TooltipButton to={scaleUrl}>Scale</TooltipButton>
<TooltipButton>Restart</TooltipButton> <TooltipButton>Restart</TooltipButton>
<TooltipButton>Stop</TooltipButton> <TooltipButton>Stop</TooltipButton>
<TooltipDivider /> <TooltipDivider />
<TooltipButton>Delete</TooltipButton> <TooltipButton to={deleteUrl}>Delete</TooltipButton>
</Tooltip> </Tooltip>
); );
}; };
ServicesQuickActions.propTypes = { ServicesQuickActions.propTypes = {
service: PropTypes.object, service: PropTypes.object.isRequired,
url: PropTypes.string.isRequired,
position: PropTypes.object, position: PropTypes.object,
show: PropTypes.bool, show: PropTypes.bool,
onBlur: PropTypes.func onBlur: PropTypes.func

View File

@ -0,0 +1,69 @@
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { compose, graphql, gql } from 'react-apollo';
import ServiceScaleMutation from '@graphql/ServiceScale.gql';
import { Loader, ErrorMessage } from '@components/messaging';
import { ServiceDelete as ServiceDeleteComponent } from '@components/service';
import { Modal } from 'joyent-ui-toolkit';
import ServiceGql from './service-gql';
class ServiceDelete extends PureComponent {
render() {
if (this.props.loading) {
return <Loader />;
}
if (this.props.error) {
return (
<ErrorMessage message="Oops, an error occured while loading your service." />
);
}
const { service, deleteServices, history, match } = this.props;
const handleCloseClick = evt => {
const closeUrl = match.url.split('/').slice(0, -2).join('/');
history.replace(closeUrl);
};
const handleConfirmClick = evt => {
deleteServices(service.id);
};
return (
<Modal width={460} onCloseClick={handleCloseClick}>
<ServiceDeleteComponent
service={service}
onConfirmClick={handleConfirmClick}
onCancelClick={handleCloseClick}
/>
</Modal>
);
}
}
ServiceDelete.propTypes = {
service: PropTypes.object,
history: PropTypes.object,
deleteServices: PropTypes.func.isRequired
};
const DeleteGql = gql`
mutation deleteServices($ids: [ID]!) {
deleteServices(ids: $ids) {
id
slug
}
}
`;
const DeleteServicesGql = graphql(DeleteGql, {
props: ({ mutate }) => ({
deleteServices: serviceId => mutate({ variables: { ids: [serviceId] } })
})
});
const ServiceDeleteWithData = compose(DeleteServicesGql, ServiceGql)(
ServiceDelete
);
export default ServiceDeleteWithData;

View File

@ -0,0 +1,2 @@
export { default as ServiceScale } from './scale';
export { default as ServiceDelete } from './delete';

View File

@ -0,0 +1,64 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { compose, graphql } from 'react-apollo';
import ServiceScaleMutation from '@graphql/ServiceScale.gql';
import { Loader, ErrorMessage } from '@components/messaging';
import { ServiceScale as ServiceScaleComponent } from '@components/service';
import { Modal } from 'joyent-ui-toolkit';
import ServiceGql from './service-gql';
class ServiceScale extends Component {
render() {
if (this.props.loading) {
return <Loader />;
}
if (this.props.error) {
return (
<ErrorMessage message="Oops, an error occured while loading your service." />
);
}
const { service, scale, history, match } = this.props;
const handleCloseClick = evt => {
const closeUrl = match.url.split('/').slice(0, -2).join('/');
history.replace(closeUrl);
};
const handleConfirmClick = evt => {
scale(service.id, 2);
};
return (
<Modal width={460} onCloseClick={handleCloseClick}>
<ServiceScaleComponent
service={service}
onConfirmClick={handleConfirmClick}
onCancelClick={handleCloseClick}
/>
</Modal>
);
}
}
ServiceScale.propTypes = {
service: PropTypes.object,
history: PropTypes.object,
scale: PropTypes.func.isRequired
};
const ServiceScaleGql = graphql(ServiceScaleMutation, {
props: ({ mutate }) => ({
scale: (serviceId, replicas) =>
mutate({
variables: {
serviceId,
replicas
}
})
})
});
const ServiceScaleWithData = compose(ServiceScaleGql, ServiceGql)(ServiceScale);
export default ServiceScaleWithData;

View File

@ -0,0 +1,25 @@
import { graphql } from 'react-apollo';
import InstancesQuery from '@graphql/Instances.gql';
export default graphql(InstancesQuery, {
options(props) {
const params = props.match.params;
const deploymentGroupSlug = params.deploymentGroup;
const serviceSlug = params.service;
return {
variables: {
deploymentGroupSlug,
serviceSlug
}
};
},
props: ({ data: { deploymentGroup, loading, error } }) => ({
service: deploymentGroup &&
deploymentGroup.services &&
deploymentGroup.services.length
? deploymentGroup.services[0]
: null,
loading,
error
})
});

View File

@ -11,11 +11,21 @@ import { LayoutContainer } from '@components/layout';
import { Loader, ErrorMessage } from '@components/messaging'; import { Loader, ErrorMessage } from '@components/messaging';
import { ServiceListItem } from '@components/services'; import { ServiceListItem } from '@components/services';
import { ServicesQuickActions } from '@components/services';
const StyledContainer = styled.div` const StyledContainer = styled.div`
position: relative; position: relative;
`; `;
class ServiceList extends Component { class ServiceList extends Component {
ref(name) {
this._refs = this._refs || {};
return el => {
this._refs[name] = el;
};
}
render() { render() {
const { const {
deploymentGroup, deploymentGroup,
@ -23,7 +33,8 @@ class ServiceList extends Component {
loading, loading,
error, error,
servicesQuickActions, servicesQuickActions,
toggleServicesQuickActions toggleServicesQuickActions,
url
} = this.props; } = this.props;
if (loading) { if (loading) {
@ -40,12 +51,27 @@ class ServiceList extends Component {
); );
} }
const handleQuickActionsClick = o => { const handleQuickActionsClick = (evt, service) => {
toggleServicesQuickActions(o); const list = this._refs.container;
const listRect = list.getBoundingClientRect();
const button = evt.currentTarget;
const buttonRect = button.getBoundingClientRect();
const position = {
left: buttonRect.left -
listRect.left +
(buttonRect.right - buttonRect.left) / 2,
top: buttonRect.bottom - listRect.top
};
toggleServicesQuickActions({
service,
position
});
}; };
const handleQuickActionsBlur = o => { const handleQuickActionsBlur = o => {
toggleServicesQuickActions(o); toggleServicesQuickActions({ show: false });
}; };
const serviceList = services.map(service => const serviceList = services.map(service =>
@ -53,22 +79,22 @@ class ServiceList extends Component {
key={service.id} key={service.id}
deploymentGroup={deploymentGroup.slug} deploymentGroup={deploymentGroup.slug}
service={service} service={service}
showQuickActions={
servicesQuickActions.service &&
servicesQuickActions.service.id === service.id
}
onQuickActionsClick={handleQuickActionsClick} onQuickActionsClick={handleQuickActionsClick}
onQuickActionsBlur={handleQuickActionsBlur}
/> />
); );
return ( return (
<LayoutContainer> <LayoutContainer>
<StyledContainer> <StyledContainer>
<div> <div ref={this.ref('container')}>
{/* <div ref={this.ref('container')}> */}
{serviceList} {serviceList}
{/* <ServicesTooltip {...uiTooltip} onBlur={handleTooltipBlur} /> */} <ServicesQuickActions
position={servicesQuickActions.position}
service={servicesQuickActions.service}
show={servicesQuickActions.show}
url={url}
onBlur={handleQuickActionsBlur}
/>
</div> </div>
</StyledContainer> </StyledContainer>
</LayoutContainer> </LayoutContainer>
@ -77,7 +103,8 @@ class ServiceList extends Component {
} }
const mapStateToProps = (state, ownProps) => ({ const mapStateToProps = (state, ownProps) => ({
servicesQuickActions: state.ui.services.quickActions servicesQuickActions: state.ui.services.quickActions,
url: ownProps.match.url
}); });
const mapDispatchToProps = dispatch => ({ const mapDispatchToProps = dispatch => ({

View File

@ -68,8 +68,10 @@ const ServicesTopology = ({
onNodeTitleClick={handleNodeTitleClick} onNodeTitleClick={handleNodeTitleClick}
/> />
<ServicesQuickActions <ServicesQuickActions
service={servicesQuickActions.service}
show={servicesQuickActions.show} show={servicesQuickActions.show}
position={servicesQuickActions.position} position={servicesQuickActions.position}
url={url}
onBlur={handleTooltipBlur} onBlur={handleTooltipBlur}
/> />
</StyledContainer> </StyledContainer>

View File

@ -0,0 +1,9 @@
mutation scale($serviceId: ID!, $replicas: Int!) {
scale(serviceId: $serviceId, replicas: $replicas) {
scale {
id
serviceName
replicas
}
}
}

View File

@ -2,7 +2,6 @@ import React from 'react';
import { BrowserRouter, Redirect, Route, Switch } from 'react-router-dom'; import { BrowserRouter, Redirect, Route, Switch } from 'react-router-dom';
import { Header, Breadcrumb, Menu } from '@containers/navigation'; import { Header, Breadcrumb, Menu } from '@containers/navigation';
import { InstanceList } from '@containers/instances';
import { import {
DeploymentGroupList, DeploymentGroupList,
@ -15,6 +14,10 @@ import {
ServicesMenu ServicesMenu
} from '@containers/services'; } from '@containers/services';
import { ServiceScale, ServiceDelete } from '@containers/service';
import { InstanceList } from '@containers/instances';
const rootRedirect = p => <Redirect to="/deployment-groups" />; const rootRedirect = p => <Redirect to="/deployment-groups" />;
const deploymentGroupRedirect = p => const deploymentGroupRedirect = p =>
@ -30,7 +33,7 @@ const serviceRedirect = p =>
const Router = ( const Router = (
<BrowserRouter> <BrowserRouter>
<div> <div style={{ position: 'relative' }}>
<Route path="/" component={Header} /> <Route path="/" component={Header} />
@ -82,25 +85,41 @@ const Router = (
<Route <Route
path="/deployment-groups/:deploymentGroup/services-list" path="/deployment-groups/:deploymentGroup/services-list"
exact
component={ServicesMenu} component={ServicesMenu}
/> />
<Route <Route
path="/deployment-groups/:deploymentGroup/services-list" path="/deployment-groups/:deploymentGroup/services-list"
exact
component={ServiceList} component={ServiceList}
/> />
<Route
path="/deployment-groups/:deploymentGroup/services-list/:service/scale"
exact
component={ServiceScale}
/>
<Route
path="/deployment-groups/:deploymentGroup/services-list/:service/delete"
exact
component={ServiceDelete}
/>
<Route <Route
path="/deployment-groups/:deploymentGroup/services-topology" path="/deployment-groups/:deploymentGroup/services-topology"
exact
component={ServicesMenu} component={ServicesMenu}
/> />
<Route <Route
path="/deployment-groups/:deploymentGroup/services-topology" path="/deployment-groups/:deploymentGroup/services-topology"
exact
component={ServicesTopology} component={ServicesTopology}
/> />
<Route
path="/deployment-groups/:deploymentGroup/services-topology/:service/scale"
exact
component={ServiceScale}
/>
<Route
path="/deployment-groups/:deploymentGroup/services-topology/:service/delete"
exact
component={ServiceDelete}
/>
<Route <Route
path="/deployment-groups/:deploymentGroup/services/:service" path="/deployment-groups/:deploymentGroup/services/:service"

View File

@ -8,7 +8,7 @@ export default handleActions(
const s = show === undefined const s = show === undefined
? !state.services.quickActions.service || ? !state.services.quickActions.service ||
service.uuid !== state.services.quickActions.service.uuid service.id !== state.services.quickActions.service.id
: show; : show;
const quickActions = s const quickActions = s

View File

@ -36,6 +36,27 @@ const serviceBySlug = serviceSlug =>
: null : null
); );
const instancesByServiceId = serviceId =>
createSelector(
[apollo],
apollo =>
apollo && apollo.data
? Object.keys(apollo.data).reduce((is, i, k) => {
if (
apollo.data[k].__typename === 'Instance' &&
apollo.data[k].service === serviceId
) {
is.push(apollo.data[k]);
}
return is;
}, [])
: null
);
const serviceWidthInstancesBySlug = serviceSlug => {
const service = serviceBySlug(serviceSlug);
};
// Apollo gql utils // // Apollo gql utils //
const findService = (services, uuid) => const findService = (services, uuid) =>

View File

@ -1,6 +1,6 @@
import { createStore, combineReducers, applyMiddleware, compose } from 'redux'; import { createStore, combineReducers, applyMiddleware, compose } from 'redux';
import { reducer as formReducer } from 'redux-form'; import { reducer as formReducer } from 'redux-form';
// import { enableBatching } from 'redux-batched-actions'; import { enableBatching } from 'redux-batched-actions';
import { ApolloClient, createNetworkInterface } from 'react-apollo'; import { ApolloClient, createNetworkInterface } from 'react-apollo';
import state from './state'; import state from './state';
import { ui } from './reducers'; import { ui } from './reducers';

View File

@ -100,6 +100,21 @@ const createServicesFromManifest = ({ deploymentGroupId, raw }) => {
return Promise.resolve(undefined); return Promise.resolve(undefined);
}; };
const deleteServices = options => getServices({ id: options.ids[0] });
const scale = options => {
const service = getServices({ id: options.serviceId })[0];
return {
scale: [
{
id: service.id,
serviceName: service.name,
replicas: 2
}
]
};
};
module.exports = { module.exports = {
portal: getPortal, portal: getPortal,
deploymentGroups: getDeploymentGroups, deploymentGroups: getDeploymentGroups,
@ -114,5 +129,7 @@ module.exports = {
id: uuid(), id: uuid(),
type: options.type, type: options.type,
format: options.format format: options.format
})) })),
deleteServices: (options, request, fn) => fn(null, deleteServices(options)),
scale: (options, reguest, fn) => fn(null, scale(options))
}; };

View File

@ -1,4 +1,3 @@
scalar Date scalar Date
scalar Object scalar Object

View File

@ -1,13 +0,0 @@
{
"sourceMaps": "inline",
"plugins": [
"styled-components"
],
"env": {
"test": {
"presets": [
"react-app"
]
}
}
}

View File

@ -1,3 +0,0 @@
.nyc_output
coverage
dist

View File

@ -1,3 +0,0 @@
{
"extends": "joyent-portal"
}

View File

@ -1,5 +0,0 @@
{
"syntax": "scss",
"processors": ["stylelint-processor-styled-components"],
"extends": ["stylelint-config-standard", "stylelint-config-primer"]
}

View File

@ -1,10 +0,0 @@
{
"libs": [
"ecmascript"
],
"plugins": {
"doc_comment": true,
"local-scope": true,
"node": true
}
}

View File

@ -1,13 +0,0 @@
# Change Log
All notable changes to this project will be documented in this file.
See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
<a name="1.0.5"></a>
## 1.0.5 (2017-05-25)
<a name="1.0.4"></a>
## 1.0.4 (2017-05-25)

View File

@ -1,64 +0,0 @@
# normalized-styled-components
[![License: MPL 2.0](https://img.shields.io/badge/License-MPL%202.0-brightgreen.svg)](https://opensource.org/licenses/MPL-2.0)
[![npm](https://img.shields.io/npm/v/normalized-styled-components.svg)](https://npmjs.com/package/normalized-styled-components)
[![standard-readme compliant](https://img.shields.io/badge/standard--readme-OK-green.svg)](https://github.com/RichardLitt/standard-readme)
[`normalize.css`](https://github.com/necolas/normalize.css) with a [`styled-components`](https://github.com/styled-components/styled-components) mindset.
## Table of Contents
- [Install](#install)
- [Usage](#usage)
- [License](#license)
## Install
```
yarn add --dev normalized-styled-components
```
## Usage
```js
import { Button } from 'normalized-styled-components';
export default () => (
<Button>Click Here!</Button>
)
```
```css
.jdhBdT {
font-family: sans-serif;
font-size: 100%;
line-height: 1.15;
margin: 0;
overflow: visible;
text-transform: none;
appearance: button;
-moz-appearance: button;
-webkit-appearance: button;
}
.jdhBdT::-moz-focus-inner,
.jdhBdT[type="button"]::-moz-focus-inner,
.jdhBdT[type="reset"]::-moz-focus-inner,
.jdhBdT[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
.jdhBdT:-moz-focusring,
.jdhBdT[type="button"]:-moz-focusring,
.jdhBdT[type="reset"]:-moz-focusring,
.jdhBdT[type="submit"]:-moz-focusring {
outline: 0.0625rem dotted ButtonText;
}
```
```html
<button className="bgTKnx">Click Here!</button>
```
## License
MPL-2.0

View File

@ -1,79 +0,0 @@
{
"name": "normalized-styled-components",
"version": "1.0.5",
"license": "MPL-2.0",
"description": "normalize.css with a styled-components mindset",
"keywords": [
"normalizations",
"style",
"css",
"react",
"css",
"css-in-js",
"styled-components"
],
"repository": "github:yldio/joyent-portal",
"main": "dist/normalized-styled-components.umd.js",
"jsnext:main": "dist/normalized-styled-components.es.js",
"module": "dist/normalized-styled-components.es.js",
"entry": "src/index.js",
"scripts": {
"lint:css": "echo 0",
"lint-ci:css": "echo 0",
"lint:js": "eslint . --fix",
"lint-ci:js": "eslint . --format junit --output-file $CIRCLE_TEST_REPORTS/lint/normalized-styled-components.xml",
"lint": "redrun -s lint:*",
"lint-ci": "redrun -p lint-ci:*",
"test": "bup && NODE_ENV=test jest --coverage",
"test-ci": "NODE_ENV=test JEST_JUNIT_OUTPUT=$CIRCLE_TEST_REPORTS/test/normalized-styled-components.xml jest --coverage --coverageDirectory=$CIRCLE_ARTIFACTS/normalized-styled-components --testResultsProcessor=$(node -e \"console.log(require.resolve('jest-junit'))\")",
"build": "bup",
"prepublish": "redrun build"
},
"dependencies": {
"remcalc": "^1.0.8"
},
"devDependencies": {
"babel-plugin-styled-components": "^1.1.4",
"babel-preset-react-app": "^3.0.0",
"bup": "^1.0.9",
"chalk": "^1.1.3",
"eslint": "^3.19.0",
"eslint-config-joyent-portal": "1.0.0",
"jest": "^20.0.4",
"jest-diff": "^20.0.3",
"jest-junit": "^1.5.1",
"jest-matcher-utils": "^20.0.3",
"jest-snapshot": "^20.0.3",
"jest-styled-components": "^3.0.0-2",
"react": "^15.5.4",
"react-scripts": "^1.0.7",
"react-test-renderer": "^15.5.4",
"redrun": "^5.9.14",
"strip-ansi": "^3.0.1",
"styled-components": "^2.0.1",
"stylelint": "^7.11.0",
"stylelint-config-primer": "^1.4.0",
"stylelint-config-standard": "^16.0.0",
"stylelint-processor-styled-components": "styled-components/stylelint-processor-styled-components#68b4c4f"
},
"peerDependencies": {
"react": "*",
"styled-components": "*"
},
"jest": {
"testEnvironment": "jsdom",
"testRegex": "test/index.js",
"setupFiles": [
"<rootDir>/node_modules/react-scripts/config/polyfills.js"
],
"testEnvironment": "node",
"transform": {
"^.+\\.(js|jsx)$": "<rootDir>/node_modules/react-scripts/config/jest/babelTransform.js",
"^(?!.*\\.(js|jsx|css|json)$)": "<rootDir>/node_modules/react-scripts/config/jest/fileTransform.js"
},
"transformIgnorePatterns": [
"[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$"
],
"rootDir": "."
}
}

View File

@ -1,259 +0,0 @@
import styled from 'styled-components';
import remcalc from 'remcalc';
export const Article = styled.article`
display: block;
`;
export const Aside = styled.aside`
display: block;
`;
export const Footer = styled.footer`
display: block;
`;
export const Header = styled.header`
display: block;
`;
export const Nav = styled.nav`
display: block;
`;
export const Section = styled.section`
display: block;
`;
export const FigCaption = styled.figcaption`
display: block;
`;
export const Figure = styled.figure`
display: block;
margin: ${remcalc(16)} ${remcalc(40)};
`;
export const Main = styled.main`
display: block;
`;
export const H1 = styled.h1`
font-size: ${remcalc(32)};
margin: ${remcalc(10)} 0;
`;
export const Hr = styled.hr`
box-sizing: content-box;
height: 0;
overflow: visible;
`;
export const Pre = styled.pre`
font-family: monospace, monospace;
font-size: ${remcalc(16)};
`;
export const A = styled.a`
background-color: transparent;
text-decoration-skip: objects;
`;
export const Abbr = styled.abbr`
&[title] {
border-bottom: none;
text-decoration: underline;
text-decoration: underline dotted;
}
`;
export const B = styled.b`
font-weight: bolder;
`;
export const Strong = styled.strong`
font-weight: bolder;
`;
export const Code = styled.code`
font-family: monospace, monospace;
font-size: ${remcalc(16)};
`;
export const Kbd = styled.kbd`
font-family: monospace, monospace;
font-size: ${remcalc(16)};
`;
export const Samp = styled.samp`
font-family: monospace, monospace;
font-size: ${remcalc(16)};
`;
export const Dfn = styled.dfn`
font-style: italic;
`;
export const Mark = styled.mark`
background-color: #ff0;
color: #000;
`;
export const Small = styled.small`
font-size: 80%;
`;
export const Sub = styled.sub`
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
bottom: -0.25em;
`;
export const Sup = styled.sup`
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
top: -0.5em;
`;
export const Audio = styled.audio`
display: inline-block;
&:not([controls]) {
display: none;
height: 0;
}
`;
export const Video = styled.video`
display: inline-block;
`;
export const Img = styled.img`
border-style: none;
`;
export const Svg = styled.svg`
&:not(:root) {
overflow: hidden;
}
`;
export const Button = styled.button`
font-family: sans-serif;
font-size: 100%;
line-height: 1.15;
margin: 0;
overflow: visible;
text-transform: none;
appearance: button;
&::-moz-focus-inner,
&[type="button"]::-moz-focus-inner,
&[type="reset"]::-moz-focus-inner,
&[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
&:-moz-focusring,
&[type="button"]:-moz-focusring,
&[type="reset"]:-moz-focusring,
&[type="submit"]:-moz-focusring {
outline: ${remcalc(1)} dotted ButtonText;
}
`;
export const Input = styled.input`
font-family: sans-serif;
font-size: 100%;
line-height: 1.15;
margin: 0;
overflow: visible;
&[type="checkbox"],
&[type="radio"] {
box-sizing: border-box;
padding: 0;
}
&[type="number"]::-webkit-inner-spin-button,
&[type="number"]::-webkit-outer-spin-button {
height: auto;
}
&[type="search"] {
appearance: textfield;
outline-offset: ${remcalc(-2)};
}
&[type="search"]::-webkit-search-cancel-button,
&[type="search"]::-webkit-search-decoration {
appearance: none;
}
&::-webkit-file-upload-button {
appearance: button;
font: inherit;
}
`;
export const Optgroup = styled.optgroup`
font-family: sans-serif;
font-size: 100%;
line-height: 1.15;
margin: 0;
`;
export const Select = styled.select`
font-family: sans-serif;
font-size: 100%;
line-height: 1.15;
margin: 0;
text-transform: none;
`;
export const Textarea = styled.textarea`
font-family: sans-serif;
font-size: 100%;
line-height: 1.15;
margin: 0;
overflow: auto;
`;
export const Fieldset = styled.fieldset`
padding: 0.35em 0.75em 0.625em;
`;
export const Legend = styled.legend`
box-sizing: border-box;
color: inherit;
display: table;
max-width: 100%;
padding: 0;
white-space: normal;
`;
export const Progress = styled.progress`
display: inline-block;
vertical-align: baseline;
`;
export const Details = styled.details`
display: block;
`;
export const Menu = styled.menu`
display: block;
`;
export const Summary = styled.summary`
display: list-item;
`;
export const Canvas = styled.canvas`
display: inline-block;
`;

View File

@ -1,476 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders <A /> correctly 1`] = `
.jleQxG {
background-color: transparent;
-webkit-text-decoration-skip: objects;
text-decoration-skip: objects;
}
<a
className="sc-gqjmRU jleQxG"
/>
`;
exports[`renders <Abbr /> correctly 1`] = `
<abbr
className="sc-VigVT ijOVMO"
/>
`;
exports[`renders <Article /> correctly 1`] = `
.fpcbkF {
display: block;
}
<article
className="sc-bdVaJa fpcbkF"
/>
`;
exports[`renders <Aside /> correctly 1`] = `
.gbieAY {
display: block;
}
<aside
className="sc-bwzfXH gbieAY"
/>
`;
exports[`renders <Audio /> correctly 1`] = `
.SYMpT {
display: inline-block;
}
.SYMpT:not([controls]) {
display: none;
height: 0;
}
<audio
className="sc-ckVGcZ SYMpT"
/>
`;
exports[`renders <B /> correctly 1`] = `
.vhpOG {
font-weight: bolder;
}
<b
className="sc-jTzLTM vhpOG"
/>
`;
exports[`renders <Button /> correctly 1`] = `
.efaqoE {
font-family: sans-serif;
font-size: 100%;
line-height: 1.15;
margin: 0;
overflow: visible;
-webkit-text-transform: none;
text-transform: none;
-webkit-appearance: button;
-moz-appearance: button;
appearance: button;
}
.efaqoE::-moz-focus-inner,
.efaqoE[type="button"]::-moz-focus-inner,
.efaqoE[type="reset"]::-moz-focus-inner,
.efaqoE[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
.efaqoE:-moz-focusring,
.efaqoE[type="button"]:-moz-focusring,
.efaqoE[type="reset"]:-moz-focusring,
.efaqoE[type="submit"]:-moz-focusring {
outline: 0.0625rem dotted ButtonText;
}
<button
className="sc-kEYyzF efaqoE"
/>
`;
exports[`renders <Canvas /> correctly 1`] = `
.gIGqrW {
display: inline-block;
}
<canvas
className="sc-gPEVay gIGqrW"
/>
`;
exports[`renders <Code /> correctly 1`] = `
.NmzmU {
font-family: monospace, monospace;
font-size: 1rem;
}
<code
className="sc-jzJRlG NmzmU"
/>
`;
exports[`renders <Details /> correctly 1`] = `
.kSeyxS {
display: block;
}
<details
className="sc-cMljjf kSeyxS"
/>
`;
exports[`renders <Dfn /> correctly 1`] = `
.lcACZG {
font-style: italic;
}
<dfn
className="sc-chPdSV lcACZG"
/>
`;
exports[`renders <Fieldset /> correctly 1`] = `
.dLqrpE {
padding: 0.35em 0.75em 0.625em;
}
<fieldset
className="sc-cvbbAY dLqrpE"
/>
`;
exports[`renders <FigCaption /> correctly 1`] = `
.fGYiaS {
display: block;
}
<figcaption
className="sc-bZQynM fGYiaS"
/>
`;
exports[`renders <Figure /> correctly 1`] = `
.fpLcXm {
display: block;
margin: 1rem 2.5rem;
}
<figure
className="sc-gzVnrw fpLcXm"
/>
`;
exports[`renders <Footer /> correctly 1`] = `
.dMAkQL {
display: block;
}
<footer
className="sc-htpNat dMAkQL"
/>
`;
exports[`renders <H1 /> correctly 1`] = `
.itlxbG {
font-size: 2rem;
margin: 0.625rem 0;
}
<h1
className="sc-dnqmqq itlxbG"
/>
`;
exports[`renders <Header /> correctly 1`] = `
.imCjfa {
display: block;
}
<header
className="sc-bxivhb imCjfa"
/>
`;
exports[`renders <Hr /> correctly 1`] = `
.jvTISp {
box-sizing: content-box;
height: 0;
overflow: visible;
}
<hr
className="sc-iwsKbI jvTISp"
/>
`;
exports[`renders <Img /> correctly 1`] = `
.gLFqHa {
border-style: none;
}
<img
className="sc-eNQAEJ gLFqHa"
/>
`;
exports[`renders <Input /> correctly 1`] = `
.gtmtGl {
font-family: sans-serif;
font-size: 100%;
line-height: 1.15;
margin: 0;
overflow: visible;
}
.gtmtGl::-webkit-file-upload-button {
-webkit-appearance: button;
-moz-appearance: button;
appearance: button;
font: inherit;
}
<input
className="sc-kkGfuU gtmtGl"
/>
`;
exports[`renders <Kbd /> correctly 1`] = `
.cNQErp {
font-family: monospace, monospace;
font-size: 1rem;
}
<kbd
className="sc-cSHVUG cNQErp"
/>
`;
exports[`renders <Legend /> correctly 1`] = `
.iBvQlR {
box-sizing: border-box;
color: inherit;
display: table;
max-width: 100%;
padding: 0;
white-space: normal;
}
<legend
className="sc-jWBwVP iBvQlR"
/>
`;
exports[`renders <Main /> correctly 1`] = `
.kGbKV {
display: block;
}
<main
className="sc-htoDjs kGbKV"
/>
`;
exports[`renders <Mark /> correctly 1`] = `
.gUcHXP {
background-color: #ff0;
color: #000;
}
<mark
className="sc-kgoBCf gUcHXP"
/>
`;
exports[`renders <Menu /> correctly 1`] = `
.EtDOy {
display: block;
}
<menu
className="sc-jAaTju EtDOy"
/>
`;
exports[`renders <Nav /> correctly 1`] = `
.kXFzZl {
display: block;
}
<nav
className="sc-ifAKCX kXFzZl"
/>
`;
exports[`renders <Optgroup /> correctly 1`] = `
.bwvGAC {
font-family: sans-serif;
font-size: 100%;
line-height: 1.15;
margin: 0;
}
<optgroup
className="sc-iAyFgw bwvGAC"
/>
`;
exports[`renders <Pre /> correctly 1`] = `
.ePyiae {
font-family: monospace, monospace;
font-size: 1rem;
}
<pre
className="sc-gZMcBi ePyiae"
/>
`;
exports[`renders <Progress /> correctly 1`] = `
.irOoVX {
display: inline-block;
vertical-align: baseline;
}
<progress
className="sc-brqgnP irOoVX"
/>
`;
exports[`renders <Samp /> correctly 1`] = `
.brPjlW {
font-family: monospace, monospace;
font-size: 1rem;
}
<samp
className="sc-kAzzGY brPjlW"
/>
`;
exports[`renders <Section /> correctly 1`] = `
.kyfnqM {
display: block;
}
<section
className="sc-EHOje kyfnqM"
/>
`;
exports[`renders <Select /> correctly 1`] = `
.kskmSD {
font-family: sans-serif;
font-size: 100%;
line-height: 1.15;
margin: 0;
-webkit-text-transform: none;
text-transform: none;
}
<select
className="sc-hSdWYo kskmSD"
/>
`;
exports[`renders <Small /> correctly 1`] = `
.eNDzVi {
font-size: 80%;
}
<small
className="sc-kGXeez eNDzVi"
/>
`;
exports[`renders <Strong /> correctly 1`] = `
.liZvtt {
font-weight: bolder;
}
<strong
className="sc-fjdhpX liZvtt"
/>
`;
exports[`renders <Sub /> correctly 1`] = `
.bfYNTw {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
bottom: -0.25em;
}
<sub
className="sc-kpOJdX bfYNTw"
/>
`;
exports[`renders <Summary /> correctly 1`] = `
.chrtFK {
display: list-item;
}
<summary
className="sc-jDwBTQ chrtFK"
/>
`;
exports[`renders <Sup /> correctly 1`] = `
.hZcmXd {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
top: -0.5em;
}
<sup
className="sc-dxgOiQ hZcmXd"
/>
`;
exports[`renders <Svg /> correctly 1`] = `
.GnRoM:not(:root) {
overflow: hidden;
}
<svg
className="sc-hMqMXs GnRoM"
/>
`;
exports[`renders <Textarea /> correctly 1`] = `
.bDTEgL {
font-family: sans-serif;
font-size: 100%;
line-height: 1.15;
margin: 0;
overflow: auto;
}
<textarea
className="sc-eHgmQL bDTEgL"
/>
`;
exports[`renders <Video /> correctly 1`] = `
.bkGlpl {
display: inline-block;
}
<video
className="sc-jKJlTe bkGlpl"
/>
`;

View File

@ -1,246 +0,0 @@
import React from 'react';
import renderer from 'react-test-renderer';
import 'jest-styled-components';
import {
Article,
Aside,
Footer,
Header,
Nav,
Section,
FigCaption,
Figure,
Main,
H1,
Hr,
Pre,
A,
Abbr,
B,
Strong,
Code,
Kbd,
Samp,
Dfn,
Mark,
Small,
Sub,
Sup,
Audio,
Video,
Img,
Svg,
Button,
Input,
Optgroup,
Select,
Textarea,
Fieldset,
Legend,
Progress,
Details,
Menu,
Summary,
Canvas
} from '../src/';
it('renders <Article /> correctly', () => {
const tree = renderer.create(<Article />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Aside /> correctly', () => {
const tree = renderer.create(<Aside />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Footer /> correctly', () => {
const tree = renderer.create(<Footer />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Header /> correctly', () => {
const tree = renderer.create(<Header />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Nav /> correctly', () => {
const tree = renderer.create(<Nav />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Section /> correctly', () => {
const tree = renderer.create(<Section />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <FigCaption /> correctly', () => {
const tree = renderer.create(<FigCaption />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Figure /> correctly', () => {
const tree = renderer.create(<Figure />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Main /> correctly', () => {
const tree = renderer.create(<Main />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <H1 /> correctly', () => {
const tree = renderer.create(<H1 />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Hr /> correctly', () => {
const tree = renderer.create(<Hr />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Pre /> correctly', () => {
const tree = renderer.create(<Pre />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <A /> correctly', () => {
const tree = renderer.create(<A />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Abbr /> correctly', () => {
const tree = renderer.create(<Abbr />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <B /> correctly', () => {
const tree = renderer.create(<B />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Strong /> correctly', () => {
const tree = renderer.create(<Strong />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Code /> correctly', () => {
const tree = renderer.create(<Code />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Kbd /> correctly', () => {
const tree = renderer.create(<Kbd />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Samp /> correctly', () => {
const tree = renderer.create(<Samp />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Dfn /> correctly', () => {
const tree = renderer.create(<Dfn />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Mark /> correctly', () => {
const tree = renderer.create(<Mark />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Small /> correctly', () => {
const tree = renderer.create(<Small />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Sub /> correctly', () => {
const tree = renderer.create(<Sub />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Sup /> correctly', () => {
const tree = renderer.create(<Sup />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Audio /> correctly', () => {
const tree = renderer.create(<Audio />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Video /> correctly', () => {
const tree = renderer.create(<Video />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Img /> correctly', () => {
const tree = renderer.create(<Img />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Svg /> correctly', () => {
const tree = renderer.create(<Svg />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Button /> correctly', () => {
const tree = renderer.create(<Button />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Input /> correctly', () => {
const tree = renderer.create(<Input />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Optgroup /> correctly', () => {
const tree = renderer.create(<Optgroup />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Select /> correctly', () => {
const tree = renderer.create(<Select />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Textarea /> correctly', () => {
const tree = renderer.create(<Textarea />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Fieldset /> correctly', () => {
const tree = renderer.create(<Fieldset />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Legend /> correctly', () => {
const tree = renderer.create(<Legend />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Progress /> correctly', () => {
const tree = renderer.create(<Progress />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Details /> correctly', () => {
const tree = renderer.create(<Details />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Menu /> correctly', () => {
const tree = renderer.create(<Menu />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Summary /> correctly', () => {
const tree = renderer.create(<Summary />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});
it('renders <Canvas /> correctly', () => {
const tree = renderer.create(<Canvas />).toJSON();
expect(tree).toMatchStyledComponentsSnapshot();
});

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +0,0 @@
.nyc_output
coverage
dist

View File

@ -1,3 +0,0 @@
{
"extends": "joyent-portal"
}

View File

@ -1,10 +0,0 @@
{
"libs": [
"ecmascript"
],
"plugins": {
"doc_comment": true,
"local-scope": true,
"node": true
}
}

View File

@ -1,13 +0,0 @@
# Change Log
All notable changes to this project will be documented in this file.
See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
<a name="1.0.5"></a>
## 1.0.5 (2017-05-25)
<a name="1.0.4"></a>
## 1.0.4 (2017-05-25)

View File

@ -1,63 +0,0 @@
# remcalc
[![License: MPL 2.0](https://img.shields.io/badge/License-MPL%202.0-brightgreen.svg)](https://opensource.org/licenses/MPL-2.0)
[![npm](https://img.shields.io/npm/v/remcalc.svg)](https://npmjs.com/package/remcalc)
[![standard-readme compliant](https://img.shields.io/badge/standard--readme-OK-green.svg)](https://github.com/RichardLitt/standard-readme)
Calculate the `rem`'s from `px` values.
## Table of Contents
- [Install](#install)
- [Usage](#usage)
- [License](#license)
## Install
```
yarn add --dev remcalc
```
## Usage
```js
import remcalc from 'remcalc';
import assert from 'assert';
assert.deepEqual(remcalc.withBase(10, 1, 2, 3, 4), '0.1rem 0.2rem 0.3rem 0.4rem');
assert.deepEqual(remcalc('1'), '0.0625rem');
assert.deepEqual(remcalc('1px'), '0.0625rem');
assert.deepEqual(remcalc.withBase(10, '1px'), '0.1rem');
assert.deepEqual(
remcalc('1', '2', '3', '4'),
'0.0625rem 0.125rem 0.1875rem 0.25rem'
);
assert.deepEqual(
remcalc('1px', '2px', '3px', '4px'),
'0.0625rem 0.125rem 0.1875rem 0.25rem'
);
assert.deepEqual(
remcalc.withBase(10, '1', '2', '3', '4'),
'0.1rem 0.2rem 0.3rem 0.4rem'
);
assert.deepEqual(
remcalc.withBase(10, '1px', '2px', '3px', '4px'),
'0.1rem 0.2rem 0.3rem 0.4rem'
);
assert.deepEqual(remcalc('1 2 3 4'), '0.0625rem 0.125rem 0.1875rem 0.25rem');
assert.deepEqual(remcalc.withBase(10, '1 2 3 4'), '0.1rem 0.2rem 0.3rem 0.4rem');
```
## License
MPL-2.0

View File

@ -1,72 +0,0 @@
{
"name": "remcalc",
"version": "1.0.5",
"license": "MPL-2.0",
"description": "Calculate the `rem`'s from `px` values",
"keywords": [
"calc",
"rem",
"em",
"px",
"pixels",
"pixel"
],
"repository": "github:yldio/joyent-portal",
"main": "dist/remcalc.umd.js",
"jsnext:main": "dist/remcalc.es.js",
"module": "dist/remcalc.es.js",
"entry": "src/index.js",
"scripts": {
"lint": "eslint . --fix",
"lint-ci": "eslint . --format junit --output-file $CIRCLE_TEST_REPORTS/lint/remcalc.xml",
"test": "bup && cross-env NODE_ENV=test nyc --reporter=lcov --reporter=text ava",
"test-ci": "cross-env NODE_ENV=test nyc --report-dir=$CIRCLE_ARTIFACTS/remcalc --reporter=lcov --reporter=text ava --tap | tap-xunit > $CIRCLE_TEST_REPORTS/test/remcalc.xml",
"build": "bup",
"prepublish": "bup"
},
"dependencies": {
"lodash.flatten": "^4.4.0"
},
"devDependencies": {
"ava": "0.19.1",
"babel-plugin-istanbul": "^4.1.4",
"babel-plugin-transform-es2015-arrow-functions": "^6.22.0",
"babel-plugin-transform-es2015-parameters": "^6.24.1",
"babel-plugin-transform-es2015-spread": "^6.22.0",
"babel-plugin-transform-es2015-template-literals": "^6.22.0",
"babel-register": "^6.24.1",
"bup": "^1.0.9",
"cross-env": "^5.0.1",
"eslint": "^3.19.0",
"eslint-config-joyent-portal": "1.0.0",
"nyc": "^11.0.2",
"tap-xunit": "^1.7.0"
},
"nyc": {
"sourceMap": false,
"instrument": false
},
"babel": {
"sourceMaps": "inline",
"plugins": [
"transform-es2015-parameters",
"transform-es2015-template-literals",
"transform-es2015-arrow-functions",
"transform-es2015-spread"
],
"env": {
"test": {
"plugins": [
"istanbul"
]
}
}
},
"ava": {
"tap": true,
"require": [
"babel-register"
],
"babel": "inherit"
}
}

View File

@ -1,11 +0,0 @@
const flatten = require('lodash.flatten');
const BASE = 16;
const calc = (base, ...values) =>
flatten(values.map(value => String(value).split(/\s/gim)))
.map(value => `${Number(value.replace('px', '')) / base}rem`)
.join(' ');
module.exports = (...values) => calc(BASE, ...values);
module.exports.withBase = calc;

View File

@ -1,40 +0,0 @@
const test = require('ava');
const remcalc = require('../');
test('with multiple num arguments', t => {
t.deepEqual(remcalc(1, 2, 3, 4), '0.0625rem 0.125rem 0.1875rem 0.25rem');
t.deepEqual(remcalc.withBase(10, 1, 2, 3, 4), '0.1rem 0.2rem 0.3rem 0.4rem');
});
test('with single str argument', t => {
t.deepEqual(remcalc('1'), '0.0625rem');
t.deepEqual(remcalc('1px'), '0.0625rem');
t.deepEqual(remcalc.withBase(10, '1px'), '0.1rem');
});
test('with multiple str arguments', t => {
t.deepEqual(
remcalc('1', '2', '3', '4'),
'0.0625rem 0.125rem 0.1875rem 0.25rem'
);
t.deepEqual(
remcalc('1px', '2px', '3px', '4px'),
'0.0625rem 0.125rem 0.1875rem 0.25rem'
);
t.deepEqual(
remcalc.withBase(10, '1', '2', '3', '4'),
'0.1rem 0.2rem 0.3rem 0.4rem'
);
t.deepEqual(
remcalc.withBase(10, '1px', '2px', '3px', '4px'),
'0.1rem 0.2rem 0.3rem 0.4rem'
);
});
test('with single str argument spaced', t => {
t.deepEqual(remcalc('1 2 3 4'), '0.0625rem 0.125rem 0.1875rem 0.25rem');
t.deepEqual(remcalc.withBase(10, '1 2 3 4'), '0.1rem 0.2rem 0.3rem 0.4rem');
});

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +0,0 @@
.nyc_output
coverage
dist

View File

@ -1,3 +0,0 @@
{
"extends": "joyent-portal"
}

View File

@ -1,10 +0,0 @@
{
"libs": [
"ecmascript"
],
"plugins": {
"doc_comment": true,
"local-scope": true,
"node": true
}
}

View File

@ -1,13 +0,0 @@
# Change Log
All notable changes to this project will be documented in this file.
See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
<a name="1.0.5"></a>
## 1.0.5 (2017-05-25)
<a name="1.0.4"></a>
## 1.0.4 (2017-05-25)

View File

@ -1,36 +0,0 @@
# rnd-id
[![License: MPL 2.0](https://img.shields.io/badge/License-MPL%202.0-brightgreen.svg)](https://opensource.org/licenses/MPL-2.0)
[![npm](https://img.shields.io/npm/v/rnd-id.svg)](https://npmjs.com/package/rnd-id)
[![standard-readme compliant](https://img.shields.io/badge/standard--readme-OK-green.svg)](https://github.com/RichardLitt/standard-readme)
Generate a random alphabetical string.
## Table of Contents
- [Install](#install)
- [Usage](#usage)
- [License](#license)
## Install
```
yarn add --dev rnd-id
```
## Usage
```js
const rndId = require('rnd-id');
console.log(rndId()) // kbtpZ
console.log(rndId()) // cuBuLn
console.log(rndId()) // sPwzn
console.log(rndId()) // kKUko
console.log(rndId()) // czzpgR
console.log(rndId()) // cjtzdI
```
## License
MPL-2.0

View File

@ -1,65 +0,0 @@
{
"name": "rnd-id",
"version": "1.0.5",
"license": "MPL-2.0",
"description": "Generate a random alpha string",
"keywords": [
"random",
"alphabetical"
],
"repository": "github:yldio/joyent-portal",
"main": "dist/rnd-id.umd.js",
"jsnext:main": "dist/rnd-id.es.js",
"module": "dist/rnd-id.es.js",
"entry": "src/index.js",
"scripts": {
"lint": "eslint . --fix",
"lint-ci": "eslint . --format junit --output-file $CIRCLE_TEST_REPORTS/lint/rnd-id.xml",
"test": "bup && cross-env NODE_ENV=test nyc --reporter=lcov --reporter=text ava",
"test-ci": "cross-env NODE_ENV=test nyc --report-dir=$CIRCLE_ARTIFACTS/rnd-id --reporter=lcov --reporter=text ava --tap | tap-xunit > $CIRCLE_TEST_REPORTS/test/rnd-id.xml",
"build": "bup",
"prepublish": "bup"
},
"dependencies": {
"random-natural": "^1.0.3"
},
"devDependencies": {
"ava": "0.19.1",
"babel-plugin-istanbul": "^4.1.4",
"babel-plugin-transform-es2015-arrow-functions": "^6.22.0",
"babel-plugin-transform-es2015-template-literals": "^6.22.0",
"babel-register": "^6.24.1",
"bup": "^1.0.9",
"cross-env": "^5.0.1",
"eslint": "^3.19.0",
"eslint-config-joyent-portal": "1.0.0",
"lodash.uniq": "^4.5.0",
"nyc": "^11.0.2",
"tap-xunit": "^1.7.0"
},
"nyc": {
"sourceMap": false,
"instrument": false
},
"babel": {
"sourceMaps": "inline",
"plugins": [
"transform-es2015-arrow-functions",
"transform-es2015-template-literals"
],
"env": {
"test": {
"plugins": [
"istanbul"
]
}
}
},
"ava": {
"tap": true,
"require": [
"babel-register"
],
"babel": "inherit"
}
}

View File

@ -1,15 +0,0 @@
const randomNatural = require('random-natural');
// From https://github.com/styled-components/styled-components/blob/065001c725744629c7870240e4a955b924ef5337/src/utils/generateAlphabeticName.js
const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
const rndId = _code => {
const code = _code ? _code : randomNatural({ min: 1000000000 });
const lastDigit = chars[code % chars.length];
return code > chars.length
? `${rndId(Math.floor(code / chars.length))}${lastDigit}`
: lastDigit;
};
module.exports = rndId;

View File

@ -1,17 +0,0 @@
const test = require('ava');
const uniq = require('lodash.uniq');
const rndId = require('../');
test('should generate strings', t => {
t.truthy(
[rndId(), rndId(), rndId(), rndId()].every(
s => typeof s === 'string' && s.length
)
);
});
test('should generate unique strings', t => {
const arr = [rndId(), rndId(), rndId(), rndId()];
t.deepEqual(uniq(arr).length, arr.length);
});

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +0,0 @@
.nyc_output
coverage
dist

View File

@ -1,3 +0,0 @@
{
"extends": "joyent-portal"
}

View File

@ -1,10 +0,0 @@
{
"libs": [
"ecmascript"
],
"plugins": {
"doc_comment": true,
"local-scope": true,
"node": true
}
}

View File

@ -1,23 +0,0 @@
# Change Log
All notable changes to this project will be documented in this file.
See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
<a name="1.0.7"></a>
## 1.0.7 (2017-05-25)
### Bug Fixes
* **styled-is:** correct package entrypoints ([44a2f2e](https://github.com/yldio/joyent-portal/commit/44a2f2e))
<a name="1.0.6"></a>
## 1.0.6 (2017-05-25)
### Bug Fixes
* **styled-is:** correct package entrypoints ([44a2f2e](https://github.com/yldio/joyent-portal/commit/44a2f2e))

View File

@ -1,91 +0,0 @@
# styled-is
[![License: MPL 2.0](https://img.shields.io/badge/License-MPL%202.0-brightgreen.svg)](https://opensource.org/licenses/MPL-2.0)
[![npm](https://img.shields.io/npm/v/styled-is.svg)](https://npmjs.com/package/styled-is)
[![standard-readme compliant](https://img.shields.io/badge/standard--readme-OK-green.svg)](https://github.com/RichardLitt/standard-readme)
Flag utility for [`styled-components`](https://github.com/styled-components/styled-components).
## Table of Contents
- [Install](#install)
- [Usage](#usage)
- [License](#license)
## Install
```
yarn add --dev styled-is
```
## Usage
```js
import is, { isNot, isOr, isSomeNot } from 'styled-is';
import styled from 'styled-components';
const Div = styled.div`
display: block;
opacity: 0;
${is('red')`
background-color: red;
`};
${is('blue')`
background-color: blue;
`};
${is('red', 'blue')`
opacity: 1;
`};
${is('left')`
float: left;
`};
${is('right')`
float: right;
`};
${isNot('left', 'right')`
float: center;
`};
${isOr('left', 'right')`
position: relative;
`};
${isSomeNot('red', 'left')`
wat: 1;
`};
`;
```
```js
// display: block;
// opacity: 0;
// float: center;
// wat: 1;
<Div>
// display: block;
// opacity: 0;
// background-color: red;
// opacity: 1;
// float: center;
// wat: 1;
<Div red>
// display: block;
// opacity: 0;
// background-color: red;
// opacity: 1;
// float: left;
// position: relative;
<Div red left>
```
## License
MPL-2.0

View File

@ -1,78 +0,0 @@
{
"name": "styled-is",
"version": "1.0.7",
"license": "MPL-2.0",
"description": "Flag utility for styled-components",
"keywords": [
"flag",
"flags",
"react",
"css",
"css-in-js",
"styled-components"
],
"repository": "github:yldio/joyent-portal",
"main": "dist/styled-is.umd.js",
"jsnext:main": "dist/styled-is.es.js",
"module": "dist/styled-is.es.js",
"entry": "src/index.js",
"scripts": {
"lint": "eslint . --fix",
"lint-ci": "eslint . --format junit --output-file $CIRCLE_TEST_REPORTS/lint/styled-is.xml",
"test:run": "cross-env NODE_ENV=test nyc --reporter=lcov --reporter=text ava",
"test-ci:run": "cross-env NODE_ENV=test nyc --report-dir=$CIRCLE_ARTIFACTS/styled-is --reporter=lcov --reporter=text ava --tap | tap-xunit > $CIRCLE_TEST_REPORTS/test/styled-is.xml",
"test": "redrun -s build test:run",
"test-ci": "redrun -s build test-ci:run",
"build": "bup",
"prepublish": "redrun build"
},
"devDependencies": {
"ava": "0.19.1",
"babel-plugin-istanbul": "^4.1.4",
"babel-plugin-transform-es2015-arrow-functions": "^6.22.0",
"babel-plugin-transform-es2015-parameters": "^6.24.1",
"babel-plugin-transform-es2015-spread": "^6.22.0",
"babel-plugin-transform-es2015-template-literals": "^6.22.0",
"babel-register": "^6.24.1",
"bup": "^1.0.9",
"cross-env": "^5.0.1",
"eslint": "^3.19.0",
"eslint-config-joyent-portal": "1.0.0",
"nyc": "^11.0.2",
"react": "^15.5.4",
"redrun": "^5.9.14",
"styled-components": "^2.0.1",
"tap-xunit": "^1.7.0"
},
"peerDependencies": {
"react": "*",
"styled-components": "*"
},
"nyc": {
"sourceMap": false,
"instrument": false
},
"babel": {
"sourceMaps": "inline",
"plugins": [
"transform-es2015-parameters",
"transform-es2015-template-literals",
"transform-es2015-arrow-functions",
"transform-es2015-spread"
],
"env": {
"test": {
"plugins": [
"istanbul"
]
}
}
},
"ava": {
"tap": true,
"require": [
"babel-register"
],
"babel": "inherit"
}
}

View File

@ -1,13 +0,0 @@
import { css } from 'styled-components';
export default (...names) => (...args) => props =>
names.every(name => props[name]) ? css(...args) : css``;
export const isNot = (...names) => (...args) => props =>
names.every(name => !props[name]) ? css(...args) : css``;
export const isOr = (...names) => (...args) => props =>
names.some(name => props[name]) ? css(...args) : css``;
export const isSomeNot = (...names) => (...args) => props =>
names.some(name => !props[name]) ? css(...args) : css``;

View File

@ -1,52 +0,0 @@
const { default: is, isNot, isOr, isSomeNot } = require('../');
const test = require('ava');
test('should render only if prop is truthy', t => {
const rule = is('test')`hello`;
t.deepEqual(rule({ test: false }), []);
t.deepEqual(rule({ test: true }), ['hello']);
});
test('should render only if prop is falsy', t => {
const rule = isNot('test')`hello`;
t.deepEqual(rule({ test: false }), ['hello']);
t.deepEqual(rule({ test: true }), []);
});
test('should render only if all props are truthy', t => {
const rule = is('t1', 't2')`hello`;
t.deepEqual(rule({ t1: true, t2: false }), []);
t.deepEqual(rule({ t1: false, t2: false }), []);
t.deepEqual(rule({ t1: false, t2: true }), []);
t.deepEqual(rule({ t1: true, t2: true }), ['hello']);
});
test('should render only if all props are falsy', t => {
const rule = isNot('t1', 't2')`hello`;
t.deepEqual(rule({ t1: true, t2: false }), []);
t.deepEqual(rule({ t1: false, t2: false }), ['hello']);
t.deepEqual(rule({ t1: false, t2: true }), []);
t.deepEqual(rule({ t1: true, t2: true }), []);
});
test('should render only if one prop is truthy', t => {
const rule = isOr('t1', 't2')`hello`;
t.deepEqual(rule({ t1: true, t2: false }), ['hello']);
t.deepEqual(rule({ t1: false, t2: false }), []);
t.deepEqual(rule({ t1: false, t2: true }), ['hello']);
t.deepEqual(rule({ t1: true, t2: true }), ['hello']);
});
test('should render only if one prop is falsy', t => {
const rule = isSomeNot('t1', 't2')`hello`;
t.deepEqual(rule({ t1: true, t2: false }), ['hello']);
t.deepEqual(rule({ t1: false, t2: false }), ['hello']);
t.deepEqual(rule({ t1: false, t2: true }), ['hello']);
t.deepEqual(rule({ t1: true, t2: true }), []);
});

File diff suppressed because it is too large Load Diff

View File

@ -30,6 +30,7 @@
"dependencies": { "dependencies": {
"camel-case": "^3.0.0", "camel-case": "^3.0.0",
"d3": "^4.9.1", "d3": "^4.9.1",
"disable-scroll": "^0.3.0",
"lodash.isstring": "^4.0.1", "lodash.isstring": "^4.0.1",
"normalized-styled-components": "^1.0.5", "normalized-styled-components": "^1.0.5",
"polished": "^1.1.3", "polished": "^1.1.3",

View File

@ -0,0 +1,20 @@
import unitcalc from 'unitcalc';
import styled from 'styled-components';
import camelCase from 'camel-case';
const aligns = ['vertical-align'];
const alignsFromProps = props =>
aligns
.filter(align => props[camelCase(align)])
.map(
align => `
${align}: ${props[camelCase(align)]};
`
)
.join(';\n');
export default Component =>
Component.extend
? Component.extend`${alignsFromProps}`
: styled(Component)`${alignsFromProps}`;

View File

@ -8,6 +8,7 @@ export const insetShaddow = `inset 0 ${remcalc(3)} 0 0 rgba(0, 0, 0, 0.05)`;
export const tooltipShadow = `0 ${remcalc(2)} ${remcalc(6)} ${remcalc( export const tooltipShadow = `0 ${remcalc(2)} ${remcalc(6)} ${remcalc(
1 1
)} rgba(0, 0, 0, 0.1)`; )} rgba(0, 0, 0, 0.1)`;
export const modalShadow = `0 0 ${remcalc(6)} ${remcalc(1)} rgba(0, 0, 0, 0.1)`;
export const border = { export const border = {
checked: css`${remcalc(1)} solid ${props => props.theme.primary}`, checked: css`${remcalc(1)} solid ${props => props.theme.primary}`,

View File

@ -0,0 +1,35 @@
import React, { Component } from 'react';
import styled from 'styled-components';
import unitcalc from 'unitcalc';
import theme from '../theme';
import Button from '../button';
import { CloseIcon } from '../icons';
const StyledCloseButton = Button.extend`
background-color: ${theme.white};
padding: ${unitcalc(2)};
min-width: auto;
border: none;
box-shadow: none;
&:hover,
&:focus,
&:active,
&:active:hover,
&:active:focus {
background-color: ${theme.white};
border: none;
box-shadow: none;
}
`;
/**
* @example ./usage.md
*/
const CloseButton = props => (
<StyledCloseButton {...props}>
<CloseIcon />
</StyledCloseButton>
);
export default CloseButton;

View File

@ -0,0 +1,3 @@
```
<CloseButton />
```

View File

@ -34,7 +34,6 @@ const style = css`
border-radius: ${borderRadius}; border-radius: ${borderRadius};
background-color: ${props => props.theme.white}; background-color: ${props => props.theme.white};
box-shadow: ${insetShaddow};
border: ${border.unchecked}; border: ${border.unchecked};
${is('error')` ${is('error')`

View File

@ -8,3 +8,4 @@ export { default as FormMeta } from './meta';
export { default as Radio, RadioList } from './radio'; export { default as Radio, RadioList } from './radio';
export { default as Select } from './select'; export { default as Select } from './select';
export { default as Toggle, ToggleList } from './toggle'; export { default as Toggle, ToggleList } from './toggle';
export { default as NumberInput } from './number-input';

View File

@ -0,0 +1,51 @@
import BaseInput, { Stylable } from './base/input';
import { Subscriber } from 'react-broadcast';
import Baseline from '../baseline';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import IconButton from '../icon-button';
import unitcalc from 'unitcalc';
import { PlusIcon, MinusIcon } from '../icons';
const StyledContainer = styled.div`
margin-bottom: ${unitcalc(4)};
`;
const StyledNumberInput = styled(Baseline(BaseInput(Stylable('input'))))`
width: ${unitcalc(20)};
margin: 0 ${unitcalc(1)} 0 0;
vertical-align: middle;
`;
/**
* @example ./usage-number-input.md
*/
const NumberInput = ({ value, ...rest }) => {
const render = value => (
<StyledContainer>
<StyledNumberInput value={value} />
<IconButton onClick={() => {}}>
<MinusIcon verticalAlign="middle" />
</IconButton>
<IconButton onClick={() => {}}>
<PlusIcon verticalAlign="middle" />
</IconButton>
</StyledContainer>
);
return (
<Subscriber channel="input-group">
{render}
</Subscriber>
);
};
NumberInput.propTypes = {
value: PropTypes.number,
minValue: PropTypes.number,
maxValue: PropTypes.number,
onChange: PropTypes.func
};
export default Baseline(NumberInput);

View File

@ -0,0 +1,3 @@
```
<NumberInput placeholder='I am the placeholder' value='1' onChange={() => {}} />
```

View File

@ -0,0 +1,90 @@
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import remcalc from 'remcalc';
import { borderRadius } from '../boxes';
import Baseline from '../baseline';
const StyledIconButton = styled.button`
border-radius: ${borderRadius};
border: solid ${remcalc(1)} ${props => props.theme.grey};
background-color: ${props => props.theme.white};
box-sizing: border-box;
display: inline-block;
justify-content: center;
align-items: center;
margin-left: ${remcalc(6)};
padding: ${remcalc(15)} ${remcalc(18)};
position: relative;
text-align: center;
line-height: normal;
vertical-align: middle;
touch-action: manipulation;
cursor: pointer;
&:focus {
outline: 0;
background-color: ${props => props.theme.white};
border-color: ${props => props.theme.grey};
}
&:hover {
background-color: ${props => props.theme.whiteHover};
border-color: ${props => props.theme.grey};
}
&:active,
&:active:hover,
&:active:focus {
outline: 0;
background-color: ${props => props.theme.whiteActive};
border-color: ${props => props.theme.grey};
}
&[disabled] {
cursor: not-allowed;
pointer-events: none;
color: ${props => props.theme.grey};
background-color: ${props => props.theme.disabled};
border-color: ${props => props.theme.grey};
&:focus {
background-color: ${props => props.theme.disabled};
border-color: ${props => props.theme.grey};
}
&:hover {
background-color: ${props => props.theme.disabled};
border-color: ${props => props.theme.disabled};
}
&:active,
&:active:hover,
&:active:focus {
background-color: ${props => props.theme.disabled};
border-color: ${props => props.theme.disabled};
}
}
`;
const StyledDiv = styled.div`
height: ${remcalc(16)};
`;
/**
* @example ./usage.md
*/
const IconButton = ({ children, onClick }) => (
<StyledIconButton onClick={onClick}>
<StyledDiv>
{children}
</StyledDiv>
</StyledIconButton>
);
IconButton.propTypes = {
children: PropTypes.node,
onClick: PropTypes.func
};
export default Baseline(IconButton);

View File

@ -0,0 +1,7 @@
```
const CloseIcon = require('../icons/close').default;
<IconButton>
<CloseIcon/>
</IconButton>
```

View File

@ -0,0 +1,7 @@
import Baseline from '../baseline';
// eslint-disable-next-line no-unused-vars
import React from 'react';
import CloseIcon from './svg/icon_close_cross.svg';
export default Baseline(CloseIcon);

View File

@ -0,0 +1,3 @@
export { default as CloseIcon } from './close';
export { default as PlusIcon } from './plus';
export { default as MinusIcon } from './minus';

View File

@ -0,0 +1,8 @@
import Baseline from '../baseline';
import Basealign from '../basealign';
// eslint-disable-next-line no-unused-vars
import React from 'react';
import MinusIcon from './svg/icon_minus.svg';
export default Basealign(MinusIcon);

View File

@ -0,0 +1,8 @@
import Baseline from '../baseline';
import Basealign from '../basealign';
// eslint-disable-next-line no-unused-vars
import React from 'react';
import CloseIcon from './svg/icon_plus.svg';
export default Baseline(CloseIcon);

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="13px" viewBox="0 0 12 13" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>icon: alert</title>
<desc>Created with Sketch.</desc>
<defs>
<linearGradient x1="49.9665552%" y1="100%" x2="49.9665552%" y2="0%" id="linearGradient-1">
<stop stop-color="#E6E6E6" offset="0%"></stop>
<stop stop-color="#FFFFFF" offset="100%"></stop>
</linearGradient>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="creating-deployment-group:-editing-manifest" transform="translate(-1108.000000, -20.000000)" fill="url(#linearGradient-1)">
<g id="header" transform="translate(0.000000, -1.000000)">
<g id="button:-alerts" transform="translate(1087.000000, 1.000000)">
<path d="M27,33 C26.448,33 26,32.552 26,32 L28,32 C28,32.552 27.552,33 27,33 Z M30.6,27.3333333 C30.6,28.6826667 31.6752,29.7777778 33,29.7777778 L33,31 L30.6,31 L28.2,31 L25.8,31 L23.4,31 L21,31 L21,29.7777778 C22.3248,29.7777778 23.4,28.6826667 23.4,27.3333333 L23.4,26.1111111 C23.4,24.5173333 24.4044,23.1741111 25.8,22.6693333 L25.8,21.2222222 C25.8,20.5475556 26.3376,20 27,20 C27.6624,20 28.2,20.5475556 28.2,21.2222222 L28.2,22.6693333 C29.5956,23.1741111 30.6,24.5173333 30.6,26.1111111 L30.6,27.3333333 Z" id="icon:-alert"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="9px" height="6px" viewBox="0 0 9 6" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>arrow: right</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="creating-deployment-group:-editing-manifest-(demo)" transform="translate(-190.000000, -1161.000000)" fill="#494949">
<g id="text-field:-multiple-lines" transform="translate(183.000000, 372.000000)">
<polygon id="arrow:-right" transform="translate(11.500000, 792.000000) rotate(90.000000) translate(-11.500000, -792.000000) " points="9.88604803 787.5 8.5 788.851816 11.7279039 792 8.5 795.148184 9.88604803 796.5 14.5 792"></polygon>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 955 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 17 16"><defs><style>.cls-1{fill:#d8d8d8;}.cls-2{fill:#fff;}.cls-3{fill:url(#linear-gradient);}.cls-4{fill:#a2a2a2;}</style><linearGradient id="linear-gradient" x1="8.5" y1="14" x2="8.5" y2="2" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#e6e6e6"/><stop offset="0.04" stop-color="#eaeaea"/><stop offset="0.21" stop-color="#f6f6f6"/><stop offset="0.43" stop-color="#fdfdfd"/><stop offset="1" stop-color="#fff"/></linearGradient></defs><title>calendar_</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><rect class="cls-1" x="1" y="2" width="15" height="14"/><rect class="cls-2" y="1" width="17" height="14"/><rect class="cls-3" x="1" y="2" width="15" height="12"/><rect class="cls-4" x="3" y="4" width="2" height="2"/><rect class="cls-4" x="6" y="4" width="2" height="2"/><rect class="cls-4" x="9" y="4" width="2" height="2"/><rect class="cls-4" x="12" y="4" width="2" height="2"/><rect class="cls-4" x="3" y="7" width="2" height="2"/><rect class="cls-4" x="6" y="7" width="2" height="2"/><rect class="cls-4" x="9" y="7" width="2" height="2"/><rect class="cls-4" x="12" y="7" width="2" height="2"/><rect class="cls-4" x="3" y="10" width="2" height="2"/><rect class="cls-4" x="6" y="10" width="2" height="2"/><rect class="cls-4" x="9" y="10" width="2" height="2"/><path class="cls-4" d="M15,1V.5a.5.5,0,0,0-1,0V1H3V.5a.5.5,0,0,0-1,0V1H0V15H17V1Zm1,13H1V2H2v.5a.5.5,0,0,0,1,0V2H14v.5a.5.5,0,0,0,1,0V2h1Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="12px" viewBox="0 0 12 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>icon: close</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="creating-deployment-group:-editing-manifest" transform="translate(-1158.000000, -288.000000)" fill="#494949">
<g id="notification:-task-acomplished" transform="translate(183.000000, 270.000000)">
<path d="M981.899495,22.8994949 L981.899495,16.8994949 L979.899495,16.8994949 L979.899495,22.8994949 L973.899495,22.8994949 L973.899495,24.8994949 L979.899495,24.8994949 L979.899495,30.8994949 L981.899495,30.8994949 L981.899495,24.8994949 L987.899495,24.8994949 L987.899495,22.8994949 L981.899495,22.8994949 Z" id="icon:-close" transform="translate(980.899495, 23.899495) rotate(45.000000) translate(-980.899495, -23.899495) "></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>icon: cpu</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="creating-deployment-group:-review-(without-package-selection)" transform="translate(-202.000000, -552.000000)">
<g id="service:-wordpress" transform="translate(183.000000, 468.000000)">
<g id="package" transform="translate(0.000000, 72.000000)">
<g id="icon:-cpu" transform="translate(19.000000, 12.000000)">
<circle id="Oval-4" stroke="#8043DC" stroke-width="2" cx="24" cy="24" r="23"></circle>
<g id="cpu" transform="translate(12.000000, 12.000000)" fill="#8043DC">
<path d="M8,16 L16,16 L16,8 L8,8 L8,16 Z M7,17 L17,17 L17,7 L7,7 L7,17 Z" id="Fill-1"></path>
<path d="M20,18 C20,19.103 19.103,20 18,20 L6,20 C4.897,20 4,19.103 4,18 L4,6 C4,4.897 4.897,4 6,4 L18,4 C19.103,4 20,4.897 20,6 L20,18 Z M23,13 C23.552,13 24,12.553 24,12 C24,11.447 23.552,11 23,11 L22,11 L22,10 L23,10 C23.552,10 24,9.553 24,9 C24,8.447 23.552,8 23,8 L22,8 L22,6 C22,3.791 20.209,2 18,2 L16,2 L16,1 C16,0.447 15.552,0 15,0 C14.448,0 14,0.447 14,1 L14,2 L13,2 L13,1 C13,0.447 12.552,0 12,0 C11.448,0 11,0.447 11,1 L11,2 L10,2 L10,1 C10,0.447 9.552,0 9,0 C8.448,0 8,0.447 8,1 L8,2 L6,2 C3.791,2 2,3.791 2,6 L2,8 L1,8 C0.448,8 0,8.447 0,9 C0,9.553 0.448,10 1,10 L2,10 L2,11 L1,11 C0.448,11 0,11.447 0,12 C0,12.553 0.448,13 1,13 L2,13 L2,14 L1,14 C0.448,14 0,14.447 0,15 C0,15.553 0.448,16 1,16 L2,16 L2,18 C2,20.209 3.791,22 6,22 L8,22 L8,23 C8,23.553 8.448,24 9,24 C9.552,24 10,23.553 10,23 L10,22 L11,22 L11,23 C11,23.553 11.448,24 12,24 C12.552,24 13,23.553 13,23 L13,22 L14,22 L14,23 C14,23.553 14.448,24 15,24 C15.552,24 16,23.553 16,23 L16,22 L18,22 C20.209,22 22,20.209 22,18 L22,16 L23,16 C23.552,16 24,15.553 24,15 C24,14.447 23.552,14 23,14 L22,14 L22,13 L23,13 Z" id="Fill-2"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="9px" height="13px" viewBox="0 0 9 13" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>icon: data center</title>
<desc>Created with Sketch.</desc>
<defs>
<linearGradient x1="49.9665552%" y1="100%" x2="49.9665552%" y2="0%" id="linearGradient-1">
<stop stop-color="#E6E6E6" offset="0%"></stop>
<stop stop-color="#FFFFFF" offset="100%"></stop>
</linearGradient>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="creating-deployment-group:-editing-manifest" transform="translate(-1174.000000, -20.000000)" fill="url(#linearGradient-1)">
<g id="header" transform="translate(0.000000, -1.000000)">
<path d="M1174,34 L1183,34 L1183,21 L1174,21 L1174,34 Z M1176,32 L1181,32 L1181,23 L1176,23 L1176,32 Z M1177,25 L1180.001,25 L1180.001,24 L1177,24 L1177,25 Z M1177,27 L1180.001,27 L1180.001,26 L1177,26 L1177,27 Z M1177,29 L1180.001,29 L1180.001,28 L1177,28 L1177,29 Z" id="icon:--data-center"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>icon: disk</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="creating-deployment-group:-review-(without-package-selection)" transform="translate(-202.000000, -1200.000000)">
<g id="service:-wordpress" transform="translate(183.000000, 1116.000000)">
<g id="package" transform="translate(0.000000, 72.000000)">
<g id="icon:-disk" transform="translate(19.000000, 12.000000)">
<circle id="Oval-4" stroke="#A88A83" stroke-width="2" cx="24" cy="24" r="23"></circle>
<g transform="translate(14.000000, 14.000000)" fill="#A88A83">
<path d="M18,17 C18,17.552 17.552,18 17,18 L3,18 C2.448,18 2,17.552 2,17 L2,3 C2,2.448 2.448,2 3,2 L17,2 C17.552,2 18,2.448 18,3 L18,17 Z M17,0 L3,0 C1.343,0 0,1.343 0,3 L0,17 C0,18.657 1.343,20 3,20 L17,20 C18.657,20 20,18.657 20,17 L20,3 C20,1.343 18.657,0 17,0 L17,0 Z" id="Fill-1"></path>
<path d="M10,15 C7.243,15 5,12.757 5,10 C5,7.243 7.243,5 10,5 C12.757,5 15,7.243 15,10 C15,12.757 12.757,15 10,15 M10,4 C6.687,4 4,6.687 4,10 C4,13.313 6.687,16 10,16 C13.313,16 16,13.313 16,10 C16,6.687 13.313,4 10,4" id="Fill-3"></path>
<path d="M9,10 C9,10.553 9.447,11 10,11 C10.553,11 11,10.553 11,10 C11,9.447 10.553,9 10,9 C9.447,9 9,9.447 9,10 Z" id="Fill-5"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>icon: error</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="project-overview" transform="translate(-889.000000, -333.000000)">
<g id="feed" transform="translate(876.000000, 241.000000)">
<g id="event" transform="translate(0.000000, 92.000000)">
<g id="icon:-error" transform="translate(13.000000, 0.000000)">
<circle id="Oval" fill="#DA4B42" cx="9" cy="9" r="9"></circle>
<g id="cion:-error" transform="translate(9.000000, 9.000000) rotate(45.000000) translate(-9.000000, -9.000000) translate(5.000000, 5.000000)" fill="#FFFFFF">
<rect id="Rectangle-7" x="3" y="-3.37507799e-14" width="2" height="8"></rect>
<rect id="Rectangle-7" transform="translate(4.000000, 4.000000) rotate(90.000000) translate(-4.000000, -4.000000) " x="3" y="-2.34923192e-13" width="2" height="8"></rect>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>icon: state</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="topology" transform="translate(-489.000000, -441.000000)">
<g id="services" transform="translate(0.000000, 348.000000)">
<g id="service:-nginx" transform="translate(476.000000, 36.000000)">
<g id="icon:-state" transform="translate(13.000000, 57.000000)">
<circle id="Oval" fill="#00AF66" cx="9" cy="9" r="9"></circle>
<path d="M9.47745233,6.60270759 L8.95496861,7.04565311 L8.51133742,6.60270759 C7.70841297,5.79909747 6.40563205,5.79909747 5.60270759,6.60270759 C4.79909747,7.40631772 4.79909747,8.70841297 5.60270759,9.5120231 L8.95496861,12.8642841 L12.3668833,9.5120231 C13.1698077,8.70841297 13.2301471,7.40631772 12.4265369,6.60270759 C11.6229268,5.79909747 10.2810625,5.79909747 9.47745233,6.60270759 Z" id="icon:-health" fill="#FFFFFF"></path>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="18px" height="9px" viewBox="0 0 18 9" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>icon: instances</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="topology" transform="translate(-1046.000000, -447.000000)" fill="#494949">
<g id="services" transform="translate(0.000000, 348.000000)">
<g id="service:-consul" transform="translate(1003.000000, 36.000000)">
<g id="metric">
<g id="data-centers-&amp;-instanecs" transform="translate(43.000000, 59.000000)">
<path d="M4.5,4 C2.015,4 0,6.015 0,8.5 C0,10.985 2.015,13 4.5,13 C6.985,13 9,10.985 9,8.5 C9,6.015 6.985,4 4.5,4 M13.0909091,4 C12.7145455,4 12.3512727,4.047 12,4.12 C14.184,4.576 15.8181818,6.359 15.8181818,8.5 C15.8181818,10.641 14.184,12.424 12,12.88 C12.3512727,12.953 12.7145455,13 13.0909091,13 C15.8018182,13 18,10.985 18,8.5 C18,6.015 15.8018182,4 13.0909091,4 M14,8.5 C14,10.985 11.8018182,13 9.09090909,13 C8.71454545,13 8.35127273,12.953 8,12.88 C10.184,12.424 11.8181818,10.641 11.8181818,8.5 C11.8181818,6.359 10.184,4.576 8,4.12 C8.35127273,4.047 8.71454545,4 9.09090909,4 C11.8018182,4 14,6.015 14,8.5" id="icon:-instances"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="8px" height="2px" viewBox="0 0 8 2" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>icon: plus</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="scaling-dialogue-2" transform="translate(-641.000000, -425.000000)" fill="#494949">
<g id="content" transform="translate(453.000000, 234.000000)">
<g id="number-of-instances" transform="translate(36.000000, 168.000000)">
<g id="button:-minus" transform="translate(132.000000, 0.000000)">
<rect id="icon:-plus" x="20" y="23" width="8" height="2"></rect>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 963 B

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="8px" height="8px" viewBox="0 0 8 8" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>icon: plus</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="scaling-dialogue-2" transform="translate(-695.000000, -422.000000)" fill="#494949">
<g id="content" transform="translate(453.000000, 234.000000)">
<g id="number-of-instances" transform="translate(36.000000, 168.000000)">
<g id="button:-plus" transform="translate(186.000000, 0.000000)">
<path d="M23,23 L20,23 L20,25 L23,25 L23,28 L25,28 L25,25 L28,25 L28,23 L25,23 L25,20 L23,20 L23,23 Z" id="icon:-plus"></path>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>icon: cpu</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="creating-deployment-group:-review-(without-package-selection)" transform="translate(-202.000000, -1038.000000)">
<g id="service:-wordpress" transform="translate(183.000000, 954.000000)">
<g id="package" transform="translate(0.000000, 72.000000)">
<g id="icon:-cpu" transform="translate(19.000000, 12.000000)">
<circle id="Oval-4" stroke="#32ABCF" stroke-width="2" cx="24" cy="24" r="23"></circle>
<path d="M21,28 L24,28 L24,26 L21,26 L21,28 Z M21,31 L24,31 L24,29 L21,29 L21,31 Z M21,25 L24,25 L24,23 L21,23 L21,25 Z M21,22 L24,22 L24,20 L21,20 L21,22 Z M21,19 L24,19 L24,17 L21,17 L21,19 Z M20,33 L27,33 L27,15 L20,15 L20,33 Z M30,22 C30.552,22 31,21.553 31,21 C31,20.447 30.552,20 30,20 L29,20 L29,19 L30,19 C30.552,19 31,18.553 31,18 C31,17.447 30.552,17 30,17 L29,17 L29,15 C29,13.896 28.104,13 27,13 L20,13 C18.896,13 18,13.896 18,15 L18,33 C18,34.104 18.896,35 20,35 L27,35 C28.104,35 29,34.104 29,33 L29,31 L30,31 C30.552,31 31,30.553 31,30 C31,29.447 30.552,29 30,29 L29,29 L29,28 L30,28 C30.552,28 31,27.553 31,27 C31,26.447 30.552,26 30,26 L29,26 L29,25 L30,25 C30.552,25 31,24.553 31,24 C31,23.447 30.552,23 30,23 L29,23 L29,22 L30,22 Z" id="Page-1" fill="#32ABCF" transform="translate(24.500000, 24.000000) rotate(45.000000) translate(-24.500000, -24.000000) "></path>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="9px" height="9px" viewBox="0 0 9 9" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>tick</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="creating-deployment-group:-editing-manifest" transform="translate(-399.000000, -206.000000)" fill="#494949">
<g id="steps" transform="translate(183.000000, 186.000000)">
<g id="step" transform="translate(168.000000, 0.000000)">
<g id="icon:-in-progress" transform="translate(40.000000, 12.000000)">
<polygon id="tick" points="15.3161492 8 11.2540547 13.4771898 9.7036608 11.3123859 8 12.4948677 11.2227757 17 17 9.21019617"></polygon>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="18px" height="24px" viewBox="0 0 18 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>Fill 1</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="creating-deployment-group:-editing-manifest" transform="translate(-196.000000, -575.000000)" fill="#646464">
<g id="button:-upload" transform="translate(183.000000, 564.000000)">
<g id="icon:-upload" transform="translate(13.000000, 11.000000)">
<path d="M5.0004,-0.0003 L0.0004,4.0007 L0.0004,23.9997 L18.0004,23.9997 L18.0004,-0.0003 L5.0004,-0.0003 Z M1.9994,4.9997 L5.0004,4.9997 L5.0004,2.0007 L16.0004,2.0007 L16.0004,22.0007 L1.9994,22.0007 L1.9994,4.9997 Z M9,9.9463 L9.044,10.0003 L8.956,10.0003 L9,9.9463 Z M8,11.1533 L8,17.0003 L10,17.0003 L10,11.1533 L11.23,12.6383 L12.77,11.3623 L9,6.8113 L5.23,11.3623 L6.77,12.6383 L8,11.1533 Z" id="Fill-1"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="12px" viewBox="0 0 12 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>Shape</title>
<desc>Created with Sketch.</desc>
<defs>
<linearGradient x1="49.9665552%" y1="100%" x2="49.9665552%" y2="0%" id="linearGradient-1">
<stop stop-color="#E6E6E6" offset="0%"></stop>
<stop stop-color="#FFFFFF" offset="100%"></stop>
</linearGradient>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="topology" transform="translate(-1280.000000, -21.000000)" fill-rule="nonzero" fill="url(#linearGradient-1)">
<g id="header" transform="translate(0.000000, -1.000000)">
<g id="user_" transform="translate(1280.000000, 22.000000)">
<path d="M12,12 L0,12 C0.0879206862,10.6850688 0.610056844,9.4361191 1.48494983,8.448 C1.91244945,7.94595587 2.6394085,7.8212683 3.21070234,8.152 C4.84372259,9.09118114 6.87643212,8.99426146 8.41204013,7.904 C8.95662257,7.53065583 9.69030531,7.59438751 10.1618729,8.056 C11.2498099,9.09393775 11.9060055,10.5019119 12,12 Z M5.6187291,0 C3.84550716,-1.082166e-16 2.40802676,1.4326888 2.40802676,3.2 C2.40802676,4.968 3.82876254,7.2 5.6187291,7.2 C7.40869565,7.2 8.82943144,4.968 8.82943144,3.2 C8.82943144,1.4326888 7.39195104,1.082166e-16 5.6187291,0 Z" id="Shape"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -12,6 +12,9 @@ export { default as Small } from './text/small';
export { default as theme } from './theme'; export { default as theme } from './theme';
export { default as typography, fonts } from './typography'; export { default as typography, fonts } from './typography';
export { default as Topology } from './topology'; export { default as Topology } from './topology';
export { default as Modal } from './modal';
export { default as CloseButton } from './close-button';
export { default as IconButton } from './icon-button';
export { Tooltip, TooltipButton, TooltipDivider } from './tooltip'; export { Tooltip, TooltipButton, TooltipDivider } from './tooltip';
@ -63,7 +66,8 @@ export {
RadioList, RadioList,
Select, Select,
Toggle, Toggle,
ToggleList ToggleList,
NumberInput
} from './form'; } from './form';
export { export {

View File

@ -1,14 +1,68 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
// import styled from 'styled-components'; import PropTypes from 'prop-types';
import styled from 'styled-components';
import disableScroll from 'disable-scroll';
import remcalc from 'remcalc';
import theme from '../theme';
import { border, borderRadius, modalShadow } from '../boxes';
import Button from '../button';
import CloseButton from '../close-button';
const StyledBackground = styled.div`
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-color: rgba(250, 250, 250, 0.5);
`;
const StyledModal = styled.div`
position: absolute;
left: 50%;
top: 33.33%;
padding: ${remcalc(30)} ${remcalc(36)} ${remcalc(36)} ${remcalc(36)};
background-color: ${theme.white};
box-shadow: ${modalShadow};
width: ${props => remcalc(props.width)};
margin: 0 auto 0 -${props => remcalc(props.width / 2)};
`;
// tmp
const StyledClose = styled(CloseButton)`
position: absolute;
right: ${remcalc(6)};
top: ${remcalc(3)};
`;
class Modal extends Component { class Modal extends Component {
componentDidMount() {
disableScroll.on();
}
componentWillUnmount() {
disableScroll.off();
}
render() { render() {
const { children, width, onCloseClick } = this.props;
return ( return (
<div> <StyledBackground>
<p>Modal</p> <StyledModal width={width}>
</div> <StyledClose onClick={onCloseClick}>X</StyledClose>
{children}
</StyledModal>
</StyledBackground>
); );
} }
} }
Modal.propTypes = {
children: PropTypes.node,
width: PropTypes.number,
onCloseClick: PropTypes.func
};
export default Modal; export default Modal;

View File

@ -0,0 +1,3 @@
```
<Modal />
```

Some files were not shown because too many files have changed in this diff Show More