mirror of
https://github.com/gravitational/teleport.git
synced 2026-10-11 22:49:54 +00:00
Move code to this repo
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
node_modules
|
||||
scripts
|
||||
**/node_modules/
|
||||
**/dist/
|
||||
.gitignore
|
||||
Dockerfile
|
||||
Makefile
|
||||
*/**/.git
|
||||
*/**/*.log
|
||||
@@ -0,0 +1,2 @@
|
||||
const eslint = require('./packages/build/.eslintrc');
|
||||
module.exports = eslint;
|
||||
@@ -0,0 +1,4 @@
|
||||
node_modules
|
||||
dist
|
||||
*.log
|
||||
.vscode
|
||||
@@ -0,0 +1,3 @@
|
||||
[submodule "packages/webapps"]
|
||||
path = packages/webapps
|
||||
url = [email protected]:gravitational/teleport.git
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"arrowParens": "avoid",
|
||||
"printWidth": 80,
|
||||
"bracketSpacing": true,
|
||||
"jsxBracketSameLine": false,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
{ "extends": "./../packages/build/.babelrc" }
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { configure } from '@storybook/react';
|
||||
import { addDecorator } from '@storybook/react';
|
||||
import theme from './../packages/design/src/theme';
|
||||
import ThemeProvider from './../packages/design/src/ThemeProvider';
|
||||
import Box from './../packages/design/src/Box';
|
||||
|
||||
const ThemeDecorator = storyFn => (
|
||||
<ThemeProvider theme={theme}>
|
||||
<Box p={3}>{storyFn()}</Box>
|
||||
</ThemeProvider>
|
||||
);
|
||||
|
||||
addDecorator(ThemeDecorator);
|
||||
|
||||
const reqs = require.context('./../packages/', true, /\.story.js$/);
|
||||
const loadStories = () => {
|
||||
reqs.keys().forEach(reqs);
|
||||
};
|
||||
|
||||
configure(loadStories, module);
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require("path");
|
||||
const createConfig = require('@gravitational/build/webpack/webpack.base');
|
||||
const webpackCfg = createConfig();
|
||||
|
||||
module.exports = ({ config }) => {
|
||||
config.devtool = false;
|
||||
config.resolve = {
|
||||
...config.resolve,
|
||||
...webpackCfg.resolve,
|
||||
}
|
||||
|
||||
return config;
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
FROM node:12-slim
|
||||
RUN apt-get update && apt-get install git -y
|
||||
|
||||
# copy only package.json files first
|
||||
RUN mkdir -p web-apps
|
||||
COPY yarn.lock web-apps/
|
||||
COPY package.json web-apps/
|
||||
# copy the build folder so yarn can install build/bin files in other packages
|
||||
COPY packages/build/ web-apps/packages/build/
|
||||
# copy just the package.json files to yarn install results
|
||||
COPY packages/design/package.json web-apps/packages/design/
|
||||
COPY packages/gravity/package.json web-apps/packages/gravity/
|
||||
COPY packages/shared/package.json web-apps/packages/shared/
|
||||
COPY packages/teleport/package.json web-apps/packages/teleport/
|
||||
COPY packages/e/gravity/package.json web-apps/packages/e/gravity/
|
||||
COPY packages/e/teleport/package.json web-apps/packages/e/teleport/
|
||||
WORKDIR web-apps
|
||||
RUN yarn install
|
||||
COPY . .
|
||||
ARG NPM_SCRIPT
|
||||
RUN yarn run $NPM_SCRIPT
|
||||
@@ -0,0 +1,57 @@
|
||||
IMAGE_NAME := web-apps:1.0.0
|
||||
REPO_VER_TAG := $(shell git describe --tags --abbrev=8)
|
||||
CONTAINER_NAME := web-apps-container-$(REPO_VER_TAG)-$(shell bash -c 'echo $$RANDOM')
|
||||
HOME_DIR = $(shell pwd)
|
||||
|
||||
.PHONY:gravity
|
||||
gravity:
|
||||
$(MAKE) docker-build PACKAGE_PATH=packages/gravity NPM_CMD=build-gravity
|
||||
|
||||
.PHONY:teleport
|
||||
teleport:
|
||||
$(MAKE) docker-build PACKAGE_PATH=packages/teleport NPM_CMD=build-teleport
|
||||
|
||||
.PHONY:docker-enter
|
||||
docker-enter:
|
||||
docker run -ti --rm=true -t $(IMAGE_NAME) /bin/bash
|
||||
|
||||
.PHONY: docker-clean
|
||||
docker-clean:
|
||||
docker rmi --force $(IMAGE_NAME)
|
||||
|
||||
docker-build:
|
||||
rm -rf $(HOME_DIR)/$(PACKAGE_PATH)/dist
|
||||
docker build --force-rm=true --build-arg NPM_SCRIPT=$(NPM_CMD) -t $(IMAGE_NAME) .
|
||||
docker create --name $(CONTAINER_NAME) -t $(IMAGE_NAME) && \
|
||||
docker cp $(CONTAINER_NAME):/web-apps/$(PACKAGE_PATH)/dist $(HOME_DIR)/$(PACKAGE_PATH)/
|
||||
docker rm -f $(CONTAINER_NAME)
|
||||
|
||||
.PHONY:clean
|
||||
clean:
|
||||
find . -name "node_modules" -type d -prune -exec rm -rf '{}' +
|
||||
find . -name "dist" -type d -prune -exec rm -rf '{}' +
|
||||
|
||||
.PHONY:install
|
||||
install:
|
||||
bash -c "./scripts/install.sh"
|
||||
|
||||
# Use git submodule status to figure out if submodule is not initialized
|
||||
# (- at the beginning) or somehow modified/outdated (+ at the beginning).
|
||||
# or the folder has been deleted ([null])
|
||||
# .PHONY: ensure-submodules
|
||||
# ensure-submodules:
|
||||
# @if git submodule status | egrep -q '(^[-]|^[+])|[null]' ; then \
|
||||
# git submodule update --init; \
|
||||
# fi
|
||||
|
||||
.PHONY: init
|
||||
init:
|
||||
git config core.hooksPath $(HOME_DIR)/scripts/githooks/oss
|
||||
|
||||
.PHONY: init-enterprise
|
||||
init-enterprise:
|
||||
git config core.hooksPath $(HOME_DIR)/scripts/githooks/enterpise
|
||||
|
||||
|
||||
#ensure-submodules
|
||||
#$(shell test -d $(FMC_DRV) || git submodule update --init)
|
||||
@@ -0,0 +1,5 @@
|
||||
const baseCfg = require('@gravitational/build/.babelrc');
|
||||
module.exports = function (api) {
|
||||
api.cache(true);
|
||||
return baseCfg
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
module.exports = {
|
||||
moduleNameMapper: {
|
||||
'shared/(.*)$': '<rootDir>/packages/shared/$1',
|
||||
'design/(.*)$': '<rootDir>/packages/design/src/$1',
|
||||
'gravity/(.*)$': '<rootDir>/packages/gravity/src/$1',
|
||||
'teleport/(.*)$': '<rootDir>/packages/teleport/src/$1',
|
||||
'e-teleport/(.*)$': '<rootDir>/packages/e/teleport/src/$1',
|
||||
'e-shared/(.*)$': '<rootDir>/packages/e/shared/$1',
|
||||
'e-gravity/(.*)$': '<rootDir>/packages/e/gravity/$1',
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"jsx": "react",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"shared/*": ["packages/shared/*"],
|
||||
"design/*": ["packages/design/src/*"],
|
||||
"design": ["packages/design/src/"],
|
||||
"teleport/*": ["packages/teleport/src/*"],
|
||||
"gravity/*": ["packages/gravity/src/*"],
|
||||
"e-gravity/*": ["packages/e/gravity/src/*"],
|
||||
"e-teleport/*": ["packages/e/teleport/src/*"],
|
||||
"e-shared/*": ["packages/e/shared/src/*"],
|
||||
}
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "namespaces",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"storybook": "start-storybook -p 9002 -c .storybook",
|
||||
"test": "jest",
|
||||
"tdd": "jest . --watch",
|
||||
"build-gravity": "yarn workspace @gravitational/gravity run build",
|
||||
"build-teleport": "yarn workspace @gravitational/teleport run build"
|
||||
},
|
||||
"private": true,
|
||||
"workspaces": [
|
||||
"packages/*/**"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
const presets = ['@babel/preset-env', '@babel/preset-react'];
|
||||
|
||||
const plugins = [
|
||||
'@babel/plugin-proposal-class-properties',
|
||||
'@babel/plugin-proposal-object-rest-spread',
|
||||
'@babel/plugin-syntax-dynamic-import',
|
||||
];
|
||||
|
||||
module.exports = {
|
||||
env: {
|
||||
test: {
|
||||
presets: [
|
||||
['@babel/preset-env', { targets: { node: 'current' } }],
|
||||
'@babel/preset-react',
|
||||
],
|
||||
},
|
||||
development: {
|
||||
plugins: [
|
||||
'react-hot-loader/babel',
|
||||
...plugins,
|
||||
'babel-plugin-styled-components',
|
||||
],
|
||||
},
|
||||
},
|
||||
presets,
|
||||
plugins,
|
||||
};
|
||||
@@ -0,0 +1,69 @@
|
||||
const path = require('path');
|
||||
const createConfig = require('./webpack/webpack.base');
|
||||
|
||||
module.exports = {
|
||||
parser: 'babel-eslint',
|
||||
parserOptions: {
|
||||
ecmaVersion: 6,
|
||||
sourceType: 'module',
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
experimentalObjectRestSpread: true,
|
||||
},
|
||||
},
|
||||
env: {
|
||||
es6: true,
|
||||
browser: true,
|
||||
node: true,
|
||||
mocha: true,
|
||||
},
|
||||
globals: {
|
||||
expect: true,
|
||||
jest: true,
|
||||
},
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:import/errors',
|
||||
'plugin:import/warnings',
|
||||
],
|
||||
plugins: ['react', 'babel', 'import'],
|
||||
|
||||
rules: {
|
||||
'comma-dangle': 0,
|
||||
'no-mixed-spaces-and-tabs': 0,
|
||||
'no-alert': 0,
|
||||
'import/no-named-as-default': 0,
|
||||
'import/default': 2,
|
||||
'import/named': 2,
|
||||
'import/no-unresolved': 2,
|
||||
'no-underscore-dangle': 0,
|
||||
'no-case-declarations': 0,
|
||||
'strict': 0,
|
||||
'no-console': 1,
|
||||
'no-trailing-spaces': 2,
|
||||
'react/display-name': 0,
|
||||
'react/jsx-no-undef': 2,
|
||||
'react/jsx-pascal-case': 2,
|
||||
'react/no-danger': 2,
|
||||
'react/jsx-no-duplicate-props': 2,
|
||||
'react/jsx-sort-prop-types': 0,
|
||||
'react/jsx-sort-props': 0,
|
||||
'react/jsx-uses-react': 1,
|
||||
'react/jsx-uses-vars': 1,
|
||||
'react/no-did-mount-set-state': 1,
|
||||
'react/no-did-update-set-state': 1,
|
||||
'react/no-unknown-property': 1,
|
||||
'react/prop-types': 0,
|
||||
'react/react-in-jsx-scope': 1,
|
||||
'react/self-closing-comp': 0,
|
||||
'react/sort-comp': 0,
|
||||
'react/jsx-wrap-multilines': 1,
|
||||
},
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
webpack: {
|
||||
config: createConfig()
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env node
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const defaultConfig = process.argv.some(arg => arg.startsWith('--dev'))
|
||||
? 'webpack.dev.config.js'
|
||||
: 'webpack.prod.config.js';
|
||||
|
||||
if (!process.argv.some(arg => arg.startsWith('--config'))) {
|
||||
let webpackConfig = path.join(process.cwd(), 'webpack.config.js');
|
||||
if (!fs.existsSync(webpackConfig)) {
|
||||
webpackConfig = path.join(__dirname, '../webpack', defaultConfig);
|
||||
}
|
||||
|
||||
process.argv.push('--config', webpackConfig);
|
||||
}
|
||||
|
||||
require('webpack-cli');
|
||||
Executable
+30
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env node
|
||||
process.on('unhandledRejection', err => {
|
||||
throw err;
|
||||
});
|
||||
|
||||
const spawn = require('cross-spawn');
|
||||
const path = require('path');
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
const devServerPath = path.join(__dirname, '../devServer.js');
|
||||
const nodeArgs = [devServerPath].concat(args);
|
||||
|
||||
const result = spawn.sync('node', nodeArgs, { stdio: 'inherit' });
|
||||
if (result.signal) {
|
||||
if (result.signal === 'SIGKILL') {
|
||||
console.log(
|
||||
'The build failed because the process exited too early. ' +
|
||||
'This probably means the system ran out of memory or someone called ' +
|
||||
'`kill -9` on the process.'
|
||||
);
|
||||
} else if (result.signal === 'SIGTERM') {
|
||||
console.log(
|
||||
'The build failed because the process exited too early. ' +
|
||||
'Someone might have called `kill` or `killall`, or the system could ' +
|
||||
'be shutting down.'
|
||||
);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
process.exit(result.status);
|
||||
@@ -0,0 +1,144 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const uri = require('url');
|
||||
const WebpackDevServer = require('webpack-dev-server');
|
||||
const webpack = require('webpack');
|
||||
const proxy = require('http-proxy').createProxyServer();
|
||||
const changeProxyResponse = require('./devServerUtils');
|
||||
const webpackConfig = require('./webpack/webpack.dev.config');
|
||||
|
||||
// parse target URL
|
||||
const argv = require('optimist')
|
||||
.usage('Usage: $0 -proxy [url]')
|
||||
.demand(['proxy']).argv;
|
||||
|
||||
const urlObj = uri.parse(argv.proxy);
|
||||
|
||||
if (!urlObj.host) {
|
||||
console.error('invalid URL: ' + argv.proxy);
|
||||
return;
|
||||
}
|
||||
|
||||
const PROXY_TARGET = urlObj.host;
|
||||
const ROOT = '/web';
|
||||
const PORT = '8080';
|
||||
const WEBPACK_CLIENT_ENTRY =
|
||||
'webpack-dev-server/client?https://0.0.0.0:' + PORT;
|
||||
const WEBPACK_SRV_ENTRY = 'webpack/hot/dev-server';
|
||||
|
||||
for (var prop in webpackConfig.entry) {
|
||||
webpackConfig.entry[prop].unshift('react-hot-loader/patch');
|
||||
webpackConfig.entry[prop].unshift(WEBPACK_CLIENT_ENTRY, WEBPACK_SRV_ENTRY);
|
||||
}
|
||||
|
||||
function getTargetOptions() {
|
||||
return {
|
||||
target: 'https://' + PROXY_TARGET,
|
||||
secure: false,
|
||||
changeOrigin: true,
|
||||
xfwd: true,
|
||||
};
|
||||
}
|
||||
|
||||
const compiler = webpack(webpackConfig);
|
||||
|
||||
const server = new WebpackDevServer(compiler, {
|
||||
proxy: {
|
||||
'/web/grafana/*': getTargetOptions(),
|
||||
'/web/config.*': getTargetOptions(),
|
||||
'/pack/v1/*': getTargetOptions(),
|
||||
'/portalapi/*': getTargetOptions(),
|
||||
'/portal*': getTargetOptions(),
|
||||
'/proxy/*': getTargetOptions(),
|
||||
'/v1/*': getTargetOptions(),
|
||||
'/app/*': getTargetOptions(),
|
||||
'/sites/v1/*': getTargetOptions(),
|
||||
},
|
||||
publicPath: ROOT + '/app',
|
||||
hot: true,
|
||||
disableHostCheck: true,
|
||||
https: true,
|
||||
inline: true,
|
||||
headers: { 'X-Custom-Header': 'yes' },
|
||||
//stats: { colors: true },
|
||||
stats: 'errors-only',
|
||||
});
|
||||
|
||||
// tell webpack dev server to proxy below sockets requests to actual server
|
||||
server.listeningApp.on('upgrade', function(req, socket) {
|
||||
console.log('proxying ws', req.url);
|
||||
proxy.ws(req, socket, {
|
||||
target: 'wss://' + PROXY_TARGET,
|
||||
secure: false,
|
||||
});
|
||||
});
|
||||
|
||||
const indexHtmlPath = path.join(process.cwd(), '//dist//index.html');
|
||||
const htmlToSend = fs.readFileSync(indexHtmlPath, 'utf8');
|
||||
|
||||
// to enable Hot Module Reload we need to serve local index.html.
|
||||
// since local index.html has no embeded TOKEN, we need to:
|
||||
// 1) make a proxy request
|
||||
// 2) modify proxy response by replacing server index.html with the local
|
||||
// 3) insert embeded by server token into the local
|
||||
server.app.use(
|
||||
changeProxyResponse(
|
||||
(req, res) => {
|
||||
// return true if you want to modify the response later
|
||||
var contentType = res.getHeader('Content-Type');
|
||||
if (contentType && contentType.startsWith('text/html')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
(req, res, body) => {
|
||||
// body is a Buffer with the current response; return Buffer or string with the modified response
|
||||
// can also return a Promise.
|
||||
var str = body.toString();
|
||||
res.set({
|
||||
'content-security-policy': '',
|
||||
});
|
||||
|
||||
if (req.path.endsWith('/complete/')) {
|
||||
return body;
|
||||
}
|
||||
|
||||
var htmlWithTokens = htmlToSend;
|
||||
htmlWithTokens = replaceToken(
|
||||
new RegExp(/<meta name="grv_csrf_token" .*\>/),
|
||||
str,
|
||||
htmlWithTokens
|
||||
);
|
||||
htmlWithTokens = replaceToken(
|
||||
new RegExp(/<meta name="grv_bearer_token" .*\>/),
|
||||
str,
|
||||
htmlWithTokens
|
||||
);
|
||||
return htmlWithTokens;
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
function serveHTML() {
|
||||
return function(req, res) {
|
||||
proxy.web(req, res, getTargetOptions());
|
||||
};
|
||||
}
|
||||
|
||||
server.app.get(ROOT + '/*', serveHTML());
|
||||
server.app.get(ROOT, serveHTML());
|
||||
|
||||
server.listen(PORT, '0.0.0.0', function() {
|
||||
console.log(
|
||||
'Dev Server is up and running: https://localhost:' + PORT + '/web/'
|
||||
);
|
||||
});
|
||||
|
||||
function replaceToken(regex, takeFrom, insertTo) {
|
||||
var value = takeFrom.match(regex);
|
||||
if (value) {
|
||||
return insertTo.replace(regex, value[0]);
|
||||
}
|
||||
return insertTo;
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
//
|
||||
// taken and modified from https://github.com/mo22/express-modify-response
|
||||
//
|
||||
module.exports = function expressModifyResponse(checkCallback, modifyCallback) {
|
||||
return function expressModifyResponse(req, res, next) {
|
||||
var _end = res.end;
|
||||
var _write = res.write;
|
||||
var checked = false;
|
||||
var buffers = [];
|
||||
var addBuffer = (chunk, encoding) => {
|
||||
if (chunk === undefined)
|
||||
return;
|
||||
if (typeof chunk === 'string') {
|
||||
chunk = new Buffer(chunk, encoding);
|
||||
}
|
||||
buffers.push(chunk);
|
||||
};
|
||||
|
||||
var _writeHead = res.writeHead;
|
||||
|
||||
res.writeHead = function () {
|
||||
// writeHead supports (statusCode, headers) as well as (statusCode,
|
||||
// statusMessage, headers)
|
||||
var headers = (arguments.length > 2)
|
||||
? arguments[2]
|
||||
: arguments[1];
|
||||
var contentType = this.getHeader('content-type');
|
||||
|
||||
if ((typeof contentType != 'undefined') && (contentType.indexOf('text/html') == 0)) {
|
||||
res.isHtml = true;
|
||||
|
||||
// Strip off the content length since it will change.
|
||||
res.removeHeader('Content-Length');
|
||||
|
||||
if (headers) {
|
||||
delete headers['content-length'];
|
||||
}
|
||||
}
|
||||
|
||||
_writeHead.apply(res, arguments);
|
||||
};
|
||||
|
||||
res.write = function write(chunk, encoding) {
|
||||
if (!checked) {
|
||||
checked = true;
|
||||
var hook = checkCallback(req, res);
|
||||
if (!hook) {
|
||||
res.end = _end;
|
||||
res.write = _write;
|
||||
return res.write(chunk, encoding);
|
||||
} else {
|
||||
addBuffer(chunk, encoding);
|
||||
}
|
||||
} else {
|
||||
addBuffer(chunk, encoding);
|
||||
}
|
||||
};
|
||||
|
||||
res.end = function end(chunk, encoding) {
|
||||
if (!checked) {
|
||||
checked = true;
|
||||
var hook = checkCallback(req, res);
|
||||
if (!hook) {
|
||||
res.end = _end;
|
||||
res.write = _write;
|
||||
return res.end(chunk, encoding);
|
||||
} else {
|
||||
addBuffer(chunk, encoding);
|
||||
}
|
||||
} else {
|
||||
addBuffer(chunk, encoding);
|
||||
}
|
||||
var buffer = Buffer.concat(buffers);
|
||||
|
||||
Promise
|
||||
.resolve(modifyCallback(req, res, buffer))
|
||||
.then((result) => {
|
||||
if (typeof result === 'string') {
|
||||
result = new Buffer(result, 'utf-8');
|
||||
}
|
||||
|
||||
if (res.getHeader('Content-Length')) {
|
||||
res.setHeader('Content-Length', String(result.length));
|
||||
}
|
||||
res.end = _end;
|
||||
res.write = _write;
|
||||
res.write(result);
|
||||
res.end();
|
||||
})
|
||||
.catch((e) => {
|
||||
// handle?
|
||||
next(e);
|
||||
});
|
||||
};
|
||||
|
||||
next();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="referrer" content="origin" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="grv_csrf_token" content="{{ .XCSRF }}" />
|
||||
<meta name="grv_bearer_token" content="{{ .Session }}" />
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
<script src="/web/config.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"name": "@gravitational/build",
|
||||
"version": "1.0.1",
|
||||
"description": "build scripts",
|
||||
"main": "index.js",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/gravitational/webapps/webapps.git",
|
||||
"directory": "packages/build"
|
||||
},
|
||||
"bin": {
|
||||
"gravity-start": "./bin/start.js",
|
||||
"gravity-build": "./bin/build.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.3.4",
|
||||
"@babel/plugin-proposal-class-properties": "^7.2.1",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.2.0",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
|
||||
"@babel/plugin-transform-classes": "^7.3.4",
|
||||
"@babel/preset-env": "^7.3.4",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@hot-loader/react-dom": "^16.8.6",
|
||||
"@storybook/addon-info": "^5.1.9",
|
||||
"@storybook/react": "^5.1.9",
|
||||
"babel-eslint": "10.0.1",
|
||||
"babel-loader": "8.0.6",
|
||||
"body-parser": "1.18.3",
|
||||
"core-js": "^3",
|
||||
"cross-env": "5.0.5",
|
||||
"css-loader": "1.0.1",
|
||||
"eslint": "4.19.1",
|
||||
"eslint-import-resolver-webpack": "0.11.0",
|
||||
"eslint-loader": "2.1.1",
|
||||
"eslint-plugin-babel": "4.1.2",
|
||||
"eslint-plugin-import": "2.16.0",
|
||||
"eslint-plugin-react": "7.11.1",
|
||||
"events": "1.0.2",
|
||||
"expect": "1.20.2",
|
||||
"express": "4.16.3",
|
||||
"file-loader": "2.0.0",
|
||||
"html-webpack-plugin": "3.2.0",
|
||||
"jest": "^24.8.0",
|
||||
"jest-styled-components": "^6.3.1",
|
||||
"optimist": "^0.6.1",
|
||||
"raw-loader": "0.5.1",
|
||||
"react": "^16.8.4",
|
||||
"react-dom": "^16.8.4",
|
||||
"react-hot-loader": "4.11.0",
|
||||
"serve-static": "1.13.2",
|
||||
"style-loader": "0.19.1",
|
||||
"styled-components": "4.1.2",
|
||||
"svg-url-loader": "^2.3.2",
|
||||
"url-loader": "1.1.2",
|
||||
"webpack": "4.33.0",
|
||||
"webpack-bundle-analyzer": "^3.3.2",
|
||||
"webpack-cli": "3.3.2",
|
||||
"webpack-dev-server": "3.1.11",
|
||||
"cross-spawn": "6.0.5"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const HtmlWebPackPlugin = require('html-webpack-plugin');
|
||||
|
||||
const appDirectory = fs.realpathSync(process.cwd());
|
||||
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
|
||||
|
||||
module.exports = function createConfig() {
|
||||
return {
|
||||
optimization: {
|
||||
splitChunks: {
|
||||
cacheGroups: {
|
||||
vendors: {
|
||||
chunks: 'all',
|
||||
name: 'vendor',
|
||||
test: /([\\/]node_modules[\\/])/,
|
||||
priority: -10,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
entry: {
|
||||
app: ['./src/boot.js'],
|
||||
},
|
||||
|
||||
output: {
|
||||
// used by loaders to generate various URLs within CSS, JS based off publicPath
|
||||
publicPath: '/web/app/',
|
||||
|
||||
path: resolveApp('dist/app'),
|
||||
|
||||
/*
|
||||
* format of the output file names. [name] stands for 'entry' keys
|
||||
* defined in the 'entry' section
|
||||
**/
|
||||
filename: '[name].[hash].js',
|
||||
|
||||
// chunk file name format
|
||||
chunkFilename: '[name].[chunkhash].js',
|
||||
},
|
||||
|
||||
resolve: {
|
||||
// some vendor libraries expect below globals to be defined
|
||||
alias: {
|
||||
jQuery: 'jquery',
|
||||
teleport: path.join(__dirname, '/../../teleport/src'),
|
||||
'e-teleport': path.join(__dirname, '/../../e/teleport/src'),
|
||||
'e-shared': path.join(__dirname, '/../../e/shared/src'),
|
||||
'e-gravity': path.join(__dirname, '/../../e/gravity/src'),
|
||||
design: path.join(__dirname, '/../../design/src'),
|
||||
shared: path.join(__dirname, '/../../shared'),
|
||||
gravity: path.join(__dirname, '/../../gravity/src'),
|
||||
},
|
||||
|
||||
/*
|
||||
* root path to resolve js our modules, enables us to use absolute path.
|
||||
* For ex: require('./../../../config') can be replaced with require('app/config')
|
||||
**/
|
||||
modules: ['node_modules', 'src'],
|
||||
extensions: ['.js', '.jsx'],
|
||||
},
|
||||
|
||||
noParse: function(content) {
|
||||
return /xterm.js$/.test(content);
|
||||
},
|
||||
|
||||
rules: {
|
||||
fonts: {
|
||||
test: /fonts\/(.)+\.(woff|woff2|ttf|eot|svg)/,
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 102400, // 100kb
|
||||
name: '/assets/fonts/[name].[ext]',
|
||||
},
|
||||
},
|
||||
|
||||
svg: {
|
||||
test: /\.svg$/,
|
||||
loader: 'svg-url-loader',
|
||||
options: {
|
||||
noquotes: true,
|
||||
},
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
|
||||
css() {
|
||||
return {
|
||||
test: /\.(css)$/,
|
||||
use: ['style-loader', 'css-loader'],
|
||||
};
|
||||
},
|
||||
|
||||
images: {
|
||||
test: /\.(png|jpg|gif)$/,
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: '/assets/img/img-[hash:6].[ext]',
|
||||
},
|
||||
},
|
||||
jsx(args) {
|
||||
args = args || {};
|
||||
var emitWarning = false;
|
||||
if (args.withHot) {
|
||||
emitWarning = true;
|
||||
}
|
||||
|
||||
return {
|
||||
test: /\.(js|jsx)$/,
|
||||
exclude: /(node_modules)|(assets)/,
|
||||
use: [
|
||||
{
|
||||
loader: 'babel-loader',
|
||||
},
|
||||
{
|
||||
loader: 'eslint-loader',
|
||||
options: {
|
||||
emitWarning,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
plugins: {
|
||||
// builds index html page, the main entry point for application
|
||||
createIndexHtml(options) {
|
||||
return createHtmlPluginInstance({
|
||||
filename: '../index.html',
|
||||
title: '',
|
||||
inject: true,
|
||||
template: path.join(__dirname, '/../index.ejs'),
|
||||
...options,
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
function createHtmlPluginInstance(cfg) {
|
||||
cfg.inject = true;
|
||||
return new HtmlWebPackPlugin(cfg);
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
const webpack = require('webpack');
|
||||
const createConfig = require('./webpack.base');
|
||||
|
||||
process.env.BABEL_ENV = 'development';
|
||||
process.env.NODE_ENV = 'development';
|
||||
|
||||
const baseCfg = createConfig();
|
||||
|
||||
var cfg = {
|
||||
entry: baseCfg.entry,
|
||||
output: {
|
||||
...baseCfg.output,
|
||||
filename: '[name].js',
|
||||
chunkFilename: '[name].js',
|
||||
},
|
||||
resolve: {
|
||||
...baseCfg.resolve,
|
||||
alias: {
|
||||
...baseCfg.resolve.alias,
|
||||
'react-dom': '@hot-loader/react-dom',
|
||||
},
|
||||
},
|
||||
|
||||
devtool: false,
|
||||
|
||||
mode: 'development',
|
||||
|
||||
optimization: baseCfg.optimization,
|
||||
|
||||
module: {
|
||||
noParse: baseCfg.noParse,
|
||||
strictExportPresence: true,
|
||||
rules: [
|
||||
baseCfg.rules.fonts,
|
||||
baseCfg.rules.svg,
|
||||
baseCfg.rules.images,
|
||||
baseCfg.rules.jsx({ withHot: true }),
|
||||
baseCfg.rules.css(),
|
||||
],
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
baseCfg.plugins.createIndexHtml(),
|
||||
],
|
||||
};
|
||||
|
||||
module.exports = cfg;
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
const webpack = require('webpack');
|
||||
const createConfig = require('./webpack.base');
|
||||
const baseCfg = createConfig();
|
||||
|
||||
process.env.BABEL_ENV = 'production';
|
||||
process.env.NODE_ENV = 'production';
|
||||
|
||||
//const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
|
||||
// .BundleAnalyzerPlugin;
|
||||
|
||||
var cfg = {
|
||||
entry: baseCfg.entry,
|
||||
output: baseCfg.output,
|
||||
resolve: baseCfg.resolve,
|
||||
|
||||
mode: 'production',
|
||||
|
||||
optimization: {
|
||||
...baseCfg.optimization,
|
||||
minimize: false,
|
||||
},
|
||||
|
||||
module: {
|
||||
noParse: baseCfg.noParse,
|
||||
strictExportPresence: true,
|
||||
rules: [
|
||||
baseCfg.rules.fonts,
|
||||
baseCfg.rules.svg,
|
||||
baseCfg.rules.images,
|
||||
baseCfg.rules.jsx(),
|
||||
baseCfg.rules.css(),
|
||||
],
|
||||
},
|
||||
|
||||
plugins: [
|
||||
// new BundleAnalyzerPlugin(),
|
||||
new webpack.HashedModuleIdsPlugin(),
|
||||
baseCfg.plugins.createIndexHtml(),
|
||||
],
|
||||
};
|
||||
|
||||
module.exports = cfg;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "@gravitational/design",
|
||||
"version": "1.0.0",
|
||||
"description": "Gravitatinal design system",
|
||||
"main": "index.js",
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"storybook": "start-storybook -p 9002 -c .storybook",
|
||||
"test": "jest",
|
||||
"tdd": "jest . --watch"
|
||||
},
|
||||
"repository": {
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/gravitational/webapps/webapps.git",
|
||||
"directory": "packages/design"
|
||||
},
|
||||
"dependencies": {
|
||||
"cross-env": "5.0.5",
|
||||
"styled-system": "^3.1.11",
|
||||
"@gravitational/build": "^1.0.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { configure } from '@storybook/react';
|
||||
import { addDecorator } from '@storybook/react';
|
||||
import theme from './../../theme';
|
||||
import ThemeProvider from '../ThemeProvider';
|
||||
import Box from './../Box';
|
||||
|
||||
const ThemeDecorator = storyFn => (
|
||||
<ThemeProvider theme={theme}>
|
||||
<Box p={3}>
|
||||
{storyFn()}
|
||||
</Box>
|
||||
</ThemeProvider>
|
||||
)
|
||||
|
||||
addDecorator(ThemeDecorator);
|
||||
|
||||
const sharedReq = require.context('./../../', true, /\.story.js$/);
|
||||
const srcReq = require.context('./../../../src', true, /\.story.js$/);
|
||||
|
||||
const loadStories = () => {
|
||||
sharedReq.keys().forEach(sharedReq);
|
||||
srcReq.keys().forEach(srcReq);
|
||||
}
|
||||
|
||||
configure(loadStories, module);
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const webpackBaseCfg = require('@gravitational/build/webpack/webpack.base');
|
||||
|
||||
module.exports = ({ config }) => {
|
||||
config.devtool = false;
|
||||
config.resolve = {
|
||||
...config.resolve,
|
||||
...webpackBaseCfg.resolve,
|
||||
};
|
||||
|
||||
return config;
|
||||
};
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import PropTypes from 'prop-types';
|
||||
import { space, color, width } from 'design/system';
|
||||
import defaultTheme from 'design/theme'
|
||||
|
||||
const kindColors = props => {
|
||||
const { kindColor, theme } = props;
|
||||
switch (kindColor) {
|
||||
case 'danger':
|
||||
return {
|
||||
background: theme.colors.danger,
|
||||
color: theme.colors.primary.contrastText
|
||||
}
|
||||
case 'info':
|
||||
return {
|
||||
background: theme.colors.info,
|
||||
color: theme.colors.primary.contrastText
|
||||
}
|
||||
case 'warning':
|
||||
return {
|
||||
background: theme.colors.warning,
|
||||
color: theme.colors.primary.contrastText
|
||||
}
|
||||
case 'success':
|
||||
return {
|
||||
background: theme.colors.success,
|
||||
color: theme.colors.primary.contrastText
|
||||
}
|
||||
default:
|
||||
return {
|
||||
background: theme.colors.danger,
|
||||
color: theme.colors.primary.contrastText
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Alert = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 8px;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, .12), 0 2px 2px rgba(0, 0, 0, .24);
|
||||
font-weight: ${({theme}) => theme.fontWeights.regular};
|
||||
font-size: 16px;
|
||||
margin: 0 0 16px 0;
|
||||
min-height: 48px;
|
||||
padding: 8px 16px;
|
||||
overflow: auto;
|
||||
word-break: break-all;
|
||||
${space}
|
||||
${kindColors}
|
||||
${width}
|
||||
|
||||
a {
|
||||
color: ${({theme}) => theme.colors.light};
|
||||
}
|
||||
`;
|
||||
|
||||
Alert.propTypes = {
|
||||
kind: PropTypes.oneOf(['danger', 'info', 'warning', 'success']),
|
||||
...color.propTypes,
|
||||
...space.propTypes,
|
||||
...width.propTypes,
|
||||
};
|
||||
|
||||
Alert.defaultProps = {
|
||||
kindColor: 'danger',
|
||||
theme: defaultTheme,
|
||||
};
|
||||
|
||||
Alert.displayName = 'Alert';
|
||||
|
||||
export default Alert;
|
||||
export const Danger = props => <Alert kindColor="danger" {...props} />
|
||||
export const Info = props => <Alert kindColor="info" {...props} />
|
||||
export const Warning = props => <Alert kindColor="warning" {...props} />
|
||||
export const Success = props => <Alert kindColor="success" {...props} />
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import { withInfo } from '@storybook/addon-info';
|
||||
import Alert from './index';
|
||||
|
||||
storiesOf('Desigin/Alert', module)
|
||||
.addDecorator(withInfo)
|
||||
.add('Alert Component', () => {
|
||||
return (
|
||||
<Alert>This is an error message</Alert>
|
||||
);
|
||||
})
|
||||
.add('Danger Alert', () => {
|
||||
return (
|
||||
<Alert kindColor="danger">This is an error message</Alert>
|
||||
);
|
||||
})
|
||||
.add('Warning Alert', () => {
|
||||
return (
|
||||
<Alert kindColor="warning">This is a warning message</Alert>
|
||||
);
|
||||
})
|
||||
.add('Info Alert', () => {
|
||||
return (
|
||||
<Alert kindColor="info">This is a informational message</Alert>
|
||||
);
|
||||
})
|
||||
.add('Success Alert', () => {
|
||||
return (
|
||||
<Alert kindColor="success">This is a success message</Alert>
|
||||
);
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import Alert, { Danger, Info, Warning, Success } from './Alert';
|
||||
export default Alert;
|
||||
export {
|
||||
Danger, Info, Warning, Success
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import styled from 'styled-components';
|
||||
import defaultTheme from './../theme';
|
||||
import {
|
||||
overflow,
|
||||
borders,
|
||||
borderRadius,
|
||||
flex,
|
||||
height,
|
||||
maxWidth,
|
||||
minHeight,
|
||||
maxHeight,
|
||||
minWidth,
|
||||
alignSelf,
|
||||
justifySelf,
|
||||
space,
|
||||
width,
|
||||
color,
|
||||
textAlign,
|
||||
} from '../system';
|
||||
|
||||
const Box = styled.div`
|
||||
box-sizing: border-box;
|
||||
${maxWidth}
|
||||
${minWidth}
|
||||
${space}
|
||||
${height}
|
||||
${minHeight}
|
||||
${maxHeight}
|
||||
${width}
|
||||
${color}
|
||||
${textAlign}
|
||||
${flex}
|
||||
${alignSelf}
|
||||
${justifySelf}
|
||||
${borders}
|
||||
${borderRadius}
|
||||
${overflow}
|
||||
`;
|
||||
|
||||
Box.displayName = 'Box';
|
||||
Box.defaultProps = {
|
||||
theme: defaultTheme,
|
||||
};
|
||||
|
||||
Box.propTypes = {
|
||||
...space.propTypes,
|
||||
...height.propTypes,
|
||||
...width.propTypes,
|
||||
...color.propTypes,
|
||||
...textAlign.propTypes,
|
||||
...flex.propTypes,
|
||||
...alignSelf.propTypes,
|
||||
...justifySelf.propTypes,
|
||||
...borders.propTypes,
|
||||
...overflow.propTypes,
|
||||
};
|
||||
|
||||
export default Box;
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { storiesOf } from '@storybook/react'
|
||||
import { withInfo } from '@storybook/addon-info'
|
||||
import Box from './Box';
|
||||
|
||||
storiesOf('Desigin/Box', module)
|
||||
.addDecorator(withInfo)
|
||||
.add('Layout component', () => (
|
||||
<Box color="white" bg="blue">
|
||||
this is a simple div
|
||||
</Box>
|
||||
))
|
||||
.add('Padding', () => (
|
||||
<Box bg="blue" p={3}>
|
||||
Hello
|
||||
</Box>
|
||||
))
|
||||
.add('Margin', () => (
|
||||
<Box bg="blue" m={4}>
|
||||
Hello
|
||||
</Box>
|
||||
))
|
||||
.add('Color', () => (
|
||||
<Box bg="blue" p={3} color='white'>
|
||||
Hello
|
||||
</Box>
|
||||
))
|
||||
.add('Background Color', () => (
|
||||
<Box bg="blue" p={3} color='white'>
|
||||
Hello
|
||||
</Box>
|
||||
))
|
||||
.add('Border Radius', () => (
|
||||
<div>
|
||||
<Box
|
||||
borderRadius="16px"
|
||||
color='white'
|
||||
p={5}
|
||||
bg='blue'>
|
||||
16 Pixel Border Radius
|
||||
</Box>
|
||||
<Box
|
||||
mt={4}
|
||||
borderBottomRightRadius={3}
|
||||
borderBottomLeftRadius={3}
|
||||
color='white'
|
||||
p={5}
|
||||
bg='blue'>
|
||||
Border Radius on Bottom Left & Right
|
||||
</Box>
|
||||
<Box
|
||||
mt={4}
|
||||
borderTopLeftRadius={16}
|
||||
borderTopRightRadius={16}
|
||||
color='white'
|
||||
p={5}
|
||||
bg='blue'>
|
||||
Border Radius on Top Left & Right
|
||||
</Box>
|
||||
</div>
|
||||
))
|
||||
.add('Width', () => (
|
||||
<Box
|
||||
p={3}
|
||||
width={1 / 2}
|
||||
color='white'
|
||||
bg='blue'>
|
||||
Half Width
|
||||
</Box>
|
||||
))
|
||||
.add('Pixel Width', () => (
|
||||
<Box
|
||||
p={3}
|
||||
width={256}
|
||||
color='white'
|
||||
bg='blue'>
|
||||
256px width
|
||||
</Box>
|
||||
))
|
||||
.add('VW Width', () => (
|
||||
<Box
|
||||
p={3}
|
||||
width='50vw'
|
||||
color='white'
|
||||
bg='blue'>
|
||||
50vw width
|
||||
</Box>
|
||||
))
|
||||
.add('Directional Padding', () => (
|
||||
<Box p={3}>
|
||||
<Box m={2} pt={3} color='white' bg='blue'>Padding Top</Box>
|
||||
<Box m={2} pr={4} color='white' bg='blue'>Padding Right</Box>
|
||||
<Box m={2} pb={3} color='white' bg='blue'>Padding Bottom</Box>
|
||||
<Box m={2} pl={4} color='white' bg='blue'>Padding Left</Box>
|
||||
<Box m={2} px={4} color='white' bg='blue'>Padding X-Axis</Box>
|
||||
<Box m={2} py={4} color='white' bg='blue'>Padding Y-Axis</Box>
|
||||
</Box>
|
||||
))
|
||||
.add('Directional Margin', () => (
|
||||
<Box p={3}>
|
||||
<Box mt={5} color='white' bg='blue'>Margin Top</Box>
|
||||
<Box mr={3} color='white' bg='blue'>Margin Right</Box>
|
||||
<Box mb={4} color='white' bg='blue'>Margin Bottom</Box>
|
||||
<Box ml={5} color='white' bg='blue'>Margin Left</Box>
|
||||
<Box mx={5} color='white' bg='blue'>Margin X-Axis</Box>
|
||||
<Box my={5} color='white' bg='blue'>Margin Y-Axis</Box>
|
||||
</Box>
|
||||
));
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import Box from './Box';
|
||||
|
||||
export default Box;
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import styled from 'styled-components'
|
||||
import PropTypes from 'prop-types'
|
||||
import { space, width, height } from 'design/system';
|
||||
import defaultTheme from 'design/theme';
|
||||
|
||||
const Button = ({ children, setRef, ...props}) => {
|
||||
return (
|
||||
<StyledButton {...props} ref={setRef}>
|
||||
{children}
|
||||
</StyledButton>
|
||||
)
|
||||
}
|
||||
|
||||
const size = props => {
|
||||
switch (props.size) {
|
||||
case 'small':
|
||||
return {
|
||||
fontSize: '10px',
|
||||
minHeight: '24px',
|
||||
padding: '0px 16px'
|
||||
}
|
||||
case 'large':
|
||||
return {
|
||||
minHeight: '48px',
|
||||
fontSize: '14px',
|
||||
padding: '0px 48px'
|
||||
}
|
||||
default:
|
||||
// medium
|
||||
return {
|
||||
minHeight: '40px',
|
||||
fontSize: `12px`,
|
||||
padding: '0px 32px'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const themedStyles = props => {
|
||||
const { colors } = props.theme;
|
||||
const style = {
|
||||
color: colors.secondary.contrastText,
|
||||
'&:disabled': {
|
||||
background: colors.action.disabledBackground,
|
||||
color: colors.action.disabled
|
||||
},
|
||||
}
|
||||
|
||||
return {
|
||||
...kinds(props),
|
||||
...style,
|
||||
...size(props),
|
||||
...space(props),
|
||||
...width(props),
|
||||
...block(props),
|
||||
...height(props)
|
||||
}
|
||||
}
|
||||
|
||||
const kinds = props => {
|
||||
const { kind, theme } = props;
|
||||
switch(kind){
|
||||
case 'secondary':
|
||||
return {
|
||||
background: theme.colors.primary.light,
|
||||
|
||||
'&:hover, &:focus': {
|
||||
background: theme.colors.primary.lighter,
|
||||
}
|
||||
};
|
||||
case 'warning':
|
||||
return {
|
||||
background: theme.colors.error.dark,
|
||||
'&:hover, &:focus': {
|
||||
background: theme.colors.error.main
|
||||
}
|
||||
};
|
||||
case 'primary':
|
||||
default:
|
||||
return {
|
||||
background: theme.colors.secondary.main,
|
||||
'&:hover, &:focus': {
|
||||
background: theme.colors.secondary.light
|
||||
},
|
||||
'&:active': {
|
||||
background: theme.colors.secondary.dark,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const block = props => (props.block ? {
|
||||
width: '100%'
|
||||
} : null)
|
||||
|
||||
const StyledButton = styled.button`
|
||||
line-height: 1.5;
|
||||
margin: 0;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
font-weight: 600;
|
||||
outline: none;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
transition: all .3s;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
&:active {
|
||||
opacity: .56;
|
||||
}
|
||||
|
||||
// remove dotted Firefox outline
|
||||
::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
${themedStyles}
|
||||
`
|
||||
|
||||
Button.propTypes = {
|
||||
block: PropTypes.bool,
|
||||
secondary: PropTypes.bool,
|
||||
...space.propTypes,
|
||||
...height.propTypes
|
||||
}
|
||||
|
||||
Button.defaultProps = {
|
||||
size: 'medium',
|
||||
theme: defaultTheme
|
||||
}
|
||||
|
||||
Button.displayName = 'Button'
|
||||
|
||||
export default Button;
|
||||
export const ButtonPrimary = props => <Button kind="primary" {...props} />
|
||||
export const ButtonSecondary = props => <Button kind="secondary" {...props} />
|
||||
export const ButtonWarning = props => <Button kind="warning" {...props} />
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { storiesOf } from '@storybook/react'
|
||||
import { withInfo } from '@storybook/addon-info'
|
||||
import Button, { ButtonPrimary, ButtonSecondary, ButtonWarning } from './Button';
|
||||
import ButtonOutlinedDefault, * as ButtonOutlined from './../ButtonOutlined';
|
||||
import ButtonIcon from './../ButtonIcon';
|
||||
import ButtonLink from './../ButtonLink';
|
||||
import { AddUsers, Trash, Ellipsis } from './../Icon';
|
||||
import styled from 'styled-components';
|
||||
|
||||
storiesOf('Desigin/Button', module)
|
||||
.addDecorator(withInfo)
|
||||
.add('kinds', () => (
|
||||
<StyledBox>
|
||||
<ButtonPrimary>Primary</ButtonPrimary>
|
||||
<ButtonSecondary>Secondary</ButtonSecondary>
|
||||
<ButtonWarning >Warning</ButtonWarning>
|
||||
<ButtonLink href="" >Link Button</ButtonLink>
|
||||
<ButtonIcon> <AddUsers/></ButtonIcon>
|
||||
<ButtonIcon> <Ellipsis /></ButtonIcon>
|
||||
<ButtonIcon> <Trash /></ButtonIcon>
|
||||
<ButtonIcon> <Trash /></ButtonIcon>
|
||||
<ButtonOutlinedDefault>Default</ButtonOutlinedDefault>
|
||||
<ButtonOutlined.OutlinedPrimary>Primary</ButtonOutlined.OutlinedPrimary>
|
||||
</StyledBox>
|
||||
))
|
||||
.add('sizes', () => (
|
||||
<div>
|
||||
<StyledBox>
|
||||
<Button size="large" mr={3}>Large</Button>
|
||||
<Button size="medium" mr={3}>Medium</Button>
|
||||
<Button size="small" mr={3}>Small</Button>
|
||||
</StyledBox>
|
||||
<StyledBox>
|
||||
<ButtonIcon size={2}> <AddUsers/></ButtonIcon>
|
||||
<ButtonIcon size={1}> <Ellipsis /></ButtonIcon>
|
||||
<ButtonIcon size={0}> <Trash /></ButtonIcon>
|
||||
</StyledBox>
|
||||
</div>
|
||||
))
|
||||
.add('block', () => <Button block>Block Button</Button>)
|
||||
.add('states', () => (
|
||||
<StyledBox>
|
||||
<Button mr={3} disabled>Disabled</Button>
|
||||
<Button autoFocus> Focused</Button>
|
||||
</StyledBox>
|
||||
));
|
||||
|
||||
const StyledBox = styled.div`
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
> * {
|
||||
margin-left: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
`
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import Button, { ButtonPrimary, ButtonWarning, ButtonSecondary } from './Button';
|
||||
export default Button;
|
||||
export { ButtonPrimary, ButtonWarning, ButtonSecondary }
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import styled from 'styled-components'
|
||||
import Icon from '../Icon';
|
||||
import { space } from 'design/system';
|
||||
|
||||
const sizeMap = {
|
||||
0: {
|
||||
fontSize: '12px',
|
||||
height: '24px',
|
||||
width: '24px',
|
||||
},
|
||||
1: {
|
||||
fontSize: '16px',
|
||||
height: '32px',
|
||||
width: '32px',
|
||||
},
|
||||
2: {
|
||||
fontSize: '24px',
|
||||
height: '48px',
|
||||
width: '48px',
|
||||
}
|
||||
}
|
||||
|
||||
const defaultSize = sizeMap[1]
|
||||
|
||||
const size = props => {
|
||||
return sizeMap[props.size] || defaultSize;
|
||||
}
|
||||
|
||||
const fromProps = props => {
|
||||
const { theme } = props;
|
||||
return {
|
||||
'&:disabled': {
|
||||
color: theme.colors.action.disabled
|
||||
},
|
||||
'&:hover, &:focus': {
|
||||
background: theme.colors.action.hover,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ButtonIcon = ({children, setRef, ...rest}) => {
|
||||
return (
|
||||
<StyledButtonIcon ref={setRef} {...rest}>{children}</StyledButtonIcon>
|
||||
)
|
||||
}
|
||||
|
||||
const StyledButtonIcon = styled.button`
|
||||
align-items: center;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
outline: none;
|
||||
border-radius: 50%;
|
||||
overflow: visible;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
flex: 0 0 auto;
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
transition: all .3s;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
|
||||
${Icon}{
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
color: ${({ theme }) => theme.colors.action.disabled };
|
||||
}
|
||||
|
||||
${fromProps}
|
||||
${size}
|
||||
${space}
|
||||
`
|
||||
export default ButtonIcon;
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import ButtonIcon from './ButtonIcon';
|
||||
export default ButtonIcon;
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import styled from 'styled-components'
|
||||
import defaultTheme from 'design/theme';
|
||||
import Button from './../Button/Button';
|
||||
|
||||
function ButtonLink({ ...props }){
|
||||
return (
|
||||
<Button as={StyledButtonLink} {...props} />
|
||||
)
|
||||
}
|
||||
|
||||
ButtonLink.propTypes = {
|
||||
...Button.propTypes
|
||||
}
|
||||
|
||||
ButtonLink.defaultProps = {
|
||||
size: 'medium',
|
||||
theme: defaultTheme
|
||||
}
|
||||
|
||||
ButtonLink.displayName = 'ButtonLink'
|
||||
|
||||
const StyledButtonLink = styled.a`
|
||||
color: ${({ theme }) => theme.colors.link};
|
||||
font-weight: normal;
|
||||
background: none;
|
||||
text-decoration: underline;
|
||||
text-transform: none;
|
||||
|
||||
&:hover, &:focus {
|
||||
background: ${ ({theme}) => theme.colors.primary.light}
|
||||
}
|
||||
`
|
||||
|
||||
export default ButtonLink;
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import ButtonLink from './ButtonLink';
|
||||
export default ButtonLink;
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import styled from 'styled-components'
|
||||
import { space, width } from 'design/system';
|
||||
import defaultTheme from 'design/theme';
|
||||
|
||||
const ButtonOutlined = ({ children, setRef, ...props}) => {
|
||||
return (
|
||||
<StyledButton {...props} ref={setRef}>
|
||||
<span>{children}</span>
|
||||
</StyledButton>
|
||||
)
|
||||
}
|
||||
|
||||
const size = props => {
|
||||
switch (props.size) {
|
||||
case 'small':
|
||||
return {
|
||||
fontSize: '10px',
|
||||
padding: '8px 8px'
|
||||
}
|
||||
case 'medium':
|
||||
return {
|
||||
fontSize: `12px`,
|
||||
padding: '12px 32px'
|
||||
}
|
||||
case 'large':
|
||||
return {
|
||||
fontSize: '14px',
|
||||
padding: '20px 40px'
|
||||
}
|
||||
default:
|
||||
return {
|
||||
fontSize: `10px`,
|
||||
padding: '12px 24px'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const themedStyles = props => {
|
||||
const { colors } = props.theme;
|
||||
const style = {
|
||||
color: colors.secondary.contrastText,
|
||||
'&:disabled': {
|
||||
background: colors.action.disabledBackground,
|
||||
color: colors.action.disabled
|
||||
},
|
||||
}
|
||||
|
||||
return {
|
||||
...kinds(props),
|
||||
...style,
|
||||
...size(props),
|
||||
...space(props),
|
||||
...width(props),
|
||||
...block(props)
|
||||
}
|
||||
}
|
||||
|
||||
const kinds = props => {
|
||||
const { kind, theme } = props;
|
||||
switch(kind){
|
||||
case 'primary':
|
||||
return {
|
||||
borderColor: theme.colors.secondary.main,
|
||||
color: theme.colors.secondary.light,
|
||||
'&:hover, &:focus': {
|
||||
borderColor: theme.colors.secondary.light
|
||||
},
|
||||
'&:active': {
|
||||
borderColor: theme.colors.secondary.dark,
|
||||
},
|
||||
}
|
||||
default:
|
||||
return {
|
||||
borderColor: theme.colors.text.primary,
|
||||
color: theme.colors.text.primary,
|
||||
'&:hover, &:focus': {
|
||||
borderColor: theme.colors.light,
|
||||
color: theme.colors.light
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const block = props => (props.block ? {
|
||||
width: '100%'
|
||||
} : null)
|
||||
|
||||
const StyledButton = styled.button`
|
||||
border-radius: 4px;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 1px solid;
|
||||
box-sizing: border-box;
|
||||
background-color: transparent;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
font-weight: bold;
|
||||
outline: none;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
transition: all .3s;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
|
||||
&:active {
|
||||
opacity: .56;
|
||||
}
|
||||
|
||||
> span {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
${themedStyles}
|
||||
${kinds}
|
||||
${block}
|
||||
`
|
||||
|
||||
ButtonOutlined.propTypes = {
|
||||
...space.propTypes,
|
||||
}
|
||||
|
||||
ButtonOutlined.defaultProps = {
|
||||
size: 'medium',
|
||||
theme: defaultTheme
|
||||
}
|
||||
|
||||
ButtonOutlined.displayName = 'ButtonOutlined'
|
||||
|
||||
export default ButtonOutlined;
|
||||
export const OutlinedPrimary = props => <ButtonOutlined kind="primary" {...props} />
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import Button, { OutlinedPrimary } from './ButtonOutlined';
|
||||
export default Button;
|
||||
export {
|
||||
OutlinedPrimary
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import styled from 'styled-components';
|
||||
import Box from './../Box';
|
||||
import theme from './../theme';
|
||||
|
||||
const Card = styled(Box)`
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.24);
|
||||
border-radius: 8px;
|
||||
`;
|
||||
|
||||
Card.defaultProps = {
|
||||
theme: theme,
|
||||
bg: 'primary.light',
|
||||
};
|
||||
|
||||
Card.displayName = 'Card';
|
||||
|
||||
export default Card;
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { storiesOf } from '@storybook/react'
|
||||
import { withInfo } from '@storybook/addon-info'
|
||||
import Card from './Card'
|
||||
|
||||
storiesOf('Desigin/Card', module)
|
||||
.addDecorator(withInfo)
|
||||
.add('Card', () => (
|
||||
<Card width="500px" height="200px" m="0 auto">
|
||||
</Card>
|
||||
))
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import Card from './Card';
|
||||
export default Card;
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import styled from 'styled-components'
|
||||
import { Text, Alert, Card } from 'design';
|
||||
|
||||
export default function CardError({children}) {
|
||||
return (
|
||||
<Card
|
||||
color='text.onLight'
|
||||
bg='light'
|
||||
width='540px'
|
||||
mx='auto'
|
||||
my={6}
|
||||
p={5}
|
||||
children={children}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const Header = props => (
|
||||
<Text typography="h1" mb={3} textAlign="center" children={props.children}/>
|
||||
)
|
||||
|
||||
const Content = ({ message='', desc }) => {
|
||||
const $desc = desc ? <Text typography="body2">{desc}</Text> : null;
|
||||
const $errMessage = message ? <Alert mt={2} mb={4}>{ message }</Alert> : null;
|
||||
return (
|
||||
<div>
|
||||
{$errMessage} {$desc}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const NotFound = ({ message }) => (
|
||||
<CardError>
|
||||
<Header>404 Not Found</Header>
|
||||
<Content message={message}/>
|
||||
</CardError>
|
||||
)
|
||||
|
||||
export const AccessDenied = ({ message}) => (
|
||||
<CardError>
|
||||
<Header>Access denied</Header>
|
||||
<Content message={message}/>
|
||||
</CardError>
|
||||
)
|
||||
|
||||
export const Failed = ({message}) => (
|
||||
<CardError>
|
||||
<Header>Internal Error</Header>
|
||||
<Content message={message}/>
|
||||
</CardError>
|
||||
)
|
||||
|
||||
export const Offline = ({message, title}) => (
|
||||
<CardError>
|
||||
<Header>{title}</Header>
|
||||
<Content
|
||||
desc={(
|
||||
<Text typography="paragraph" textAlign="center">
|
||||
{message}
|
||||
</Text>
|
||||
)}/>
|
||||
</CardError>
|
||||
)
|
||||
|
||||
export const LoginFailed = ({ message, loginUrl }) => (
|
||||
<CardError>
|
||||
<Header>Login unsuccessful</Header>
|
||||
<Content
|
||||
message={message}
|
||||
desc={(
|
||||
<Text typography="paragraph">
|
||||
<HyperLink href={loginUrl}>Please try again</HyperLink>, if the problem persists, contact your system administrator.
|
||||
</Text>
|
||||
)}/>
|
||||
</CardError>
|
||||
)
|
||||
|
||||
const HyperLink = styled.a`
|
||||
color: ${({ theme }) => theme.colors.link};
|
||||
`
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { storiesOf } from '@storybook/react'
|
||||
import { withInfo } from '@storybook/addon-info'
|
||||
import { Offline, NotFound, AccessDenied, Failed, LoginFailed } from './CardError';
|
||||
|
||||
const message = 'some error message';
|
||||
|
||||
storiesOf('Desigin/CardError', module)
|
||||
.addDecorator(withInfo)
|
||||
.add('NotFound', () => (
|
||||
<NotFound message={message} />
|
||||
))
|
||||
.add('AccessDenied', () => (
|
||||
<AccessDenied message={message} />
|
||||
))
|
||||
.add('Failed', () => (
|
||||
<Failed message={message} />
|
||||
))
|
||||
.add('LoginFailed', () => (
|
||||
<LoginFailed message={message} loginUrl="https://localhost" />
|
||||
))
|
||||
.add('Offline', () => (
|
||||
<Offline title={"This cluster is not available from Gravity."} message={"To access this cluster, please use its local endpoint"} />
|
||||
));
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import CardError, { Failed, Offline, LoginFailed, AccessDenied, NotFound } from './CardError';
|
||||
|
||||
export default CardError;
|
||||
export {
|
||||
Failed, LoginFailed, AccessDenied, NotFound, Offline
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Card, Text } from 'design';
|
||||
import * as Icons from 'design/Icon';
|
||||
|
||||
export default function CardSuccess({ title, children }) {
|
||||
return (
|
||||
<Card width="540px" p={7} my={4} mx="auto" textAlign="center">
|
||||
<Icons.CircleCheck mb={3} fontSize={64} color="success"/>
|
||||
<Text typography="h1" mb="3">
|
||||
{title}
|
||||
</Text>
|
||||
<Text typography="paragraph">
|
||||
{children}
|
||||
</Text>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export function CardSuccessLogin() {
|
||||
return (
|
||||
<CardSuccess title="Login Successful">
|
||||
You have successfully signed into your account.
|
||||
You can close this window and continue using the product.
|
||||
</CardSuccess>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import CardSuccess, { CardSuccessLogin } from './CardSuccess';
|
||||
export default CardSuccess;
|
||||
export {
|
||||
CardSuccessLogin
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { borderRadius } from 'design/system';
|
||||
import { Table } from './../Table';
|
||||
import Pager from './Pager';
|
||||
import usePages from './usePages';
|
||||
|
||||
export default function PagedTable(props) {
|
||||
const { pageSize, data, pagerPosition, ...rest } = props;
|
||||
const pagedState = usePages({ pageSize, data });
|
||||
const tableProps = {
|
||||
...rest,
|
||||
data: pagedState.data,
|
||||
};
|
||||
|
||||
const showTopPager =
|
||||
pagedState.hasPages && (!pagerPosition || pagerPosition === 'top');
|
||||
const showBottomPager =
|
||||
pagedState.hasPages && (!pagerPosition || pagerPosition === 'bottom');
|
||||
|
||||
if (showBottomPager) {
|
||||
tableProps.borderBottomRightRadius = '0';
|
||||
tableProps.borderBottomLeftRadius = '0';
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{showTopPager && (
|
||||
<StyledPanel borderTopRightRadius="3" borderTopLeftRadius="3">
|
||||
<Pager {...pagedState} />
|
||||
</StyledPanel>
|
||||
)}
|
||||
<Table {...tableProps} />
|
||||
{showBottomPager && (
|
||||
<StyledPanel borderBottomRightRadius="3" borderBottomLeftRadius="3">
|
||||
<Pager {...pagedState} />
|
||||
</StyledPanel>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const StyledPanel = styled.nav`
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
height: 24px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background: ${props => props.theme.colors.primary.light};
|
||||
${borderRadius}
|
||||
`;
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import Icon, {
|
||||
CircleArrowLeft,
|
||||
CircleArrowRight,
|
||||
} from 'design/Icon';
|
||||
import { Text } from 'design';
|
||||
|
||||
export default function Pager(props) {
|
||||
const { startFrom, endAt, totalRows, onPrev, onNext } = props;
|
||||
const isPrevDisabled = startFrom === 0;
|
||||
const isNextDisabled = endAt === totalRows;
|
||||
return (
|
||||
<>
|
||||
<Text typography="body2" color="primary.contrastText">
|
||||
SHOWING <strong>{startFrom + 1}</strong> to <strong>{endAt}</strong> of{' '}
|
||||
<strong>{totalRows}</strong>
|
||||
</Text>
|
||||
<StyledButtons>
|
||||
<button
|
||||
onClick={onPrev}
|
||||
title="Previous Page"
|
||||
disabled={isPrevDisabled}
|
||||
>
|
||||
<CircleArrowLeft fontSize="3" />
|
||||
</button>
|
||||
<button onClick={onNext} title="Next Page" disabled={isNextDisabled}>
|
||||
<CircleArrowRight fontSize="3" />
|
||||
</button>
|
||||
</StyledButtons>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const StyledButtons = styled.div`
|
||||
button {
|
||||
background: none;
|
||||
border: none;
|
||||
border-radius: 200px;
|
||||
cursor: pointer;
|
||||
height: 24px;
|
||||
padding: 0;
|
||||
margin: 0 2px;
|
||||
min-width: 24px;
|
||||
outline: none;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
background: ${props => props.theme.colors.primary.main};
|
||||
${Icon} {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
${Icon} {
|
||||
opacity: 0.56;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import Pager, { StyledButtons } from './Pager';
|
||||
export default Pager;
|
||||
export { StyledButtons };
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import PagedTable from './Paged';
|
||||
import Pager from './Pager';
|
||||
import usePages from './usePages';
|
||||
|
||||
export default PagedTable;
|
||||
export { usePages, Pager };
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
export default function usePages({ pageSize = 7, data }){
|
||||
const [ startFrom, setFrom ] = React.useState(0);
|
||||
|
||||
// set current page to 0 when data source length changes
|
||||
React.useEffect(() => {
|
||||
setFrom(0);
|
||||
}, [data.length]);
|
||||
|
||||
function onPrev(){
|
||||
let prevPage = startFrom - pageSize;
|
||||
if(prevPage < 0){
|
||||
prevPage = 0;
|
||||
}
|
||||
setFrom(prevPage);
|
||||
}
|
||||
|
||||
function onNext(){
|
||||
let nextPage = startFrom + pageSize;
|
||||
if(nextPage < data.length){
|
||||
nextPage = startFrom + pageSize;
|
||||
setFrom(nextPage);
|
||||
}
|
||||
}
|
||||
|
||||
const totalRows = data.length;
|
||||
|
||||
let endAt = 0;
|
||||
let pagedData = data;
|
||||
|
||||
if (data.length > 0){
|
||||
endAt = startFrom + (pageSize > data.length ? data.length : pageSize);
|
||||
if(endAt > data.length){
|
||||
endAt = data.length;
|
||||
}
|
||||
|
||||
pagedData = data.slice(startFrom, endAt);
|
||||
}
|
||||
|
||||
return {
|
||||
pageSize,
|
||||
startFrom,
|
||||
endAt,
|
||||
totalRows,
|
||||
data: pagedData,
|
||||
hasPages: totalRows > pageSize,
|
||||
onNext,
|
||||
onPrev
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import styled from 'styled-components';
|
||||
import Icon from '../Icon';
|
||||
import { space, borderRadius } from 'design/system';
|
||||
|
||||
export const StyledTable = styled.table`
|
||||
background: ${props => props.theme.colors.primary.light };
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, .24);
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
border-radius: 8px;
|
||||
font-size: 12px;
|
||||
width: 100%;
|
||||
|
||||
& > thead > tr > th,
|
||||
& > tbody > tr > th,
|
||||
& > tfoot > tr > th,
|
||||
& > thead > tr > td,
|
||||
& > tbody > tr > td,
|
||||
& > tfoot > tr > td {
|
||||
padding: 16px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
& > thead > tr > th {
|
||||
background: ${props => props.theme.colors.primary.main };
|
||||
color: rgba(255, 255, 255, .56);
|
||||
cursor: pointer;
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
padding: 4px 16px;
|
||||
text-align: left;
|
||||
text-transform: uppercase;
|
||||
|
||||
${Icon} {
|
||||
font-weight: bold;
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
${space}
|
||||
${borderRadius}
|
||||
`;
|
||||
|
||||
export const StyledEmptyIndicator = styled.div`
|
||||
background: ${props => props.theme.colors.primary.main };
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
margin: 48px auto;
|
||||
max-width: 720px;
|
||||
padding: 48px 32px;
|
||||
text-align: center;
|
||||
|
||||
a {
|
||||
color: ${props => props.theme.colors.link };
|
||||
}
|
||||
`
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import Text from '../Text';
|
||||
import { StyledTable, StyledEmptyIndicator } from './StyledTable';
|
||||
import * as Icons from './../Icon/Icon';
|
||||
|
||||
/**
|
||||
* Sort indicator used by SortHeaderCell
|
||||
*/
|
||||
const SortTypes = {
|
||||
ASC: 'ASC',
|
||||
DESC: 'DESC'
|
||||
};
|
||||
|
||||
class Table extends React.Component {
|
||||
|
||||
renderHeader(children) {
|
||||
const { data } = this.props;
|
||||
const cells = children.map((item, index)=>{
|
||||
return this.renderCell(
|
||||
item.props.header,
|
||||
{
|
||||
index,
|
||||
key: index,
|
||||
isHeader: true,
|
||||
data,
|
||||
...item.props
|
||||
});
|
||||
})
|
||||
|
||||
return (
|
||||
<thead>
|
||||
<tr>{cells}</tr>
|
||||
</thead>
|
||||
)
|
||||
}
|
||||
|
||||
renderBody(children) {
|
||||
const { data } = this.props;
|
||||
const rows = [];
|
||||
for (let i = 0; i < data.length; i++){
|
||||
let cells = children.map((item, index)=>{
|
||||
return this.renderCell(
|
||||
item.props.cell,
|
||||
{
|
||||
rowIndex: i,
|
||||
key: index,
|
||||
isHeader: false,
|
||||
data,
|
||||
...item.props
|
||||
}
|
||||
);
|
||||
})
|
||||
|
||||
rows.push(<tr key={i}>{cells}</tr>);
|
||||
}
|
||||
|
||||
if(rows.length) {
|
||||
return <tbody>{rows}</tbody>;
|
||||
}
|
||||
|
||||
return (
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" colSpan={children ? children.length:0}>
|
||||
<Text typography="paragraph" m="6" color="text.primary">
|
||||
NO DATA AVAILABLE
|
||||
</Text>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
);
|
||||
}
|
||||
|
||||
renderCell(cell, cellProps){
|
||||
if (React.isValidElement(cell)) {
|
||||
return React.cloneElement(cell, cellProps);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
render() {
|
||||
/* eslint-disable no-unused-vars */
|
||||
const { data, children, ...rest } = this.props;
|
||||
/* eslint-enable no-unused-vars */
|
||||
|
||||
const columns = [];
|
||||
React.Children.forEach(children, child => {
|
||||
if (child == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!child.props._isColumn){
|
||||
throw 'Should be Column';
|
||||
}
|
||||
|
||||
columns.push(child);
|
||||
});
|
||||
|
||||
return (
|
||||
<StyledTable {...rest}>
|
||||
{this.renderHeader(columns)}
|
||||
{this.renderBody(columns)}
|
||||
</StyledTable>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const SortIndicator = ({sortDir})=>{
|
||||
if(sortDir === SortTypes.DESC){
|
||||
return <Icons.SortDesc />;
|
||||
}
|
||||
|
||||
if( sortDir === SortTypes.ASC){
|
||||
return <Icons.SortAsc />;
|
||||
}
|
||||
|
||||
return <Icons.Sort />;
|
||||
};
|
||||
|
||||
class Column extends React.Component {
|
||||
static defaultProps = {
|
||||
_isColumn: true
|
||||
};
|
||||
|
||||
render() {
|
||||
throw new Error("Component Column should never render");
|
||||
}
|
||||
}
|
||||
|
||||
const Cell = props => {
|
||||
const { isHeader, children, align, style, className } = props;
|
||||
const childProps = {
|
||||
children, align, style, className
|
||||
}
|
||||
|
||||
if(isHeader) {
|
||||
return <th {...childProps} />;
|
||||
}
|
||||
|
||||
return <td {...childProps} />;
|
||||
}
|
||||
|
||||
const TextCell = ({rowIndex, data, columnKey, ...props}) => (
|
||||
<Cell {...props}>
|
||||
{data[rowIndex][columnKey]}
|
||||
</Cell>
|
||||
);
|
||||
|
||||
class SortHeaderCell extends React.Component {
|
||||
onSortChange = e => {
|
||||
e.preventDefault();
|
||||
if (!this.props.onSortChange) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { sortDir, columnKey } = this.props;
|
||||
|
||||
// default
|
||||
let newDir = SortTypes.DESC;
|
||||
if(sortDir){
|
||||
newDir = sortDir === SortTypes.DESC ? SortTypes.ASC : SortTypes.DESC;
|
||||
}
|
||||
|
||||
this.props.onSortChange(columnKey, newDir);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { sortDir, title, ...props } = this.props;
|
||||
return (
|
||||
<Cell {...props}>
|
||||
<a onClick={this.onSortChange}>{title}</a>
|
||||
<SortIndicator sortDir={sortDir}/>
|
||||
</Cell>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class EmptyIndicator extends React.Component {
|
||||
|
||||
render() {
|
||||
const {children, title} = this.props;
|
||||
const noResults = title || "No Results Found";
|
||||
return (
|
||||
<StyledEmptyIndicator>
|
||||
<Text typography="h1" color="text.primary">{noResults}</Text>
|
||||
<Text typography="paragraph" mt="3" color="text.primary">{children}</Text>
|
||||
</StyledEmptyIndicator>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export {
|
||||
Column,
|
||||
Table,
|
||||
Cell,
|
||||
TextCell,
|
||||
SortHeaderCell,
|
||||
SortIndicator,
|
||||
SortTypes,
|
||||
EmptyIndicator
|
||||
};
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { sortBy } from 'lodash';
|
||||
import { storiesOf } from '@storybook/react'
|
||||
import match from './../utils/match';
|
||||
import {
|
||||
Table,
|
||||
TablePaged,
|
||||
Column,
|
||||
TextCell,
|
||||
SortHeaderCell,
|
||||
SortTypes,
|
||||
EmptyIndicator
|
||||
} from './../DataTable';
|
||||
|
||||
storiesOf('Desigin/DataTable', module)
|
||||
.add('DataTable', () => (
|
||||
<TableSample TableComponent={Table} data={data}/>
|
||||
))
|
||||
.add('Empty', () => (
|
||||
<TableSample TableComponent={Table} data={[]}/>
|
||||
))
|
||||
.add('Nothing found', () => (
|
||||
<TableSample TableComponent={Table} data={data} filter="no_results"/>
|
||||
))
|
||||
|
||||
storiesOf('Desigin/DataTable/Paged', module)
|
||||
.add('Page size 3', () => (
|
||||
<TableSample TableComponent={TablePaged} tableProps={ { pageSize: 3 }} data={data}/>
|
||||
))
|
||||
|
||||
class TableSample extends React.Component {
|
||||
|
||||
searchableProps = ['addr', 'hostname', 'tags'];
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
filter: props.filter || '',
|
||||
colSortDirs: {
|
||||
hostname: SortTypes.DESC
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
onSortChange = (columnKey, sortDir) => {
|
||||
this.state.colSortDirs = { [columnKey]: sortDir };
|
||||
this.setState(this.state);
|
||||
}
|
||||
|
||||
onFilterChange = value => {
|
||||
this.state.filter = value;
|
||||
this.setState(this.state);
|
||||
}
|
||||
|
||||
searchAndFilterCb(targetValue, searchValue, propName){
|
||||
if(propName === 'tags'){
|
||||
return targetValue.some((item) => {
|
||||
const { name, value } = item;
|
||||
return name.toLocaleUpperCase().indexOf(searchValue) !==-1 ||
|
||||
value.toLocaleUpperCase().indexOf(searchValue) !==-1;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
sortAndFilter(data) {
|
||||
const { colSortDirs } = this.state;
|
||||
const filtered = data
|
||||
.filter(obj => match(obj, this.state.filter, {
|
||||
searchableProps: this.searchableProps,
|
||||
cb: this.searchAndFilterCb
|
||||
}));
|
||||
|
||||
const columnKey = Object.getOwnPropertyNames(colSortDirs)[0];
|
||||
const sortDir = colSortDirs[columnKey];
|
||||
let sorted = sortBy(filtered, columnKey);
|
||||
if(sortDir === SortTypes.ASC){
|
||||
sorted = sorted.reverse();
|
||||
}
|
||||
|
||||
return sorted;
|
||||
}
|
||||
|
||||
render() {
|
||||
let { data, TableComponent, tableProps } = this.props;
|
||||
data = this.sortAndFilter(data);
|
||||
const nothingFound = data.length === 0 && this.state.filter.length > 0;
|
||||
|
||||
if (nothingFound) {
|
||||
return (
|
||||
<EmptyIndicator title='No Results Found for "X458AAZ"'>
|
||||
For tips on getting better search results, please read <a href="https://gravitational.com/teleport/docs">our documentation</a>
|
||||
</EmptyIndicator>
|
||||
)
|
||||
}
|
||||
|
||||
const props = {
|
||||
data: data,
|
||||
...tableProps
|
||||
}
|
||||
|
||||
return (
|
||||
<TableComponent {...props} >
|
||||
<Column
|
||||
columnKey="hostname"
|
||||
header={
|
||||
<SortHeaderCell
|
||||
sortDir={this.state.colSortDirs.hostname}
|
||||
onSortChange={this.onSortChange}
|
||||
title="Hostname"
|
||||
/>
|
||||
}
|
||||
cell={<TextCell /> }
|
||||
/>
|
||||
<Column
|
||||
columnKey="addr"
|
||||
header={
|
||||
<SortHeaderCell
|
||||
sortDir={this.state.colSortDirs.addr}
|
||||
onSortChange={this.onSortChange}
|
||||
title="Address"
|
||||
/>
|
||||
}
|
||||
cell={<TextCell /> }
|
||||
/>
|
||||
</TableComponent>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const data = [{
|
||||
hostname: <strong>host-a</strong>,
|
||||
addr: '192.168.7.1'
|
||||
},
|
||||
{
|
||||
hostname: <strong>host-b</strong>,
|
||||
addr: '192.168.7.2'
|
||||
},
|
||||
{
|
||||
hostname: <strong>host-c</strong>,
|
||||
addr: '192.168.7.3'
|
||||
},
|
||||
{
|
||||
hostname: <strong>host-d</strong>,
|
||||
addr: '192.168.7.4'
|
||||
},
|
||||
{
|
||||
hostname: <strong>host-3</strong>,
|
||||
addr: '192.168.7.4'
|
||||
}];
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
Column,
|
||||
Table,
|
||||
Cell,
|
||||
TextCell,
|
||||
SortHeaderCell,
|
||||
SortIndicator,
|
||||
SortTypes,
|
||||
EmptyIndicator
|
||||
} from './Table';
|
||||
|
||||
import TablePaged from './Paged';
|
||||
|
||||
export {
|
||||
Column,
|
||||
Table,
|
||||
TablePaged,
|
||||
Cell,
|
||||
TextCell,
|
||||
SortHeaderCell,
|
||||
SortIndicator,
|
||||
SortTypes,
|
||||
EmptyIndicator
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import Modal from './../Modal';
|
||||
import styled from 'styled-components';
|
||||
|
||||
class Dialog extends React.Component {
|
||||
|
||||
handleBackdropClick = event => {
|
||||
|
||||
if (event.target !== event.currentTarget) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.props.onBackdropClick) {
|
||||
this.props.onBackdropClick(event);
|
||||
}
|
||||
|
||||
if (!this.props.disableBackdropClick && this.props.onClose) {
|
||||
this.props.onClose(event, 'backdropClick');
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
children,
|
||||
disableBackdropClick,
|
||||
disableEscapeKeyDown,
|
||||
onBackdropClick,
|
||||
onClose,
|
||||
onEscapeKeyDown,
|
||||
open,
|
||||
dialogCss,
|
||||
...other
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<Modal
|
||||
disableBackdropClick={disableBackdropClick}
|
||||
disableEscapeKeyDown={disableEscapeKeyDown}
|
||||
onBackdropClick={onBackdropClick}
|
||||
onEscapeKeyDown={onEscapeKeyDown}
|
||||
onClose={onClose}
|
||||
open={open}
|
||||
role="dialog"
|
||||
{...other}
|
||||
>
|
||||
<ModalBox>
|
||||
<DialogBox dialogCss={dialogCss}>
|
||||
{children}
|
||||
</DialogBox>
|
||||
</ModalBox>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Dialog.defaultProps = {
|
||||
disableBackdropClick: false,
|
||||
disableEscapeKeyDown: false,
|
||||
fullScreen: false,
|
||||
fullWidth: false,
|
||||
};
|
||||
|
||||
const ModalBox = styled.div`
|
||||
height: 100%;
|
||||
outline: none;
|
||||
color: black;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 1;
|
||||
will-change: opacity;
|
||||
transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
|
||||
`
|
||||
|
||||
const DialogBox = styled.div`
|
||||
padding: 32px;
|
||||
padding-top: 24px;
|
||||
background: ${props => props.theme.colors.primary.main };
|
||||
color: ${props => props.theme.colors.text.primary};
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, .24);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
overflow-y: auto;
|
||||
max-height: calc(100% - 96px);
|
||||
${props => props.dialogCss && props.dialogCss(props) }
|
||||
|
||||
`
|
||||
|
||||
export default Dialog;
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { storiesOf } from '@storybook/react'
|
||||
import Dialog, { DialogHeader, DialogContent, DialogFooter, DialogTitle } from './index';
|
||||
import { ButtonPrimary, Input, LabelInput } from './..';
|
||||
|
||||
storiesOf('Desigin/Dialog', module)
|
||||
.add('Simple Dialog', () => (
|
||||
<Dialog open={true}>
|
||||
<DialogHeader>
|
||||
<DialogTitle>
|
||||
Hello
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
<DialogContent width="400px">
|
||||
<LabelInput>Name</LabelInput>
|
||||
<Input />
|
||||
</DialogContent>
|
||||
<DialogFooter>
|
||||
<ButtonPrimary onClick={ () => null} >
|
||||
Save And Close
|
||||
</ButtonPrimary>
|
||||
</DialogFooter>
|
||||
</Dialog>
|
||||
)
|
||||
);
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import styled from 'styled-components';
|
||||
import { Flex } from 'design';
|
||||
|
||||
const DialogContent = styled(Flex)`
|
||||
`
|
||||
DialogContent.defaultProps = {
|
||||
...Flex.defaultProps,
|
||||
mb: "5",
|
||||
flex: "1",
|
||||
flexDirection: "column"
|
||||
}
|
||||
|
||||
export default DialogContent;
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import styled from 'styled-components';
|
||||
import { Box } from 'design';
|
||||
|
||||
const DialogFooter = styled(Box)``
|
||||
|
||||
DialogFooter.defaultProps = {
|
||||
...Box.defaultProps,
|
||||
}
|
||||
|
||||
export default DialogFooter;
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import Flex from './../Flex';
|
||||
import styled from 'styled-components';
|
||||
import { typography } from 'design/system';
|
||||
|
||||
export default function DialogHeader(props){
|
||||
return (
|
||||
<StyledDialogHeader minHeight="32px" mb="3" alignItems="center" {...props} />
|
||||
)
|
||||
}
|
||||
|
||||
const StyledDialogHeader = styled(Flex)`
|
||||
${typography}
|
||||
`
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import Text from './../Text';
|
||||
|
||||
export default function DialogTitle(props){
|
||||
return (
|
||||
<Text typography="h2" color="text.primary" caps {...props} />
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import Dialog from './Dialog';
|
||||
import DialogTitle from './DialogTitle';
|
||||
import DialogHeader from './DialogHeader';
|
||||
import DialogContent from './DialogContent';
|
||||
import DialogFooter from './DialogFooter';
|
||||
|
||||
export default Dialog;
|
||||
export {
|
||||
DialogTitle,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
DialogHeader
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import Dialog from 'design/Dialog';
|
||||
|
||||
function DialogConfirmation(props){
|
||||
const { children, open, onClose, dialogCss } = props;
|
||||
return (
|
||||
<Dialog
|
||||
dialogCss={dialogCss}
|
||||
disableEscapeKeyDown={false}
|
||||
onClose={onClose}
|
||||
open={open}
|
||||
>
|
||||
{children}
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
export default DialogConfirmation;
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { storiesOf } from '@storybook/react'
|
||||
import DialogConfirmation, { DialogHeader, DialogContent, DialogFooter, DialogTitle } from './index';
|
||||
import { ButtonPrimary } from './../Button';
|
||||
|
||||
storiesOf('Desigin/DialogConfirmation', module)
|
||||
.add('Simple DialogConfirmation', () => (
|
||||
<DialogConfirmation open={true} >
|
||||
<DialogHeader>
|
||||
<DialogTitle>
|
||||
Hello
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
<DialogContent width="400px">
|
||||
DIALOG CONTENT AREA
|
||||
</DialogContent>
|
||||
<DialogFooter>
|
||||
<ButtonPrimary>
|
||||
Save And Close
|
||||
</ButtonPrimary>
|
||||
</DialogFooter>
|
||||
</DialogConfirmation>
|
||||
));
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import DialogConfirmation from './DialogConfirmation';
|
||||
import { DialogTitle, DialogContent, DialogFooter, DialogHeader } from './../Dialog';
|
||||
|
||||
export default DialogConfirmation;
|
||||
export {
|
||||
DialogTitle,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
DialogHeader
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
export default class DocumentTitle extends React.Component {
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (prevProps.title !== this.props.title) {
|
||||
this.setTitle(this.props.title);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.setTitle(this.props.title);
|
||||
}
|
||||
|
||||
getTitle() {
|
||||
return document.title;
|
||||
}
|
||||
|
||||
setTitle(title) {
|
||||
document.title = title;
|
||||
}
|
||||
|
||||
render() {
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
export const withDocTitle = (title, component) => {
|
||||
|
||||
return class WithWindowTitle extends React.Component{
|
||||
|
||||
static displayName = `withDocTitleWrapper`
|
||||
|
||||
componentDidMount() {
|
||||
this.setTitle(title);
|
||||
}
|
||||
|
||||
setTitle(title) {
|
||||
document.title = title;
|
||||
}
|
||||
|
||||
render() {
|
||||
return React.createElement(component, {
|
||||
...this.props,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import DocumentTitle, { withDocTitle } from './DocumentTitle';
|
||||
export default DocumentTitle;
|
||||
export {
|
||||
withDocTitle
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import styled from 'styled-components';
|
||||
import { alignItems, justifyContent, flexWrap, flexDirection, propTypes } from 'design/system';
|
||||
import theme from 'design/theme';
|
||||
import Box from '../Box';
|
||||
|
||||
const Flex = styled(Box)`
|
||||
display: flex;
|
||||
${alignItems} ${justifyContent} ${flexWrap} ${flexDirection};
|
||||
`
|
||||
|
||||
Flex.defaultProps = {
|
||||
theme
|
||||
}
|
||||
|
||||
Flex.propTypes = {
|
||||
...propTypes.Box,
|
||||
...propTypes.alignItems,
|
||||
...propTypes.justifyContent,
|
||||
...propTypes.flexWrap,
|
||||
...propTypes.flexDirection
|
||||
}
|
||||
|
||||
Flex.displayName = 'Flex'
|
||||
|
||||
export default Flex;
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { storiesOf } from '@storybook/react'
|
||||
import { withInfo } from '@storybook/addon-info'
|
||||
import Flex from './Flex';
|
||||
import Box from './../Box';
|
||||
|
||||
storiesOf('Desigin/Flex', module)
|
||||
.addDecorator(withInfo)
|
||||
.add('Basic', () => (
|
||||
<Flex align='center'>
|
||||
<Box width={1 / 2} p={3} m={4} color='white' bg='blue'>Flex</Box>
|
||||
<Box width={1 / 2} p={1} m={2} color='white' bg='green'>Box</Box>
|
||||
</Flex>
|
||||
))
|
||||
.add('Wrap', () => (
|
||||
<Flex flexWrap="wrap">
|
||||
<Box width={[1, 1 / 2]} p={3} color='white' bg='blue'>Flex</Box>
|
||||
<Box width={[1, 1 / 2]} p={1} color='white' bg='green'>Wrap</Box>
|
||||
</Flex>
|
||||
))
|
||||
.add('Justify', () => (
|
||||
<Flex justifyContent='space-around'>
|
||||
<Box width={1 / 3} p={2} color='white' bg='blue'>Flex</Box>
|
||||
<Box width={1 / 3} p={2} color='white' bg='green'>Justify</Box>
|
||||
</Flex>
|
||||
));
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import Flex from './Flex';
|
||||
export default Flex;
|
||||
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { space, fontSize, width, color } from 'styled-system';
|
||||
import './../assets/icomoon/style.css';
|
||||
|
||||
const Icon = styled.span`
|
||||
display: inline-block;
|
||||
transition: color .3s;
|
||||
${space} ${width} ${color} ${fontSize}
|
||||
`;
|
||||
|
||||
Icon.displayName = `Icon`;
|
||||
Icon.defaultProps = {
|
||||
color: 'light',
|
||||
};
|
||||
|
||||
function makeFontIcon(name, iconClassName) {
|
||||
const iconClass = `icon ${iconClassName}`;
|
||||
return function({ className = '', ...rest }) {
|
||||
const classes = `${iconClass} ${className}`;
|
||||
return <Icon className={classes} {...rest} />;
|
||||
};
|
||||
}
|
||||
|
||||
export const AddUsers = makeFontIcon('AddUsers', 'icon-users-plus');
|
||||
export const Amex = makeFontIcon('Amex', 'icon-cc-amex');
|
||||
export const Apartment = makeFontIcon('Apartment', 'icon-apartment');
|
||||
export const AppInstalled = makeFontIcon('AppInstalled', 'icon-app-installed');
|
||||
export const Apple = makeFontIcon('Apple', 'icon-apple');
|
||||
export const AppRollback = makeFontIcon('AppRollback', 'icon-app-rollback');
|
||||
export const Archive = makeFontIcon('Archive', 'icon-archive2');
|
||||
export const ArrowDown = makeFontIcon('ArrowDown', 'icon-chevron-down');
|
||||
export const ArrowLeft = makeFontIcon('ArrowLeft', 'icon-chevron-left');
|
||||
export const ArrowRight = makeFontIcon('ArrowRight', 'icon-chevron-right');
|
||||
export const ArrowsVertical = makeFontIcon(
|
||||
'ArrowsVertical',
|
||||
'icon-chevrons-expand-vertical'
|
||||
);
|
||||
export const ArrowUp = makeFontIcon('ArrowUp', 'icon-chevron-up');
|
||||
export const BitBucket = makeFontIcon('Bitbucket', 'icon-bitbucket');
|
||||
export const Bubble = makeFontIcon('Bubble', 'icon-bubble');
|
||||
export const Calendar = makeFontIcon('Calendar', 'icon-calendar-empty');
|
||||
export const Camera = makeFontIcon('Camera', 'icon-camera');
|
||||
export const CardView = makeFontIcon('CardView', 'icon-th-large');
|
||||
export const CardViewSmall = makeFontIcon('CardViewSmall', 'icon-th');
|
||||
export const CaretLeft = makeFontIcon('CaretLeft', 'icon-caret-left');
|
||||
export const CaretRight = makeFontIcon('CaretRight', 'icon-caret-right');
|
||||
export const CarrotDown = makeFontIcon('CarrotDown', 'icon-caret-down');
|
||||
export const CarrotLeft = makeFontIcon('CarrotLeft', 'icon-caret-left');
|
||||
export const CarrotRight = makeFontIcon('CarrotRight', 'icon-caret-right');
|
||||
export const CarrotSort = makeFontIcon('CarrotSort', 'icon-sort');
|
||||
export const CarrotUp = makeFontIcon('CarrotUp', 'icon-caret-up');
|
||||
export const Cash = makeFontIcon('Cash', 'icon-cash-dollar');
|
||||
export const ChevronCircleDown = makeFontIcon(
|
||||
'ChevronCircleDown',
|
||||
'icon-chevron-down-circle'
|
||||
);
|
||||
export const ChevronCircleLeft = makeFontIcon(
|
||||
'ChevronCircleLeft',
|
||||
'icon-chevron-left-circle'
|
||||
);
|
||||
export const ChevronCircleRight = makeFontIcon(
|
||||
'ChevronCircleRight',
|
||||
'icon-chevron-right-circle'
|
||||
);
|
||||
export const ChevronCircleUp = makeFontIcon(
|
||||
'ChevronCircleUp',
|
||||
'icon-chevron-up-circle'
|
||||
);
|
||||
export const CircleArrowLeft = makeFontIcon(
|
||||
'CircleArrowLeft',
|
||||
'icon-arrow-left-circle'
|
||||
);
|
||||
export const CircleArrowRight = makeFontIcon(
|
||||
'CircleArrowRight',
|
||||
'icon-arrow-right-circle'
|
||||
);
|
||||
export const CircleCheck = makeFontIcon('CircleCheck', 'icon-checkmark-circle');
|
||||
export const CircleCross = makeFontIcon('CircleCross', 'icon-cross-circle');
|
||||
export const CirclePause = makeFontIcon('CirclePause', 'icon-pause-circle');
|
||||
export const CirclePlay = makeFontIcon('CirclePlay', 'icon-play-circle');
|
||||
export const CircleStop = makeFontIcon('CircleStop', 'icon-stop-circle');
|
||||
export const Cli = makeFontIcon('Cli', 'icon-terminal');
|
||||
export const Clipboard = makeFontIcon('Clipboard', 'icon-clipboard-text');
|
||||
export const ClipboardUser = makeFontIcon(
|
||||
'ClipboardUser',
|
||||
'icon-clipboard-user'
|
||||
);
|
||||
export const Close = makeFontIcon('Close', 'icon-close');
|
||||
export const Cloud = makeFontIcon('Cloud', 'icon-cloud');
|
||||
export const Cluster = makeFontIcon('Cluster', 'icon-site-map');
|
||||
export const ClusterAdded = makeFontIcon('ClusterAdded', 'icon-cluster-added');
|
||||
export const ClusterAuth = makeFontIcon('ClusterAuth', 'icon-cluster-auth');
|
||||
export const Code = makeFontIcon('Code', 'icon-code');
|
||||
export const Cog = makeFontIcon('Cog', 'icon-cog');
|
||||
export const Config = makeFontIcon('Config', 'icon-config');
|
||||
export const Contract = makeFontIcon('Contract', 'icon-frame-contract');
|
||||
export const CreditCard = makeFontIcon('CreditCard', 'icon-credit-card1');
|
||||
export const CreditCardAlt = makeFontIcon(
|
||||
'CreditCardAlt',
|
||||
'icon-credit-card-alt'
|
||||
);
|
||||
export const CreditCardAlt2 = makeFontIcon(
|
||||
'CreditCardAlt2',
|
||||
'icon-credit-card'
|
||||
);
|
||||
export const Cross = makeFontIcon('Cross', 'icon-cross');
|
||||
export const Database = makeFontIcon('Database', 'icon-database');
|
||||
export const Discover = makeFontIcon('Discover', 'icon-cc-discover');
|
||||
export const Download = makeFontIcon('Download', 'icon-get_app');
|
||||
export const Earth = makeFontIcon('Earth', 'icon-earth');
|
||||
export const Edit = makeFontIcon('Edit', 'icon-pencil4');
|
||||
export const Ellipsis = makeFontIcon('Ellipsis', 'icon-ellipsis');
|
||||
export const EmailSolid = makeFontIcon('EmailSolid', 'icon-email-solid');
|
||||
export const Equalizer = makeFontIcon('Equalizer', 'icon-equalizer');
|
||||
export const Expand = makeFontIcon('Expand', 'icon-frame-expand');
|
||||
export const Facebook = makeFontIcon('Facebook', 'icon-facebook');
|
||||
export const FacebookSquare = makeFontIcon('FacebookSquare', 'icon-facebook2');
|
||||
export const FileCode = makeFontIcon('Youtube', 'icon-file-code');
|
||||
export const ForwarderAdded = makeFontIcon(
|
||||
'ForwarderAdded',
|
||||
'icon-add-fowarder'
|
||||
);
|
||||
export const Github = makeFontIcon('Github', 'icon-github');
|
||||
export const Google = makeFontIcon('Google', 'icon-google-plus');
|
||||
export const Graph = makeFontIcon('Graph', 'icon-graph');
|
||||
export const Home = makeFontIcon('Home', 'icon-home3');
|
||||
export const Keypair = makeFontIcon('Keypair', 'icon-keypair');
|
||||
export const Kubernetes = makeFontIcon('Kubernetes', 'icon-kubernetes');
|
||||
export const Label = makeFontIcon('Label', 'icon-label');
|
||||
export const Lan = makeFontIcon('Lan', 'icon-lan');
|
||||
export const LanAlt = makeFontIcon('LanAlt', 'icon-lan2');
|
||||
export const Layers = makeFontIcon('Layers', 'icon-layers');
|
||||
export const Layers1 = makeFontIcon('Layers1', 'icon-layers1');
|
||||
export const License = makeFontIcon('License', 'icon-license2');
|
||||
export const Link = makeFontIcon('Link', 'icon-link');
|
||||
export const Linkedin = makeFontIcon('Linkedin', 'icon-linkedin');
|
||||
export const Linux = makeFontIcon('Linux', 'icon-linux');
|
||||
export const List = makeFontIcon('List', 'icon-list');
|
||||
export const ListAddCheck = makeFontIcon(
|
||||
'ListAddCheck',
|
||||
'icon-playlist_add_check'
|
||||
);
|
||||
export const ListBullet = makeFontIcon('ListBullet', 'icon-list4');
|
||||
export const ListCheck = makeFontIcon('ListCheck', 'icon-list3');
|
||||
export const ListView = makeFontIcon('ListView', 'icon-th-list');
|
||||
export const LocalPlay = makeFontIcon('LocalPlay', 'icon-local_play');
|
||||
export const Lock = makeFontIcon('Lock', 'icon-lock');
|
||||
export const Magnifier = makeFontIcon('Magnifier', 'icon-magnifier');
|
||||
export const MapMarker = makeFontIcon('MapMarker', 'icon-map-marker');
|
||||
export const MasterCard = makeFontIcon('MasterCard', 'icon-cc-mastercard');
|
||||
export const Memory = makeFontIcon('Memory', 'icon-memory');
|
||||
export const MoreHoriz = makeFontIcon('MoreHoriz', 'icon-more_horiz');
|
||||
export const MoreVert = makeFontIcon('MoreVert', 'icon-more_vert');
|
||||
export const Mute = makeFontIcon('Mute', 'icon-mute');
|
||||
export const NoteAdded = makeFontIcon('NoteAdded', 'icon-note_add');
|
||||
export const NotificationsActive = makeFontIcon(
|
||||
'NotificationsActive',
|
||||
'icon-notifications_active'
|
||||
);
|
||||
export const OpenID = makeFontIcon('OpenID', 'icon-openid');
|
||||
export const Paypal = makeFontIcon('Paypal', 'icon-cc-paypal');
|
||||
export const Pencil = makeFontIcon('Pencil', 'icon-pencil');
|
||||
export const Person = makeFontIcon('Person', 'icon-person');
|
||||
export const PersonAdd = makeFontIcon('PersonAdd', 'icon-person_add');
|
||||
export const Phone = makeFontIcon('Phone', 'icon-telephone');
|
||||
export const PhonelinkErase = makeFontIcon(
|
||||
'PhonelinkErase',
|
||||
'icon-phonelink_erase'
|
||||
);
|
||||
export const PhonelinkSetup = makeFontIcon(
|
||||
'PhonelinkSetup',
|
||||
'icon-phonelink_setup'
|
||||
);
|
||||
export const Planet = makeFontIcon('Planet', 'icon-planet');
|
||||
export const Play = makeFontIcon('Play', 'icon-play');
|
||||
export const Power = makeFontIcon('Power', 'icon-power');
|
||||
export const Profile = makeFontIcon('Profile', 'icon-profile');
|
||||
export const Restore = makeFontIcon('Restore', 'icon-restore');
|
||||
export const Server = makeFontIcon('Server', 'icon-server');
|
||||
export const SettingsInputComposite = makeFontIcon(
|
||||
'SettingsInputComposite',
|
||||
'icon-settings_input_composite'
|
||||
);
|
||||
export const SettingsOverscan = makeFontIcon(
|
||||
'SettingsOverscan',
|
||||
'icon-settings_overscan'
|
||||
);
|
||||
export const Shart = makeFontIcon('Shart', 'icon-chart-bars');
|
||||
export const ShieldCheck = makeFontIcon('ShieldCheck', 'icon-shield-check');
|
||||
export const Shrink = makeFontIcon('Shrink', 'icon-shrink');
|
||||
export const Signal = makeFontIcon('Signal', 'icon-signal');
|
||||
export const SmallArrowDown = makeFontIcon(
|
||||
'SmallArrowDown',
|
||||
'icon-arrow_drop_down'
|
||||
);
|
||||
export const SmallArrowUp = makeFontIcon(
|
||||
'SmallArrowDown',
|
||||
'icon-arrow_drop_up'
|
||||
);
|
||||
export const SmartPhone = makeFontIcon('SmartPhone', 'icon-smartphone-embed');
|
||||
export const Sort = makeFontIcon('Sort', 'icon-chevrons-expand-vertical');
|
||||
export const SortAsc = makeFontIcon('SortAsc', 'icon-chevron-up');
|
||||
export const SortDesc = makeFontIcon('SortDesc', 'icon-chevron-down');
|
||||
export const Speed = makeFontIcon('Speed', 'icon-speed-fast');
|
||||
export const Spinner = makeFontIcon('Spinner', 'icon-spinner8');
|
||||
export const Stars = makeFontIcon('Stars', 'icon-stars');
|
||||
export const Stripe = makeFontIcon('Stripe', 'icon-cc-stripe');
|
||||
export const Tablet = makeFontIcon('Tablet', 'icon-tablet2');
|
||||
export const Trash = makeFontIcon('Trash', 'icon-trash2');
|
||||
export const Twitter = makeFontIcon('Twitter', 'icon-twitter');
|
||||
export const Unarchive = makeFontIcon('Unarchive', 'icon-unarchive');
|
||||
export const Unlock = makeFontIcon('Unlock', 'icon-unlock');
|
||||
export const Upload = makeFontIcon('Upload', 'icon-file_upload');
|
||||
export const User = makeFontIcon('User', 'icon-user');
|
||||
export const UserCreated = makeFontIcon('UserCreated', 'icon-user-created');
|
||||
export const Users = makeFontIcon('Users', 'icon-users2');
|
||||
export const VideoGame = makeFontIcon('VideoGame', 'icon-videogame_asset');
|
||||
export const Visa = makeFontIcon('Visa', 'icon-cc-visa');
|
||||
export const VolumeUp = makeFontIcon('VolumeUp', 'icon-volume-high');
|
||||
export const VpnKey = makeFontIcon('VpnKey', 'icon-vpn_key');
|
||||
export const Warning = makeFontIcon('Warning', 'icon-warning');
|
||||
export const Wifi = makeFontIcon('Wifi', 'icon-wifi');
|
||||
export const Window = makeFontIcon('Window', 'icon-window');
|
||||
export const Windows = makeFontIcon('Windows', 'icon-windows');
|
||||
export const Youtube = makeFontIcon('Youtube', 'icon-youtube');
|
||||
|
||||
export default Icon;
|
||||
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import styled from 'styled-components'
|
||||
import * as Icon from '../Icon';
|
||||
|
||||
storiesOf('Desigin/Icon', module)
|
||||
.add('Icon components', () => (
|
||||
<Container>
|
||||
<IconBox IconCmpt={Icon.AddUsers} text="AddUsers"/>
|
||||
<IconBox IconCmpt={Icon.Amex} text="Amex"/>
|
||||
<IconBox IconCmpt={Icon.Apartment} text="Apartment"/>
|
||||
<IconBox IconCmpt={Icon.AppInstalled} text="AppInstalled"/>
|
||||
<IconBox IconCmpt={Icon.Apple} text="Apple"/>
|
||||
<IconBox IconCmpt={Icon.AppRollback} text="AppRollback"/>
|
||||
<IconBox IconCmpt={Icon.Archive} text="Archive"/>
|
||||
<IconBox IconCmpt={Icon.ArrowDown} text="ArrowDown"/>
|
||||
<IconBox IconCmpt={Icon.ArrowLeft} text="ArrowLeft"/>
|
||||
<IconBox IconCmpt={Icon.ArrowRight} text="ArrowRight"/>
|
||||
<IconBox IconCmpt={Icon.ArrowsVertical} text="ArrowsVertical"/>
|
||||
<IconBox IconCmpt={Icon.ArrowUp} text="ArrowUp"/>
|
||||
<IconBox IconCmpt={Icon.Bubble} text="Bubble"/>
|
||||
<IconBox IconCmpt={Icon.Calendar} text="Calendar"/>
|
||||
<IconBox IconCmpt={Icon.Camera} text="Camera"/>
|
||||
<IconBox IconCmpt={Icon.CardView} text="CardView"/>
|
||||
<IconBox IconCmpt={Icon.CardViewSmall} text="CardViewSmall"/>
|
||||
<IconBox IconCmpt={Icon.CaretLeft} text="CaretLeft"/>
|
||||
<IconBox IconCmpt={Icon.CaretRight} text="CaretRight"/>
|
||||
<IconBox IconCmpt={Icon.CarrotDown} text="CarrotDown"/>
|
||||
<IconBox IconCmpt={Icon.CarrotLeft} text="CarrotLeft"/>
|
||||
<IconBox IconCmpt={Icon.CarrotRight} text="CarrotRight"/>
|
||||
<IconBox IconCmpt={Icon.CarrotSort} text="CarrotSort"/>
|
||||
<IconBox IconCmpt={Icon.CarrotUp} text="CarrotUp"/>
|
||||
<IconBox IconCmpt={Icon.Cash} text="Cash"/>
|
||||
<IconBox IconCmpt={Icon.ChevronCircleDown} text="ChevronCircleDown"/>
|
||||
<IconBox IconCmpt={Icon.ChevronCircleLeft} text="ChevronCircleLeft"/>
|
||||
<IconBox IconCmpt={Icon.ChevronCircleRight} text="ChevronCircleRight"/>
|
||||
<IconBox IconCmpt={Icon.ChevronCircleUp} text="ChevronCircleUp"/>
|
||||
<IconBox IconCmpt={Icon.CircleArrowLeft} text="CircleArrowLeft"/>
|
||||
<IconBox IconCmpt={Icon.CircleArrowRight} text="CircleArrowRight"/>
|
||||
<IconBox IconCmpt={Icon.CircleCheck} text="CircleCheck"/>
|
||||
<IconBox IconCmpt={Icon.CircleCross} text="CircleCross"/>
|
||||
<IconBox IconCmpt={Icon.CirclePause} text="CirclePause"/>
|
||||
<IconBox IconCmpt={Icon.CirclePlay} text="CirclePlay"/>
|
||||
<IconBox IconCmpt={Icon.CircleStop} text="CircleStop"/>
|
||||
<IconBox IconCmpt={Icon.Cli} text="Cli"/>
|
||||
<IconBox IconCmpt={Icon.Clipboard} text="Clipboard"/>
|
||||
<IconBox IconCmpt={Icon.ClipboardUser} text="ClipboardUser"/>
|
||||
<IconBox IconCmpt={Icon.Close} text="Close"/>
|
||||
<IconBox IconCmpt={Icon.Cloud} text="Cloud"/>
|
||||
<IconBox IconCmpt={Icon.Cluster} text="Cluster"/>
|
||||
<IconBox IconCmpt={Icon.ClusterAdded} text="ClusterAdded"/>
|
||||
<IconBox IconCmpt={Icon.ClusterAuth} text="ClusterAuth"/>
|
||||
<IconBox IconCmpt={Icon.Code} text="Code"/>
|
||||
<IconBox IconCmpt={Icon.Cog} text="Cog"/>
|
||||
<IconBox IconCmpt={Icon.Config} text="Config"/>
|
||||
<IconBox IconCmpt={Icon.Contract} text="Contract"/>
|
||||
<IconBox IconCmpt={Icon.CreditCard} text="CreditCard"/>
|
||||
<IconBox IconCmpt={Icon.CreditCardAlt} text="CreditCardAlt"/>
|
||||
<IconBox IconCmpt={Icon.CreditCardAlt2} text="CreditCardAlt2"/>
|
||||
<IconBox IconCmpt={Icon.Cross} text="Cross"/>
|
||||
<IconBox IconCmpt={Icon.Database} text="Database"/>
|
||||
<IconBox IconCmpt={Icon.Discover} text="Discover"/>
|
||||
<IconBox IconCmpt={Icon.Download} text="Download"/>
|
||||
<IconBox IconCmpt={Icon.Earth} text="Earth"/>
|
||||
<IconBox IconCmpt={Icon.Edit} text="Edit"/>
|
||||
<IconBox IconCmpt={Icon.Ellipsis} text="Ellipsis"/>
|
||||
<IconBox IconCmpt={Icon.EmailSolid} text="EmailSolid"/>
|
||||
<IconBox IconCmpt={Icon.Equalizer} text="Equalizer"/>
|
||||
<IconBox IconCmpt={Icon.Expand} text="Expand"/>
|
||||
<IconBox IconCmpt={Icon.Facebook} text="Facebook"/>
|
||||
<IconBox IconCmpt={Icon.FacebookSquare} text="FacebookSquare"/>
|
||||
<IconBox IconCmpt={Icon.ForwarderAdded} text="ForwarderAdded"/>
|
||||
<IconBox IconCmpt={Icon.Github} text="Github"/>
|
||||
<IconBox IconCmpt={Icon.Google} text="Google"/>
|
||||
<IconBox IconCmpt={Icon.Graph} text="Graph"/>
|
||||
<IconBox IconCmpt={Icon.Home} text="Home"/>
|
||||
<IconBox IconCmpt={Icon.Keypair} text="Keypair"/>
|
||||
<IconBox IconCmpt={Icon.Label} text="Label"/>
|
||||
<IconBox IconCmpt={Icon.Lan} text="Lan"/>
|
||||
<IconBox IconCmpt={Icon.LanAlt} text="LanAlt"/>
|
||||
<IconBox IconCmpt={Icon.Layers} text="Layers"/>
|
||||
<IconBox IconCmpt={Icon.Layers1} text="Layers1"/>
|
||||
<IconBox IconCmpt={Icon.License} text="License"/>
|
||||
<IconBox IconCmpt={Icon.Link} text="Link"/>
|
||||
<IconBox IconCmpt={Icon.Linkedin} text="Linkedin"/>
|
||||
<IconBox IconCmpt={Icon.Linux} text="Linux"/>
|
||||
<IconBox IconCmpt={Icon.List} text="List"/>
|
||||
<IconBox IconCmpt={Icon.ListAddCheck} text="ListAddCheck"/>
|
||||
<IconBox IconCmpt={Icon.ListBullet} text="ListBullet"/>
|
||||
<IconBox IconCmpt={Icon.ListCheck} text="ListCheck"/>
|
||||
<IconBox IconCmpt={Icon.ListView} text="ListView"/>
|
||||
<IconBox IconCmpt={Icon.LocalPlay} text="LocalPlay"/>
|
||||
<IconBox IconCmpt={Icon.Lock} text="Lock"/>
|
||||
<IconBox IconCmpt={Icon.Magnifier} text="Magnifier"/>
|
||||
<IconBox IconCmpt={Icon.MapMarker} text="MapMarker"/>
|
||||
<IconBox IconCmpt={Icon.MasterCard} text="MasterCard"/>
|
||||
<IconBox IconCmpt={Icon.Memory} text="Memory" />
|
||||
<IconBox IconCmpt={Icon.MoreHoriz} text="MoreHoriz"/>
|
||||
<IconBox IconCmpt={Icon.MoreVert} text="MoreVert"/>
|
||||
<IconBox IconCmpt={Icon.Mute} text="Mute"/>
|
||||
<IconBox IconCmpt={Icon.NoteAdded} text="NoteAdded"/>
|
||||
<IconBox IconCmpt={Icon.NotificationsActive} text="NotificationsActive"/>
|
||||
<IconBox IconCmpt={Icon.Paypal} text="Paypal"/>
|
||||
<IconBox IconCmpt={Icon.Pencil} text="Pencil"/>
|
||||
<IconBox IconCmpt={Icon.Person} text="Person"/>
|
||||
<IconBox IconCmpt={Icon.PersonAdd} text="PersonAdd"/>
|
||||
<IconBox IconCmpt={Icon.Phone} text="Phone"/>
|
||||
<IconBox IconCmpt={Icon.PhonelinkErase} text="PhonelinkErase"/>
|
||||
<IconBox IconCmpt={Icon.PhonelinkSetup} text="PhonelinkSetup"/>
|
||||
<IconBox IconCmpt={Icon.Planet} text="Planet"/>
|
||||
<IconBox IconCmpt={Icon.Play} text="Play"/>
|
||||
<IconBox IconCmpt={Icon.Power} text="Power"/>
|
||||
<IconBox IconCmpt={Icon.Profile} text="Profile"/>
|
||||
<IconBox IconCmpt={Icon.Restore} text="Restore"/>
|
||||
<IconBox IconCmpt={Icon.Server} text="Server"/>
|
||||
<IconBox IconCmpt={Icon.SettingsInputComposite} text="SettingsInputComposite"/>
|
||||
<IconBox IconCmpt={Icon.SettingsOverscan} text="SettingsOverscan"/>
|
||||
<IconBox IconCmpt={Icon.Shart} text="Shart"/>
|
||||
<IconBox IconCmpt={Icon.ShieldCheck} text="ShieldCheck"/>
|
||||
<IconBox IconCmpt={Icon.Shrink} text="Shrink"/>
|
||||
<IconBox IconCmpt={Icon.Signal} text="Signal"/>
|
||||
<IconBox IconCmpt={Icon.SmallArrowDown} text="SmallArrowDown"/>
|
||||
<IconBox IconCmpt={Icon.SmallArrowUp} text="SmallArrowUp"/>
|
||||
<IconBox IconCmpt={Icon.SmartPhone} text="SmartPhone"/>
|
||||
<IconBox IconCmpt={Icon.Sort} text="Sort"/>
|
||||
<IconBox IconCmpt={Icon.SortAsc} text="SortAsc"/>
|
||||
<IconBox IconCmpt={Icon.SortDesc} text="SortDesc"/>
|
||||
<IconBox IconCmpt={Icon.Speed} text="Speed"/>
|
||||
<IconBox IconCmpt={Icon.Spinner} text="Spinner"/>
|
||||
<IconBox IconCmpt={Icon.Stars} text="Stars"/>
|
||||
<IconBox IconCmpt={Icon.Stripe} text="Stripe"/>
|
||||
<IconBox IconCmpt={Icon.Tablet} text="Tablet"/>
|
||||
<IconBox IconCmpt={Icon.Trash} text="Trash"/>
|
||||
<IconBox IconCmpt={Icon.Twitter} text="Twitter"/>
|
||||
<IconBox IconCmpt={Icon.Unarchive} text="Unarchive" />
|
||||
<IconBox IconCmpt={Icon.Unlock} text="Unlock"/>
|
||||
<IconBox IconCmpt={Icon.Upload} text="Upload"/>
|
||||
<IconBox IconCmpt={Icon.User} text="User"/>
|
||||
<IconBox IconCmpt={Icon.UserCreated} text="UserCreated"/>
|
||||
<IconBox IconCmpt={Icon.Users} text="Users"/>
|
||||
<IconBox IconCmpt={Icon.VideoGame} text="VideoGame"/>
|
||||
<IconBox IconCmpt={Icon.Visa} text="Visa"/>
|
||||
<IconBox IconCmpt={Icon.VolumeUp} text="VolumeUp"/>
|
||||
<IconBox IconCmpt={Icon.VpnKey} text="VpnKey"/>
|
||||
<IconBox IconCmpt={Icon.Warning} text="Warning"/>
|
||||
<IconBox IconCmpt={Icon.Wifi} text="Wifi"/>
|
||||
<IconBox IconCmpt={Icon.Window} text="Window"/>
|
||||
<IconBox IconCmpt={Icon.Windows} text="Windows"/>
|
||||
<IconBox IconCmpt={Icon.Youtube} text="Youtube"/>
|
||||
<IconBox IconCmpt={Icon.Kubernetes} text="Kubernetes"/>
|
||||
|
||||
</Container>
|
||||
));
|
||||
|
||||
const Container = styled.div`
|
||||
font-size: 24px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
`
|
||||
|
||||
const IconBox = ({IconCmpt, text}) => (
|
||||
<Box>
|
||||
<IconCmpt/>
|
||||
{text}
|
||||
</Box>
|
||||
)
|
||||
|
||||
|
||||
const Box = styled.div`
|
||||
display: flex;
|
||||
margin: 10px 10px;
|
||||
width: 300px;
|
||||
font-size: 14px;
|
||||
|
||||
.icon {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
font-size: 16px;
|
||||
}
|
||||
`
|
||||
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import Icon, {
|
||||
AddUsers,
|
||||
Amex,
|
||||
Apartment,
|
||||
AppInstalled,
|
||||
Apple,
|
||||
AppRollback,
|
||||
Archive,
|
||||
ArrowDown,
|
||||
ArrowLeft,
|
||||
ArrowRight,
|
||||
ArrowsVertical,
|
||||
ArrowUp,
|
||||
BitBucket,
|
||||
Bubble,
|
||||
Calendar,
|
||||
Camera,
|
||||
CardView,
|
||||
CardViewSmall,
|
||||
CaretLeft,
|
||||
CaretRight,
|
||||
CarrotDown,
|
||||
CarrotLeft,
|
||||
CarrotRight,
|
||||
CarrotSort,
|
||||
CarrotUp,
|
||||
Cash,
|
||||
ChevronCircleDown,
|
||||
ChevronCircleLeft,
|
||||
ChevronCircleRight,
|
||||
ChevronCircleUp,
|
||||
CircleArrowLeft,
|
||||
CircleArrowRight,
|
||||
CircleCheck,
|
||||
CircleCross,
|
||||
CirclePause,
|
||||
CirclePlay,
|
||||
CircleStop,
|
||||
Cli,
|
||||
Clipboard,
|
||||
ClipboardUser,
|
||||
Close,
|
||||
Cloud,
|
||||
Cluster,
|
||||
ClusterAdded,
|
||||
ClusterAuth,
|
||||
Code,
|
||||
Cog,
|
||||
Config,
|
||||
Contract,
|
||||
CreditCard,
|
||||
CreditCardAlt,
|
||||
CreditCardAlt2,
|
||||
Cross,
|
||||
Database,
|
||||
Discover,
|
||||
Download,
|
||||
Earth,
|
||||
Edit,
|
||||
Ellipsis,
|
||||
EmailSolid,
|
||||
Equalizer,
|
||||
Expand,
|
||||
Facebook,
|
||||
FacebookSquare,
|
||||
FileCode,
|
||||
ForwarderAdded,
|
||||
Github,
|
||||
Google,
|
||||
Graph,
|
||||
Home,
|
||||
Keypair,
|
||||
Kubernetes,
|
||||
Label,
|
||||
Lan,
|
||||
LanAlt,
|
||||
Layers,
|
||||
Layers1,
|
||||
License,
|
||||
Link,
|
||||
Linkedin,
|
||||
Linux,
|
||||
List,
|
||||
ListAddCheck,
|
||||
ListBullet,
|
||||
ListCheck,
|
||||
ListView,
|
||||
LocalPlay,
|
||||
Lock,
|
||||
Magnifier,
|
||||
MapMarker,
|
||||
MasterCard,
|
||||
Memory,
|
||||
MoreHoriz,
|
||||
MoreVert,
|
||||
Mute,
|
||||
NoteAdded,
|
||||
NotificationsActive,
|
||||
OpenID,
|
||||
Paypal,
|
||||
Pencil,
|
||||
Person,
|
||||
PersonAdd,
|
||||
Phone,
|
||||
PhonelinkErase,
|
||||
PhonelinkSetup,
|
||||
Planet,
|
||||
Play,
|
||||
Power,
|
||||
Profile,
|
||||
Restore,
|
||||
Server,
|
||||
SettingsInputComposite,
|
||||
SettingsOverscan,
|
||||
Shart,
|
||||
ShieldCheck,
|
||||
Shrink,
|
||||
Signal,
|
||||
SmallArrowDown,
|
||||
SmallArrowUp,
|
||||
SmartPhone,
|
||||
Sort,
|
||||
SortAsc,
|
||||
SortDesc,
|
||||
Speed,
|
||||
Spinner,
|
||||
Stars,
|
||||
Stripe,
|
||||
Tablet,
|
||||
Trash,
|
||||
Twitter,
|
||||
Unarchive,
|
||||
Unlock,
|
||||
Upload,
|
||||
User,
|
||||
UserCreated,
|
||||
Users,
|
||||
VideoGame,
|
||||
Visa,
|
||||
VolumeUp,
|
||||
VpnKey,
|
||||
Warning,
|
||||
Wifi,
|
||||
Window,
|
||||
Windows,
|
||||
Youtube,
|
||||
} from './Icon';
|
||||
|
||||
export default Icon;
|
||||
export {
|
||||
AddUsers,
|
||||
Amex,
|
||||
Apartment,
|
||||
AppInstalled,
|
||||
Apple,
|
||||
AppRollback,
|
||||
Archive,
|
||||
ArrowDown,
|
||||
ArrowLeft,
|
||||
ArrowRight,
|
||||
ArrowsVertical,
|
||||
ArrowUp,
|
||||
BitBucket,
|
||||
Bubble,
|
||||
Calendar,
|
||||
Camera,
|
||||
CardView,
|
||||
CardViewSmall,
|
||||
CaretLeft,
|
||||
CaretRight,
|
||||
CarrotDown,
|
||||
CarrotLeft,
|
||||
CarrotRight,
|
||||
CarrotSort,
|
||||
CarrotUp,
|
||||
Cash,
|
||||
ChevronCircleDown,
|
||||
ChevronCircleLeft,
|
||||
ChevronCircleRight,
|
||||
ChevronCircleUp,
|
||||
CircleArrowLeft,
|
||||
CircleArrowRight,
|
||||
CircleCheck,
|
||||
CircleCross,
|
||||
CirclePause,
|
||||
CirclePlay,
|
||||
CircleStop,
|
||||
Cli,
|
||||
Clipboard,
|
||||
ClipboardUser,
|
||||
Close,
|
||||
Cloud,
|
||||
Cluster,
|
||||
ClusterAdded,
|
||||
ClusterAuth,
|
||||
Code,
|
||||
Cog,
|
||||
Config,
|
||||
Contract,
|
||||
CreditCard,
|
||||
CreditCardAlt,
|
||||
CreditCardAlt2,
|
||||
Cross,
|
||||
Database,
|
||||
Discover,
|
||||
Download,
|
||||
Earth,
|
||||
Edit,
|
||||
Ellipsis,
|
||||
EmailSolid,
|
||||
Equalizer,
|
||||
Expand,
|
||||
Facebook,
|
||||
FacebookSquare,
|
||||
FileCode,
|
||||
ForwarderAdded,
|
||||
Github,
|
||||
Google,
|
||||
Graph,
|
||||
Home,
|
||||
Keypair,
|
||||
Kubernetes,
|
||||
Label,
|
||||
Lan,
|
||||
LanAlt,
|
||||
Layers,
|
||||
Layers1,
|
||||
License,
|
||||
Link,
|
||||
Linkedin,
|
||||
Linux,
|
||||
List,
|
||||
ListAddCheck,
|
||||
ListBullet,
|
||||
ListCheck,
|
||||
ListView,
|
||||
LocalPlay,
|
||||
Lock,
|
||||
Magnifier,
|
||||
MapMarker,
|
||||
MasterCard,
|
||||
Memory,
|
||||
MoreHoriz,
|
||||
MoreVert,
|
||||
Mute,
|
||||
NoteAdded,
|
||||
NotificationsActive,
|
||||
OpenID,
|
||||
Paypal,
|
||||
Pencil,
|
||||
Person,
|
||||
PersonAdd,
|
||||
Phone,
|
||||
PhonelinkErase,
|
||||
PhonelinkSetup,
|
||||
Planet,
|
||||
Play,
|
||||
Power,
|
||||
Profile,
|
||||
Restore,
|
||||
Server,
|
||||
SettingsInputComposite,
|
||||
SettingsOverscan,
|
||||
Shart,
|
||||
ShieldCheck,
|
||||
Shrink,
|
||||
Signal,
|
||||
SmallArrowDown,
|
||||
SmallArrowUp,
|
||||
SmartPhone,
|
||||
Sort,
|
||||
SortAsc,
|
||||
SortDesc,
|
||||
Speed,
|
||||
Spinner,
|
||||
Stars,
|
||||
Stripe,
|
||||
Tablet,
|
||||
Trash,
|
||||
Twitter,
|
||||
Unarchive,
|
||||
Unlock,
|
||||
Upload,
|
||||
User,
|
||||
UserCreated,
|
||||
Users,
|
||||
VideoGame,
|
||||
Visa,
|
||||
VolumeUp,
|
||||
VpnKey,
|
||||
Warning,
|
||||
Wifi,
|
||||
Window,
|
||||
Windows,
|
||||
Youtube,
|
||||
};
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import PropTypes from 'prop-types';
|
||||
import { space, color, width, height, maxWidth, maxHeight } from 'design/system';
|
||||
|
||||
const Image = props => {
|
||||
return (
|
||||
<StyledImg {...props} />
|
||||
);
|
||||
};
|
||||
|
||||
Image.propTypes = {
|
||||
/** Image Src */
|
||||
src: PropTypes.string,
|
||||
};
|
||||
|
||||
Image.displayName = 'Logo';
|
||||
|
||||
export default Image;
|
||||
|
||||
const StyledImg = styled.img`
|
||||
display: block;
|
||||
outline: none;
|
||||
${color} ${space} ${width} ${height} ${maxWidth} ${maxHeight}
|
||||
`;
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import Image from '../Image';
|
||||
import teleportSvg from './../assets/images/gravity-medallion.svg';
|
||||
|
||||
storiesOf('Desigin/Image', module).add('Component', () => <Image src={teleportSvg} />);
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import Image from './Image';
|
||||
export default Image;
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import styled from 'styled-components'
|
||||
import { Spinner as SpinnerIcon} from './../Icon';
|
||||
|
||||
const DEFAULT_DELAY = "short";
|
||||
|
||||
const DelayValueMap = {
|
||||
"none": 0,
|
||||
"short": 400, // 0.4s;
|
||||
"long": 600, // 0.6s;
|
||||
}
|
||||
|
||||
class Indicator extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this._timer = null;
|
||||
this._delay = props.delay || DEFAULT_DELAY;
|
||||
this.state = {
|
||||
canDisplay: false
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
let timeoutValue = DelayValueMap[this._delay];
|
||||
this._timer = setTimeout(() => {
|
||||
this.setState({
|
||||
canDisplay: true
|
||||
})
|
||||
}, timeoutValue);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearTimeout(this._timer);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.state.canDisplay) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledSpinner {...this.props}/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const StyledSpinner = styled(SpinnerIcon)`
|
||||
${({fontSize="32px"}) => `
|
||||
font-size: ${fontSize};
|
||||
height: ${fontSize};
|
||||
width: ${fontSize};
|
||||
`}
|
||||
|
||||
animation: anim-rotate 2s infinite linear;
|
||||
color: #fff;
|
||||
display: inline-block;
|
||||
margin: 16px;
|
||||
opacity: .87;
|
||||
text-shadow: 0 0 .25em rgba(255,255,255, .3);
|
||||
|
||||
@keyframes anim-rotate {
|
||||
0% {
|
||||
transform: rotate(0);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default Indicator;
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { storiesOf } from '@storybook/react'
|
||||
import { withInfo } from '@storybook/addon-info'
|
||||
import Indicator from '../Indicator'
|
||||
|
||||
storiesOf('Desigin/Indicator', module)
|
||||
.addDecorator(withInfo)
|
||||
.add('Loading Indicator', () => <Indicator />)
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import Indicator from './Indicator';
|
||||
export default Indicator;
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import styled from 'styled-components'
|
||||
import PropTypes from 'prop-types'
|
||||
import { space, width, color, height } from 'styled-system'
|
||||
|
||||
function error({ hasError, theme }){
|
||||
if(!hasError){
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
border: `2px solid ${theme.colors.error.main}`,
|
||||
padding: '10px 14px'
|
||||
}
|
||||
}
|
||||
|
||||
const Input = styled.input`
|
||||
appearance: none;
|
||||
border-radius: 4px;
|
||||
box-shadow: inset 0 2px 4px rgba(0, 0, 0, .24);
|
||||
box-sizing: border-box;
|
||||
border: none;
|
||||
display: block;
|
||||
height: 40px;
|
||||
font-size: 16px;
|
||||
padding: 12px 16px;
|
||||
outline: none;
|
||||
width: 100%;
|
||||
|
||||
::-ms-clear {
|
||||
display: none;
|
||||
}
|
||||
|
||||
::placeholder {
|
||||
opacity: 0.24;
|
||||
}
|
||||
|
||||
${color} ${space} ${width} ${height} ${error};
|
||||
`
|
||||
|
||||
Input.displayName = 'Input'
|
||||
|
||||
Input.propTypes = {
|
||||
placeholder: PropTypes.string,
|
||||
hasError: PropTypes.bool,
|
||||
}
|
||||
|
||||
Input.defaultProps = {
|
||||
bg: 'light',
|
||||
color: 'text.onLight',
|
||||
}
|
||||
|
||||
export default Input;
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import { withInfo } from '@storybook/addon-info';
|
||||
import Input from '../Input';
|
||||
|
||||
storiesOf('Desigin/Input', module)
|
||||
.addDecorator(withInfo)
|
||||
.add('empty', () => {
|
||||
return <Input placeholder="Enter Some Text" />;
|
||||
})
|
||||
.add('error', () => {
|
||||
return <Input hasError="blah" defaultValue="This field has an error" />;
|
||||
})
|
||||
.add('focused', () => {
|
||||
return <Input autoFocus defaultValue="This field has an focus" />;
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import Input from './Input';
|
||||
export default Input;
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { space } from 'design/system';
|
||||
|
||||
const kind = ({kind, theme}) => {
|
||||
if (kind === "secondary") {
|
||||
return {
|
||||
backgroundColor: theme.colors.primary.dark,
|
||||
color: theme.colors.text.primary
|
||||
}
|
||||
}
|
||||
|
||||
if (kind === "warning") {
|
||||
return {
|
||||
backgroundColor: theme.colors.warning,
|
||||
color: theme.colors.primary.contrastText
|
||||
}
|
||||
}
|
||||
|
||||
if (kind === "danger") {
|
||||
return {
|
||||
backgroundColor: theme.colors.danger,
|
||||
color: theme.colors.primary.contrastText
|
||||
}
|
||||
}
|
||||
|
||||
// default is primary
|
||||
return {
|
||||
backgroundColor: theme.colors.secondary.main,
|
||||
color: theme.colors.text.secondary.contrastText
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const Label = styled.div`
|
||||
box-sizing: border-box;
|
||||
border-radius: 100px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 10px;
|
||||
font-weight: 500;
|
||||
min-height: 24px;
|
||||
padding: 2px 12px;
|
||||
text-transform: uppercase;
|
||||
line-height: 1.43;
|
||||
${kind}
|
||||
${space}
|
||||
`;
|
||||
|
||||
export default Label;
|
||||
export const Primary = props => <Label kind="secondary" {...props} />
|
||||
export const Secondary = props => <Label kind="primary" {...props} />
|
||||
export const Warning = props => <Label kind="warning" {...props} />
|
||||
export const Danger = props => <Label kind="danger" {...props} />
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { storiesOf } from '@storybook/react'
|
||||
import { withInfo } from '@storybook/addon-info'
|
||||
import Label from './Label';
|
||||
import Flex from './../Flex';
|
||||
|
||||
storiesOf('Desigin/Label', module)
|
||||
.addDecorator(withInfo)
|
||||
.add('kinds', () => (
|
||||
<Flex height="100px" bg="primary.main" justifyContent="center" alignItems="center">
|
||||
<Label mr="3" kind="primary">Primary</Label>
|
||||
<Label mr="3" kind="secondary">Secondary</Label>
|
||||
<Label mr="3" kind="warning">Warning</Label>
|
||||
<Label mr="3" kind="danger">Danger</Label>
|
||||
</Flex>
|
||||
))
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import Label, { Primary, Secondary, Warning, Danger } from './Label';
|
||||
export default Label;
|
||||
export {
|
||||
Primary, Secondary, Warning, Danger
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import styled from 'styled-components';
|
||||
import PropTypes from 'prop-types';
|
||||
import { space } from 'design/system';
|
||||
|
||||
const LabelInput = styled.label`
|
||||
color: ${props =>
|
||||
props.hasError ? props.theme.colors.error.main : props.theme.colors.light};
|
||||
display: block;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
width: 100%;
|
||||
${space}
|
||||
`;
|
||||
|
||||
LabelInput.propTypes = {
|
||||
hasError: PropTypes.bool,
|
||||
};
|
||||
|
||||
LabelInput.defaultProps = {
|
||||
hasError: false,
|
||||
fontSize: 0,
|
||||
mb: 1,
|
||||
};
|
||||
|
||||
LabelInput.displayName = 'LabelInput';
|
||||
|
||||
export default LabelInput;
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import LabelInput from './LabelInput';
|
||||
export default LabelInput;
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { fontSize, color, width, space } from 'design/system';
|
||||
import { fade } from 'design/theme/utils/colorManipulator';
|
||||
|
||||
const kinds = ({ theme, kind, shadow }) => {
|
||||
// default is primary
|
||||
const styles = {
|
||||
background: theme.colors.secondary.main,
|
||||
color: theme.colors.text.secondary.contrastText
|
||||
}
|
||||
|
||||
if (kind === "secondary") {
|
||||
styles.background = theme.colors.primary.dark,
|
||||
styles.color = theme.colors.text.primary
|
||||
}
|
||||
|
||||
if (kind === "warning") {
|
||||
styles.background = theme.colors.warning;
|
||||
styles.color = theme.colors.primary.contrastText;
|
||||
}
|
||||
|
||||
if (kind === "danger") {
|
||||
styles.background = theme.colors.danger;
|
||||
styles.color = theme.colors.primary.contrastText;
|
||||
}
|
||||
|
||||
if (kind === "success") {
|
||||
styles.background = theme.colors.success;
|
||||
styles.color = theme.colors.primary.contrastText;
|
||||
}
|
||||
|
||||
if(shadow) {
|
||||
styles.boxShadow = `0 0 8px ${fade(styles.background, .24)}, 0 4px 16px ${fade(styles.background, .56)}`;
|
||||
}
|
||||
|
||||
return styles;
|
||||
}
|
||||
|
||||
const LabelState = styled.span`
|
||||
border-radius: 100px;
|
||||
font-weight: bold;
|
||||
outline: none;
|
||||
text-transform: uppercase;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
white-space: nowrap;
|
||||
${fontSize}
|
||||
${space}
|
||||
${kinds}
|
||||
${width}
|
||||
${color}
|
||||
`
|
||||
LabelState.defaultProps = {
|
||||
fontSize: 0,
|
||||
px: 3,
|
||||
color: 'light',
|
||||
fontWeight: 'bold',
|
||||
shadow: false
|
||||
}
|
||||
|
||||
export default LabelState;
|
||||
export const StateDanger = props => <LabelState kind="danger" {...props} />
|
||||
export const StateInfo = props => <LabelState kind="secondary" {...props} />
|
||||
export const StateWarning = props => <LabelState kind="warning" {...props} />
|
||||
export const StateSuccess = props => <LabelState kind="success" {...props} />
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { storiesOf } from '@storybook/react'
|
||||
import LabelState from './LabelState';
|
||||
import Flex from './../Flex';
|
||||
|
||||
storiesOf('Desigin/LabelState', module)
|
||||
.add('LabelState', () => (
|
||||
<Flex height="100px" bg="primary.main" justifyContent="center" alignItems="center">
|
||||
<LabelState mr="4" kind="success">Primary</LabelState>
|
||||
<LabelState mr="4" kind="secondary">Secondary</LabelState>
|
||||
<LabelState mr="4" kind="warning">Warning</LabelState>
|
||||
<LabelState mr="4" kind="danger">Danger</LabelState>
|
||||
</Flex>
|
||||
))
|
||||
.add('with shadow', () => (
|
||||
<Flex height="100px" bg="primary.main" justifyContent="center" alignItems="center">
|
||||
<LabelState shadow mr="4" kind="success">Primary</LabelState>
|
||||
<LabelState shadow mr="4" kind="secondary">Secondary</LabelState>
|
||||
<LabelState shadow mr="4" kind="warning">Warning</LabelState>
|
||||
<LabelState shadow mr="4" kind="danger">Danger</LabelState>
|
||||
</Flex>
|
||||
))
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import LabelState, {
|
||||
StateDanger,
|
||||
StateInfo,
|
||||
StateWarning,
|
||||
StateSuccess,
|
||||
} from './LabelState';
|
||||
export default LabelState;
|
||||
|
||||
export {
|
||||
StateDanger,
|
||||
StateInfo,
|
||||
StateWarning,
|
||||
StateSuccess,
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import styled from 'styled-components';
|
||||
import { Flex, Text } from 'design';
|
||||
|
||||
/**
|
||||
* Header
|
||||
*/
|
||||
const FeatureHeader = styled(Flex)`
|
||||
flex-shrink: 0;
|
||||
`
|
||||
|
||||
FeatureHeader.defaultProps = {
|
||||
mt: 2,
|
||||
mb: 4
|
||||
}
|
||||
|
||||
/**
|
||||
* Header Title
|
||||
*/
|
||||
const FeatureHeaderTitle = styled(Text)`
|
||||
flex-shrink: 0;
|
||||
`
|
||||
|
||||
FeatureHeaderTitle.defaultProps = {
|
||||
...Text.defaultProps,
|
||||
as: 'h1',
|
||||
typography: 'h1'
|
||||
}
|
||||
|
||||
/**
|
||||
* Feature Box (container)
|
||||
*/
|
||||
const FeatureBox = styled(Flex)`
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
|
||||
/*
|
||||
This hack adds space to the bottom.
|
||||
Directly assigning padding-bottom does not work as flex container ignores this child padding.
|
||||
Directly assigning margin-bottom impacts the scrollbar area by pushing it up as well.
|
||||
It works in all major browsers.
|
||||
*/
|
||||
::after { content: ' '; padding-bottom: 24px; }
|
||||
`
|
||||
|
||||
FeatureBox.defaultProps = {
|
||||
px: 6,
|
||||
}
|
||||
|
||||
/**
|
||||
* Layout
|
||||
*/
|
||||
const AppVerticalSplit = styled.div`
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
`
|
||||
|
||||
const AppHorizontalSplit = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%
|
||||
`
|
||||
|
||||
export {
|
||||
AppHorizontalSplit,
|
||||
AppVerticalSplit,
|
||||
FeatureBox,
|
||||
FeatureHeader,
|
||||
FeatureHeaderTitle
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
AppHorizontalSplit,
|
||||
AppVerticalSplit,
|
||||
FeatureBox,
|
||||
FeatureHeader,
|
||||
FeatureHeaderTitle,
|
||||
} from './Layout';
|
||||
|
||||
export {
|
||||
|
||||
FeatureBox,
|
||||
FeatureHeader,
|
||||
FeatureHeaderTitle,
|
||||
AppHorizontalSplit,
|
||||
AppVerticalSplit,
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import styled from 'styled-components'
|
||||
import defaultTheme from 'design/theme';
|
||||
|
||||
function Link({ ...props }){
|
||||
return (
|
||||
<StyledButtonLink {...props} />
|
||||
)
|
||||
}
|
||||
|
||||
Link.defaultProps = {
|
||||
theme: defaultTheme
|
||||
}
|
||||
|
||||
Link.displayName = 'Link'
|
||||
|
||||
const StyledButtonLink = styled.a`
|
||||
color: ${({ theme }) => theme.colors.link};
|
||||
font-weight: normal;
|
||||
background: none;
|
||||
text-decoration: underline;
|
||||
text-transform: none;
|
||||
|
||||
&:hover, &:focus {
|
||||
background: ${ ({theme}) => theme.colors.primary.light}
|
||||
}
|
||||
`
|
||||
|
||||
export default Link;
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
Copyright 2019 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import Link from './Link';
|
||||
export default Link;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user