Design sidebar (#2328)

* updated lock file

* Rolling sidebar from SB into application

* Type fix on the method label output

* Update packages/insomnia-components/components/sidebar.js

Co-authored-by: Opender Singh <opender94@gmail.com>

* PR Feedback - Keys, useCallback Hook

* stubbing component breakout

* PR Feedback

- Breaking out most UI elements into components
- Filter component in place
- Various CSS tweaks

* Removing unused file

* Updating toggle

* Resuable sidebar section (#2359)

* Introduce resuable sidebar section
* Stop eslint complaining
* add react-use
* Lint fixes
* Make the storybook story less wide

* Component development

Abstracting out line level components i.e.
Section > Header > Filter > Panel > Items

Various code fixes

* Cleaning up section visibility state

* Reverting visibiilty state updater

* Adding paths on click for spec scrolling

* refreshing package-lock to resolve conflict

* PR feedback for sidebar components

* Update packages/insomnia-components/components/sidebar/sidebar-header.js

Co-authored-by: Opender Singh <opender94@gmail.com>

* Including lock

* Merge fix

* Component structuring, prop clean-up, css updates

* Cleaning up components, pr feedback, fixing styling

* array index reference clean-up/clarity

* Leveraging useToggle rather than manual useState toggling

* Cleaning up logs

* Hide info section if missing from spec.

* Update packages/insomnia-components/components/sidebar/sidebar-responses.js

Co-authored-by: Opender Singh <opender94@gmail.com>

* Update packages/insomnia-components/components/sidebar/sidebar-schemas.js

Co-authored-by: Opender Singh <opender94@gmail.com>

* Pull fragment

* Destructuring and filter cleanup

* Clearing filter value and DOM on section collapse

* Merge latest

* Merge conflict cleanup

Co-authored-by: Opender Singh <opender94@gmail.com>
This commit is contained in:
Mike Ellan 2020-07-22 09:13:06 -04:00 committed by GitHub
parent dd87c31450
commit b7bc88a326
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 4562 additions and 411 deletions

View File

@ -2,9 +2,10 @@
import * as React from 'react';
import autobind from 'autobind-decorator';
import YAML from 'yaml';
import SpecEditorSidebarItem from './spec-editor-sidebar-item';
import { Sidebar } from 'insomnia-components';
import type { ApiSpec } from '../../../models/api-spec';
import { trackEvent } from '../../../common/analytics';
import SpecEditorSidebarItem from './spec-editor-sidebar-item';
type Props = {|
apiSpec: ApiSpec,
@ -39,6 +40,7 @@ class SpecEditorSidebar extends React.PureComponent<Props, State> {
componentDidUpdate() {
const { apiSpec } = this.props;
const { error } = this.state;
if (apiSpec.type === 'json') {
this.setState({
error:
@ -118,6 +120,7 @@ class SpecEditorSidebar extends React.PureComponent<Props, State> {
render() {
const { error } = this.state;
if (error) {
return <p className="notice error margin-sm">{error}</p>;
}
@ -125,6 +128,12 @@ class SpecEditorSidebar extends React.PureComponent<Props, State> {
const { apiSpec } = this.props;
const specCst = YAML.parseCST(apiSpec.contents);
let specJSON = {};
if (apiSpec.contentType === 'yaml') {
specJSON = YAML.parse(apiSpec.contents);
}
if (!specCst) {
return null;
}
@ -135,9 +144,14 @@ class SpecEditorSidebar extends React.PureComponent<Props, State> {
return null;
}
const navigationEl = document.contents.map(v => this.renderNext(v, '$'));
// const navigationEl = document.contents.map(v => this.renderNext(v, '$'));
return <div className="spec-editor-sidebar">{navigationEl}</div>;
return (
<div className="spec-editor-sidebar">
<Sidebar jsonData={specJSON} />
{/* navigationEl */}
</div>
);
}
}

View File

@ -1,37 +0,0 @@
.spec-editor-sidebar {
padding: var(--padding-sm);
overflow: auto;
li ul {
border-left: 1px dotted var(--hl-lg);
}
li {
display: block;
width: 100%;
white-space: nowrap;
}
li > button {
display: inline-block;
height: var(--line-height-xxxs);
// Extra padding for the textual button so we have
// a larger click area.
&:last-of-type {
padding-right: var(--padding-md);
}
i {
width: calc(var(--padding-md) * 1.3);
color: var(--hl);
font-size: var(--font-size-lg);
padding: var(--padding-xs);
}
}
ul ul {
margin-left: var(--padding-md);
padding-left: var(--padding-sm);
}
}

View File

@ -53,7 +53,6 @@
@import 'components/sidebar';
@import 'components/spec-editor';
@import 'components/unit-tests';
@import 'components/spec-editor-sidebar';
@import 'components/tabs';
@import 'components/tag';
@import 'components/themes';

View File

@ -1212,7 +1212,6 @@
"version": "0.8.8",
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
"integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==",
"dev": true,
"requires": {
"@emotion/memoize": "0.7.4"
}
@ -1220,8 +1219,7 @@
"@emotion/memoize": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz",
"integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==",
"dev": true
"integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw=="
},
"@emotion/serialize": {
"version": "0.11.16",
@ -1474,6 +1472,23 @@
"@types/node": ">= 8"
}
},
"@popmotion/easing": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@popmotion/easing/-/easing-1.0.2.tgz",
"integrity": "sha512-IkdW0TNmRnWTeWI7aGQIVDbKXPWHVEYdGgd5ZR4SH/Ty/61p63jCjrPxX1XrR7IGkl08bjhJROStD7j+RKgoIw=="
},
"@popmotion/popcorn": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/@popmotion/popcorn/-/popcorn-0.4.4.tgz",
"integrity": "sha512-jYO/8319fKoNLMlY4ZJPiPu8Ea8occYwRZhxpaNn/kZsK4QG2E7XFlXZMJBsTWDw7I1i0uaqyC4zn1nwEezLzg==",
"requires": {
"@popmotion/easing": "^1.0.1",
"framesync": "^4.0.1",
"hey-listen": "^1.0.8",
"style-value-types": "^3.1.7",
"tslib": "^1.10.0"
}
},
"@reach/router": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@reach/router/-/router-1.3.3.tgz",
@ -9304,6 +9319,31 @@
"map-cache": "^0.2.2"
}
},
"framer-motion": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-1.11.1.tgz",
"integrity": "sha512-CP6aYLPSivAWkq9UoSurefHBggxG85IT8ObYyWYkcZppgtjHzpwRzhaA8P0ljMGRqtcpeQAIybiGgPioBPlOSw==",
"requires": {
"@emotion/is-prop-valid": "^0.8.2",
"@popmotion/easing": "^1.0.2",
"@popmotion/popcorn": "^0.4.2",
"framesync": "^4.0.4",
"hey-listen": "^1.0.8",
"popmotion": "9.0.0-beta-8",
"style-value-types": "^3.1.6",
"stylefire": "^7.0.2",
"tslib": "^1.10.0"
}
},
"framesync": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/framesync/-/framesync-4.0.4.tgz",
"integrity": "sha512-mdP0WvVHe0/qA62KG2LFUAOiWLng5GLpscRlwzBxu2VXOp6B8hNs5C5XlFigsMgrfDrr2YbqTsgdWZTc4RXRMQ==",
"requires": {
"hey-listen": "^1.0.8",
"tslib": "^1.10.0"
}
},
"fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
@ -10246,6 +10286,11 @@
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
"dev": true
},
"hey-listen": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz",
"integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q=="
},
"highlight.js": {
"version": "9.18.1",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.18.1.tgz",
@ -14474,6 +14519,19 @@
"@babel/runtime": "^7.8.7"
}
},
"popmotion": {
"version": "9.0.0-beta-8",
"resolved": "https://registry.npmjs.org/popmotion/-/popmotion-9.0.0-beta-8.tgz",
"integrity": "sha512-6eQzqursPvnP7ePvdfPeY4wFHmS3OLzNP8rJRvmfFfEIfpFqrQgLsM50Gd9AOvGKJtYJOFknNG+dsnzCpgIdAA==",
"requires": {
"@popmotion/easing": "^1.0.1",
"@popmotion/popcorn": "^0.4.2",
"framesync": "^4.0.4",
"hey-listen": "^1.0.8",
"style-value-types": "^3.1.6",
"tslib": "^1.10.0"
}
},
"popper.js": {
"version": "1.16.1",
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
@ -18025,6 +18083,27 @@
}
}
},
"style-value-types": {
"version": "3.1.7",
"resolved": "https://registry.npmjs.org/style-value-types/-/style-value-types-3.1.7.tgz",
"integrity": "sha512-jPaG5HcAPs3vetSwOJozrBXxuHo9tjZVnbRyBjxqb00c2saIoeuBJc1/2MtvB8eRZy41u/BBDH0CpfzWixftKg==",
"requires": {
"hey-listen": "^1.0.8",
"tslib": "^1.10.0"
}
},
"stylefire": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/stylefire/-/stylefire-7.0.3.tgz",
"integrity": "sha512-Q0l7NSeFz/OkX+o6/7Zg3VZxSAZeQzQpYomWmIpOehFM/rJNMSLVX5fgg6Q48ut2ETNKwdhm97mPNU643EBCoQ==",
"requires": {
"@popmotion/popcorn": "^0.4.4",
"framesync": "^4.0.0",
"hey-listen": "^1.0.8",
"style-value-types": "^3.1.7",
"tslib": "^1.10.0"
}
},
"sumchecker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-2.0.2.tgz",

View File

@ -104,6 +104,7 @@
"electron-context-menu": "^0.10.0",
"electron-updater": "^4.2.0",
"font-manager": "^0.3.1",
"framer-motion": "^1.11.1",
"fs-extra": "^5.0.0",
"fuzzysort": "^1.1.1",
"graphql": "^14.5.8",

28
packages/insomnia-cli/dist/cli.js vendored Executable file
View File

@ -0,0 +1,28 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.go = go;
var _generate = require("./commands/generate");
var _util = require("./util");
function makeGenerateCommand(exitOverride) {
// inso generate
const generate = (0, _util.createCommand)(exitOverride, 'generate').description('Code generation utilities');
const conversionTypes = Object.keys(_generate.ConversionTypeMap).join(', '); // inso generate config -t kubernetes config.yaml
generate.command('config <identifier>').description('Generate configuration from an api spec').requiredOption('-t, --type <value>', `the type of configuration to generate, options are [${conversionTypes}]`).option('-o, --output <path>', 'the output path').action((identifier, cmd) => (0, _generate.generateConfig)(identifier, (0, _util.getAllOptions)(cmd)));
return generate;
}
function go(args, exitOverride) {
if (!args) {
args = process.argv;
} // inso -v
(0, _util.createCommand)(!!exitOverride).version((0, _util.getVersion)(), '-v, --version').description('A CLI for Insomnia!').option('--workingDir <dir>', 'Working directory').addCommand(makeGenerateCommand(!!exitOverride)).parseAsync(args).catch(err => console.log('An error occurred', err));
}

View File

@ -0,0 +1,82 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.generateConfig = generateConfig;
exports.ConversionTypeMap = void 0;
var o2k = _interopRequireWildcard(require("openapi-2-kong"));
var _yaml = _interopRequireDefault(require("yaml"));
var _path = _interopRequireDefault(require("path"));
var _fs = _interopRequireDefault(require("fs"));
var _memDb = require("../db/mem-db");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
const ConversionTypeMap = {
kubernetes: 'kong-for-kubernetes',
declarative: 'kong-declarative-config'
};
exports.ConversionTypeMap = ConversionTypeMap;
function validateOptions({
type
}) {
if (!ConversionTypeMap[type]) {
const conversionTypes = Object.keys(ConversionTypeMap).join(', ');
console.log(`Config type "${type}" not unrecognized. Options are [${conversionTypes}].`);
return false;
}
return true;
}
async function generateConfig(identifier, options) {
if (!validateOptions(options)) {
return;
}
const {
type,
output,
workingDir
} = options;
const db = await (0, _memDb.gitDataDirDb)({
dir: workingDir,
filterTypes: ['ApiSpec']
});
let result;
const specFromDb = db.ApiSpec.get(identifier);
try {
if (specFromDb === null || specFromDb === void 0 ? void 0 : specFromDb.contents) {
result = await o2k.generateFromString(specFromDb.contents, ConversionTypeMap[type]);
} else {
result = await o2k.generate(identifier, ConversionTypeMap[type]);
}
} catch (err) {
console.log('Config failed to generate', err);
return;
}
const yamlDocs = result.documents.map(d => _yaml.default.stringify(d)); // Join the YAML docs with "---" and strip any extra newlines surrounding them
const document = yamlDocs.join('\n---\n').replace(/\n+---\n+/g, '\n---\n');
if (output) {
const fullOutputPath = _path.default.resolve(output);
_fs.default.writeFileSync(fullOutputPath, document);
} else {
console.log(document);
}
}

View File

@ -0,0 +1 @@
"use strict";

65
packages/insomnia-cli/dist/db/mem-db.js vendored Normal file
View File

@ -0,0 +1,65 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.gitDataDirDb = exports.emptyDb = void 0;
var _fs = _interopRequireDefault(require("fs"));
var _path = _interopRequireDefault(require("path"));
var _yaml = _interopRequireDefault(require("yaml"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const emptyDb = () => ({
ApiSpec: new Map(),
Environment: new Map(),
Request: new Map(),
RequestGroup: new Map(),
Workspace: new Map()
});
exports.emptyDb = emptyDb;
const gitDataDirDb = async ({
dir,
filterTypes
}) => {
const db = emptyDb();
const insomniaDir = _path.default.normalize(_path.default.join(dir || '.', '.insomnia'));
if (!_fs.default.existsSync(insomniaDir)) {
// TODO: control logging with verbose flag
// console.log(`Directory not found: ${insomniaDir}`);
return db;
}
const readAndInsertDoc = async (type, fileName) => {
// Get contents of each file in type dir and insert into data
const contents = await _fs.default.promises.readFile(fileName);
const obj = _yaml.default.parse(contents.toString());
db[type].set(obj._id, obj);
};
const types = (filterTypes === null || filterTypes === void 0 ? void 0 : filterTypes.length) ? filterTypes : Object.keys(db);
await Promise.all(types.map(async type => {
// Get all files in type dir
const typeDir = _path.default.join(insomniaDir, type);
if (!_fs.default.existsSync(typeDir)) {
return;
}
const files = await _fs.default.promises.readdir(typeDir);
return Promise.all( // Insert each file from each type
files.map(file => readAndInsertDoc(type, _path.default.join(insomniaDir, type, file))));
}));
return db;
};
exports.gitDataDirDb = gitDataDirDb;

11
packages/insomnia-cli/dist/db/types.js vendored Normal file
View File

@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.SpecName = void 0;
// These types should come from a shared location (maybe insomnia-importers?)
// They represent the models that are read from an Insomnia data source
// eg. git data directory, insomnia export format, etc
const SpecName = 'ApiSpec';
exports.SpecName = SpecName;

47
packages/insomnia-cli/dist/util.js vendored Normal file
View File

@ -0,0 +1,47 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createCommand = createCommand;
exports.getVersion = getVersion;
exports.getAllOptions = getAllOptions;
var _commander = _interopRequireDefault(require("commander"));
var packageJson = _interopRequireWildcard(require("../package.json"));
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function createCommand(exitOverride, cmd) {
const command = new _commander.default.Command(cmd).storeOptionsAsProperties(false);
if (exitOverride) {
return command.exitOverride();
}
return command;
}
function getVersion() {
return packageJson.version;
}
function getAllOptions(cmd) {
let opts = {};
let command = cmd;
do {
// overwrite options with more specific ones
opts = { ...command.opts(),
...opts
};
command = command.parent;
} while (command);
return opts;
}

View File

@ -0,0 +1,3 @@
<svg width="12" height="12" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.5043 0C3.22008 0.0700802 2.31222 0.431767 1.87283 1.23733C1.64192 1.66065 1.59958 2.11416 1.61377 2.50458C1.62747 2.88126 1.69821 3.27006 1.75763 3.59673L1.7621 3.62126C1.8268 3.97713 1.87782 4.26573 1.88721 4.52411C1.89645 4.77823 1.86067 4.92628 1.81033 5.01858C1.74188 5.14407 1.45352 5.48624 0.00541421 5.48709L0 5.48709V6.98709L0.00541658 6.98709C1.47819 6.98788 1.7696 7.31083 1.82563 7.40421C1.86219 7.46514 1.89594 7.57359 1.88732 7.78915C1.8784 8.01198 1.82975 8.26408 1.76456 8.59L1.75942 8.61571C1.70045 8.91029 1.62799 9.27231 1.61388 9.62508C1.59906 9.99546 1.64343 10.4339 1.88813 10.8417C2.39453 11.6857 3.47747 11.9871 5 11.9871L4.56849 10.4768C3.46319 10.421 3.22451 10.1535 3.17437 10.07C3.13781 10.009 3.10406 9.9006 3.11268 9.68504C3.12159 9.46221 3.17025 9.2101 3.23543 8.88418L3.24058 8.85848C3.29954 8.56389 3.37201 8.20188 3.38612 7.8491C3.40093 7.47872 3.35656 7.04029 3.11187 6.63247C3.01632 6.47322 2.90024 6.33328 2.76455 6.21105C2.90802 6.07391 3.02923 5.91641 3.12717 5.73686C3.35807 5.31353 3.40042 4.86002 3.38622 4.4696C3.37252 4.09293 3.30179 3.70412 3.24236 3.37746L3.2379 3.35293C3.1732 2.99705 3.12218 2.70845 3.11278 2.45007C3.10354 2.19596 3.13932 2.04791 3.18967 1.95561C3.2582 1.82996 3.54719 1.48709 5 1.48709L4.5043 0ZM7.49569 0L7 1.48708V1.48709C8.45281 1.48709 8.74179 1.82996 8.81033 1.95561C8.86067 2.04791 8.89645 2.19596 8.88721 2.45007C8.87782 2.70845 8.8268 2.99705 8.7621 3.35293L8.75763 3.37746L8.75763 3.37747C8.6982 3.70413 8.62747 4.09293 8.61378 4.4696C8.59958 4.86002 8.64192 5.31353 8.87283 5.73686C8.97076 5.91641 9.09198 6.07391 9.23545 6.21105C9.09976 6.33329 8.98368 6.47322 8.88813 6.63247C8.64343 7.04029 8.59906 7.47872 8.61388 7.8491C8.62799 8.20187 8.70045 8.56388 8.75942 8.85846L8.75942 8.85848L8.76456 8.88418C8.82975 9.2101 8.8784 9.46221 8.88732 9.68504C8.89594 9.9006 8.86219 10.009 8.82563 10.07C8.77549 10.1535 8.53681 10.421 7.43151 10.4768L7 11.9871C8.52252 11.9871 9.60547 11.6857 10.1119 10.8417C10.3566 10.4339 10.4009 9.99546 10.3861 9.62508C10.372 9.27231 10.2995 8.91029 10.2406 8.61571L10.2354 8.59C10.1702 8.26408 10.1216 8.01198 10.1127 7.78915C10.1041 7.57359 10.1378 7.46514 10.1744 7.40421C10.2305 7.31072 10.5225 6.98709 12 6.98709V5.48709C10.5472 5.48709 10.2582 5.14423 10.1897 5.01858C10.1393 4.92628 10.1035 4.77823 10.1128 4.52411C10.1222 4.26573 10.1732 3.97713 10.2379 3.62126L10.2424 3.59673C10.3018 3.27006 10.3725 2.88126 10.3862 2.50458C10.4004 2.11416 10.3581 1.66065 10.1272 1.23733C9.68778 0.431767 8.77991 0.0700802 7.49569 0Z" fill="#000000"/>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,3 @@
<svg width="12px" height="12px" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.62129 7.5L8.62135 10.5001L10.5 10.5001V9.5H9.5V8.5H8.5V7.5H7.5V3C7.5 2.17157 6.82843 1.5 6 1.5H3C2.17157 1.5 1.5 2.17157 1.5 3V6C1.5 6.82843 2.17157 7.5 3 7.5H5.62129ZM12 8.00021L12 11L12 11C11.9999 11.5523 11.5523 12 11 12L10.9998 12.0002L8 12L4.99997 9H3C1.34315 9 0 7.65685 0 6V3C0 1.34315 1.34315 0 3 0H6C7.65685 0 9 1.34315 9 3V6H9.99988L10 7H10.9998L11 8L12 8.00021ZM2.5 3.5C2.5 4.05228 2.94772 4.5 3.5 4.5C4.05228 4.5 4.5 4.05228 4.5 3.5C4.5 2.94772 4.05228 2.5 3.5 2.5C2.94772 2.5 2.5 2.94772 2.5 3.5Z" fill="#000000" />
</svg>

After

Width:  |  Height:  |  Size: 679 B

View File

@ -1,345 +0,0 @@
// @flow
import * as React from 'react';
import { useState } from 'react';
import { motion } from 'framer-motion';
import styled from 'styled-components';
import Tooltip from './tooltip';
import SvgIcon, { IconEnum } from './svg-icon';
type Props = {|
className?: string,
|};
const StyledSidebar: React.ComponentType<{}> = styled.div`
/* To constants */
background-color: var(--color-bg);
border: 1px solid var(--hl-md);
color: var(--color-font);
position: relative;
svg {
font-size: var(--font-size-xl);
fill: var(--hl-lg);
}
.method {
h6 {
font-size: var(--font-size-xxs);
}
}
.method-post {
color: var(--color-success);
}
.method-get {
color: var(--color-surprise);
}
.method-del {
color: var(--color-danger);
}
.method-options-head,
.method-custom {
color: var(--color-info);
}
.method-patch {
color: var(--color-notice);
}
.method-put {
color: var(--color-warning);
}
h6 {
font-size: var(--font-size-xs);
display: flex;
flex-grow: 1;
&:hover {
cursor: default;
}
}
h5 {
font-size: var(--font-size-sm);
}
/* END To constants */
width: 260px;
height: 100%;
`;
const StyledSection: React.ComponentType<{}> = styled(motion.ul)`
overflow: hidden;
box-sizing: border-box;
border-bottom: 1px solid var(--hl-md);
`;
const StyledHeader: React.ComponentType<{}> = styled.li`
display: flex;
justify-content: space-between;
align-items: center;
&:hover {
background-color: var(--hl-xs);
}
& > * {
padding: var(--padding-md) var(--padding-md) var(--padding-md) var(--padding-md);
font-size: var(--font-size-md);
svg {
margin-left: var(--padding-sm);
&:hover {
fill: var(--color-font);
opacity: 1;
}
}
}
`;
const StyledItem: React.ComponentType<{}> = styled.li`
padding: var(--padding-sm) 0 var(--padding-sm) 0;
margin: 0px;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(var(--padding-lg), 1fr));
column-gap: var(--padding-sm);
grid-template-rows: 1fr;
align-items: start;
white-space: nowrap;
font-size: var(--font-size-md);
line-height: calc(var(--font-size) * 1.25);
a {
color: var(--hl-xl);
}
div:nth-child(1) {
text-align: right;
}
&:hover {
background-color: var(--hl-xxs);
cursor: default;
}
&:last-child {
margin-bottom: var(--padding-md);
}
`;
const StyledFilter: React.ComponentType<{}> = styled(motion.div)`
padding-left: var(--padding-md);
padding-right: var(--padding-md);
overflow: hidden;
input {
box-sizing: border-box;
width: 100%;
font-size: var(--font-size-md);
padding: var(--padding-sm);
margin-top: var(--padding-md);
margin-bottom: var(--padding-sm);
}
`;
const StyledPanel: React.ComponentType<{}> = styled(motion.div)`
height: 0px;
`;
function Sidebar(props: Props) {
// Temp garbage for easing/transition/sequencing dial-in
const [visible, setVisible] = useState(false);
const [visible2, setVisible2] = useState(false);
const [visible3, setVisible3] = useState(true);
const [visible4, setVisible4] = useState(true);
const toggleVisible = () => setVisible(!visible);
const toggleVisible2 = () => setVisible2(!visible2);
const toggleVisible3 = () => setVisible3(!visible3);
const toggleVisible4 = () => setVisible4(!visible4);
return (
<StyledSidebar className="theme--sidebar">
<StyledSection>
<StyledHeader>
<h6>INFO</h6>
</StyledHeader>
</StyledSection>
<StyledSection>
<StyledHeader>
<h6 onClick={toggleVisible2}>SERVERS</h6>
<div>
<motion.span
initial={{ opacity: visible2 ? 0.6 : 0 }}
animate={{ opacity: visible2 ? 0.6 : 0 }}
transition={{ duration: 0.2, ease: 'easeInOut', delay: 0.2 }}>
<SvgIcon icon={IconEnum.trashcan} />
</motion.span>
<motion.span
onClick={toggleVisible3}
initial={{ opacity: visible2 ? 0.6 : 0 }}
animate={{ opacity: visible2 ? 0.6 : 0 }}
transition={{ duration: 0.2, ease: 'easeInOut', delay: 0.15 }}>
<SvgIcon icon={IconEnum.search} />
</motion.span>
<motion.span
initial={{ opacity: visible2 ? 0.6 : 0.4 }}
animate={{ opacity: visible2 ? 0.6 : 0.4 }}
transition={{ duration: 0.2, ease: 'easeInOut', delay: 0.1 }}>
<Tooltip message="Add" position="top">
<SvgIcon icon={IconEnum.plus} />
</Tooltip>
</motion.span>
</div>
</StyledHeader>
<StyledPanel
initial={{ height: visible2 ? '100%' : '0px' }}
animate={{ height: visible2 ? '100%' : '0px' }}
transition={{ duration: 0.2, ease: 'easeInOut', delay: 0 }}>
<StyledFilter
initial={{ height: visible3 ? '0px' : '100%' }}
animate={{ height: visible3 ? '0px' : '100%' }}
transition={{ duration: 0.2, ease: 'easeInOut', delay: 0 }}>
<input placeholder="Filter..." />
</StyledFilter>
<StyledItem>
<div>
<SvgIcon icon={IconEnum.indentation} />
</div>
<div>development.konghq.com</div>
</StyledItem>
<StyledItem>
<div>
<SvgIcon icon={IconEnum.indentation} />
</div>
<div>staging.konghq.com</div>
</StyledItem>
<StyledItem>
<div>
<SvgIcon icon={IconEnum.indentation} />
</div>
<div>production.konghq.com</div>
</StyledItem>
</StyledPanel>
</StyledSection>
<StyledSection>
<StyledHeader>
<h6 onClick={toggleVisible}>PATHS</h6>
<div>
<motion.span
initial={{ opacity: visible ? 0.6 : 0 }}
animate={{ opacity: visible ? 0.6 : 0 }}
transition={{ duration: 0.2, ease: 'easeInOut', delay: 0.2 }}>
<SvgIcon icon={IconEnum.trashcan} />
</motion.span>
<motion.span
onClick={toggleVisible4}
initial={{ opacity: visible ? 0.6 : 0 }}
animate={{ opacity: visible ? 0.6 : 0 }}
transition={{ duration: 0.2, ease: 'easeInOut', delay: 0.15 }}>
<SvgIcon icon={IconEnum.search} />
</motion.span>
<motion.span
initial={{ opacity: visible ? 0.6 : 0.4 }}
animate={{ opacity: visible ? 0.6 : 0.4 }}
transition={{ duration: 0.2, ease: 'easeInOut', delay: 0.1 }}>
<Tooltip message="Add" position="top">
<SvgIcon icon={IconEnum.plus} />
</Tooltip>
</motion.span>
</div>
</StyledHeader>
<StyledPanel
initial={{ height: visible ? '100%' : '0px' }}
animate={{ height: visible ? '100%' : '0px' }}
transition={{ duration: 0.2, ease: 'easeInOut', delay: 0 }}>
<StyledFilter
initial={{ height: visible4 ? '0px' : '100%' }}
animate={{ height: visible4 ? '0px' : '100%' }}
transition={{ duration: 0.2, ease: 'easeInOut', delay: 0 }}>
<input placeholder="Filter..." />
</StyledFilter>
<StyledItem>
<div>
<SvgIcon icon={IconEnum.folderOpen} />
</div>
<h5>pet</h5>
</StyledItem>
<StyledItem>
<div></div>
<h6 className="method-post">POST</h6>
<p>/store/inventory/(orderId)</p>
</StyledItem>
<StyledItem>
<div></div>
<h6 className="method-get">GET</h6>
<p>/store/inventory/(orderId)</p>
</StyledItem>
<StyledItem>
<div></div>
<h6 className="method-put">PUT</h6>
<p>/store/inventory/(orderId)</p>
</StyledItem>
<StyledItem>
<div></div>
<h6 className="method-del">DEL</h6>
<p>/store/inventory/(orderId)</p>
</StyledItem>
<StyledItem>
<div></div>
<h6 className="method-post">POST</h6>
<p>/store/inventory/(orderId)</p>
</StyledItem>
<StyledItem>
<div></div>
<h6 className="method-put">PUT</h6>
<p>/store/inventory/(orderId)</p>
</StyledItem>
<StyledItem>
<div>
<SvgIcon icon={IconEnum.folderOpen} />
</div>
<h5>store</h5>
</StyledItem>
<StyledItem>
<div></div>
<h6 className="method-put">PUT</h6>
<p>/store/inventory/(orderId)</p>
</StyledItem>
<StyledItem>
<div></div>
<h6 className="method-del">DEL</h6>
<p>/store/inventory/(orderId)</p>
</StyledItem>
<StyledItem>
<div></div>
<h6 className="method-post">POST</h6>
<p>/store/inventory/(orderId)</p>
</StyledItem>
<StyledItem>
<div></div>
<h6 className="method-put">PUT</h6>
<p>/store/inventory/(orderId)</p>
</StyledItem>
<StyledItem>
<div>
<SvgIcon icon={IconEnum.folder} />
</div>
<h5>user</h5>
</StyledItem>
</StyledPanel>
</StyledSection>
<StyledSection>
<StyledHeader>
<h6>MODELS</h6>
<SvgIcon icon={IconEnum.plus} />
</StyledHeader>
</StyledSection>
<StyledSection>
<StyledHeader>
<h6>SECURITY</h6>
<SvgIcon icon={IconEnum.plus} />
</StyledHeader>
</StyledSection>
</StyledSidebar>
);
}
export default Sidebar;

View File

@ -1,20 +0,0 @@
import React from 'react';
import Sidebar from './sidebar';
import { withKnobs } from '@storybook/addon-knobs';
import { withDesign } from 'storybook-addon-designs';
export default {
title: '1st Party | Sidebar',
decorators: [withKnobs, withDesign],
};
export const _default = () => <Sidebar />;
_default.story = {
parameters: {
design: {
type: 'figma',
url: 'https://www.figma.com/file/sS7oBbKmDvhtq5lXyTckVe/Style-Guide-Components?node-id=0%3A2',
},
},
};

View File

@ -0,0 +1,165 @@
// @flow
import * as React from 'react';
import { motion } from 'framer-motion';
import styled from 'styled-components';
import SidebarHeader from './sidebar-header';
import SidebarInfo from './sidebar-info';
import SidebarServers from './sidebar-servers';
import SidebarPaths from './sidebar-paths';
import SidebarRequests from './sidebar-requests';
import SidebarResponses from './sidebar-responses';
import SidebarParameters from './sidebar-parameters';
import SidebarHeaders from './sidebar-headers';
import SidebarSchemas from './sidebar-schemas';
import SidebarSecurity from './sidebar-security';
import Dropdown from '../dropdown/dropdown';
import DropdownItem from '../dropdown/dropdown-item';
import DropdownDivider from '../dropdown/dropdown-divider';
import SvgIcon, { IconEnum } from '../svg-icon';
import { useToggle } from 'react-use';
type Props = {|
className?: string,
jsonData: Object,
|};
const StyledSidebar: React.ComponentType<{}> = styled.div`
width: 100%;
height: 100%;
background-color: var(--color-bg);
border: none;
color: var(--color-font);
position: relative;
svg {
font-size: var(--font-size-xl);
fill: var(--hl-lg);
}
ul:first-child {
border-top: none;
}
ul:last-child {
border-bottom: none;
}
`;
const StyledSection: React.ComponentType<{}> = styled(motion.ul)`
overflow: hidden;
box-sizing: border-box;
border-bottom: 1px solid var(--hl-md);
`;
const DropdownEllipsis = () => <SvgIcon icon={IconEnum.ellipsesCircle} />;
// Section Expansion & Filtering
function Sidebar(props: Props) {
// Section Visibility
const [infoSec, setInfoSec] = useToggle(false);
const [pathsVisible, setPathsVisible] = useToggle(true);
const [serversVisible, setServersVisible] = useToggle(true);
const [requestsVisible, setRequestsVisible] = useToggle(true);
const [responsesVisible, setResponsesVisible] = useToggle(true);
const [parametersVisible, setParametersVisible] = useToggle(true);
const [headersVisible, setHeadersVisible] = useToggle(true);
const [schemasVisible, setSchemasVisible] = useToggle(true);
const [securityVisible, setSecurityVisible] = useToggle(true);
// Sections
if (props.jsonData === null) {
return null;
}
const { servers, info } = props.jsonData;
const {
requestBodies,
responses,
parameters,
headers,
schemas,
securitySchemes,
} = props.jsonData.components;
const paths = Object.entries(props.jsonData.paths);
return (
<StyledSidebar className="theme--sidebar">
{info && (
<StyledSection>
<SidebarHeader headerTitle="INFO" sectionVisible={infoSec} toggleSection={setInfoSec}>
<Dropdown renderButton={DropdownEllipsis}>
<DropdownDivider>VISIBILITY</DropdownDivider>
<DropdownItem stayOpenAfterClick>
<input
type="checkbox"
onClick={setServersVisible}
defaultChecked={serversVisible}
/>
<label htmlFor="servers">Servers</label>
</DropdownItem>
<DropdownItem stayOpenAfterClick>
<input type="checkbox" onClick={setPathsVisible} defaultChecked={pathsVisible} />
<label htmlFor="paths">Paths</label>
</DropdownItem>
<DropdownItem stayOpenAfterClick>
<input
type="checkbox"
onClick={setRequestsVisible}
defaultChecked={requestsVisible}
/>
<label htmlFor="requests">Requests</label>
</DropdownItem>
<DropdownItem stayOpenAfterClick>
<input
type="checkbox"
onClick={setResponsesVisible}
defaultChecked={responsesVisible}
/>
<label htmlFor="responses">Responses</label>
</DropdownItem>
<DropdownItem stayOpenAfterClick>
<input
type="checkbox"
onClick={setParametersVisible}
defaultChecked={parametersVisible}
/>
<label htmlFor="parameters">Parameters</label>
</DropdownItem>
<DropdownItem stayOpenAfterClick>
<input
type="checkbox"
onClick={setHeadersVisible}
defaultChecked={headersVisible}
/>
<label htmlFor="headers">Headers</label>
</DropdownItem>
<DropdownItem stayOpenAfterClick>
<input
type="checkbox"
onClick={setSchemasVisible}
defaultChecked={schemasVisible}
/>
<label htmlFor="schemas">Schemas</label>
</DropdownItem>
<DropdownItem stayOpenAfterClick>
<input
type="checkbox"
onClick={setSecurityVisible}
defaultChecked={securityVisible}
/>
<label htmlFor="security">Security</label>
</DropdownItem>
</Dropdown>
</SidebarHeader>
<SidebarInfo childrenVisible={infoSec} info={info} />
</StyledSection>
)}
{serversVisible && servers && <SidebarServers servers={servers} />}
{pathsVisible && paths && <SidebarPaths paths={paths} />}
{requestsVisible && requestBodies && <SidebarRequests requests={requestBodies} />}
{responsesVisible && responses && <SidebarResponses responses={responses} />}
{parametersVisible && parameters && <SidebarParameters parameters={parameters} />}
{headersVisible && headers && <SidebarHeaders headers={headers} />}
{schemasVisible && schemas && <SidebarSchemas schemas={schemas} />}
{securityVisible && schemas && <SidebarSecurity security={securitySchemes} />}
</StyledSidebar>
);
}
export default Sidebar;

View File

@ -0,0 +1,57 @@
// @flow
import * as React from 'react';
import { useLayoutEffect } from 'react';
import styled from 'styled-components';
import { motion } from 'framer-motion';
type Props = {
filter: boolean,
onChange?: (e: SyntheticInputEvent<HTMLInputElement>) => any,
};
const StyledFilter: React.ComponentType<{}> = styled(motion.div)`
padding-left: var(--padding-md);
padding-right: var(--padding-md);
overflow: hidden;
input {
box-sizing: border-box;
width: 100%;
font-size: var(--font-size-sm);
padding: var(--padding-xs);
margin-top: 0;
margin-bottom: var(--padding-sm);
outline-style: none;
box-shadow: none;
border: 1px solid var(--hl-md);
color: var(--color-font);
background: transparent;
:focus::placeholder {
color: transparent;
}
::placeholder {
color: var(--color-font);
}
}
`;
const SidebarFilter = ({ filter, onChange }: Props) => {
const filterField = React.createRef();
useLayoutEffect(() => {
if (filterField.current && !filter) {
filterField.current.value = '';
}
}, [filter, filterField]);
return (
<StyledFilter
initial={{ height: filter ? '100%' : '0px' }}
animate={{ height: filter ? '100%' : '0px' }}>
<input type="text" placeholder="Filter..." onChange={onChange} ref={filterField} />
</StyledFilter>
);
};
export default SidebarFilter;

View File

@ -0,0 +1,80 @@
// @flow
import * as React from 'react';
import styled from 'styled-components';
import { motion } from 'framer-motion';
import SvgIcon, { IconEnum } from '../svg-icon';
type Props = {
headerTitle: string,
toggleSection: (toggle: SyntheticKeyboardEvent<HTMLButtonElement>) => void,
toggleFilter?: () => void,
sectionVisible: boolean,
children?: React.Node,
};
const StyledHeader: React.ComponentType<{}> = styled.li`
display: flex;
justify-content: space-between;
align-items: center;
&:hover {
background-color: var(--hl-xs);
}
h6 {
font-size: var(--font-size-xs);
display: flex;
flex-grow: 1;
&:hover {
cursor: default;
}
}
h6:hover {
text-decoration: underline;
}
label {
color: red !important;
position: absolute;
padding-top: var(--padding-xs);
}
& > * {
padding: var(--padding-md) var(--padding-md) var(--padding-md) var(--padding-md);
font-size: var(--font-size-md);
svg {
margin-left: var(--padding-sm);
&:hover {
fill: var(--color-font);
opacity: 1;
}
}
}
`;
const SidebarHeader = ({
headerTitle,
toggleSection,
toggleFilter,
sectionVisible,
children,
}: Props) => (
<StyledHeader>
<h6 onClick={toggleSection}>{headerTitle}</h6>
<div>
{children || (
<motion.span
onClick={toggleFilter}
initial={{ opacity: sectionVisible ? 0.6 : 0 }}
animate={{ opacity: sectionVisible ? 0.6 : 0 }}>
<SvgIcon icon={IconEnum.search} />
</motion.span>
)}
</div>
</StyledHeader>
);
export default SidebarHeader;

View File

@ -0,0 +1,53 @@
// @flow
import * as React from 'react';
import Tooltip from '../tooltip';
import SidebarItem from './sidebar-item';
import SvgIcon, { IconEnum } from '../svg-icon';
import SidebarSection from './sidebar-section';
type Props = {
headers: Object,
};
let itemPath = [];
const handleClick = items => {
itemPath.push('header');
itemPath.push.apply(itemPath, items);
itemPath = [];
};
// Implemented as a class component because of a caveat with render props
// https://reactjs.org/docs/render-props.html#be-careful-when-using-render-props-with-reactpurecomponent
export default class SidebarHeaders extends React.Component<Props> {
renderBody = (filter: string): null | React.Node => {
const filteredValues = Object.keys(this.props.headers).filter(header =>
header.toLowerCase().includes(filter.toLocaleLowerCase()),
);
if (!filteredValues.length) {
return null;
}
return (
<div>
{filteredValues.map(header => (
<React.Fragment key={header}>
<SidebarItem>
<div>
<SvgIcon icon={IconEnum.indentation} />
</div>
<span onClick={() => handleClick([header])}>
<Tooltip message={this.props.headers[header].description} position="right">
{header}
</Tooltip>
</span>
</SidebarItem>
</React.Fragment>
))}
</div>
);
};
render() {
return <SidebarSection title="HEADERS" renderBody={this.renderBody} />;
}
}

View File

@ -0,0 +1,40 @@
// @flow
import * as React from 'react';
import SidebarPanel from './sidebar-panel';
import SidebarItem from './sidebar-item';
import SidebarTextItem from './sidebar-text-item';
type Props = {
info: Object,
childrenVisible: boolean,
};
function SidebarInfo(props: Props) {
const { title, description, version, license } = props.info;
return (
<SidebarPanel childrenVisible={props.childrenVisible}>
{title && (
<SidebarItem>
<SidebarTextItem label={'Title:'} headline={title} />
</SidebarItem>
)}
{description && (
<SidebarItem>
<SidebarTextItem label={'Description:'} headline={description} />
</SidebarItem>
)}
{version && (
<SidebarItem>
<SidebarTextItem label={'Version:'} headline={version} />
</SidebarItem>
)}
{license.name && (
<SidebarItem>
<SidebarTextItem label={'License:'} headline={license.name} />
</SidebarItem>
)}
</SidebarPanel>
);
}
export default SidebarInfo;

View File

@ -0,0 +1,84 @@
// @flow
import * as React from 'react';
import styled from 'styled-components';
type Props = {
children: React.Node,
gridLayout?: boolean,
};
const StyledBlockItem: React.ComponentType<{}> = styled.div`
padding: 0 var(--padding-md) var(--padding-sm) 0;
margin: 0;
display: block;
font-size: var(--font-size-md);
line-height: var(--font-size-sm);
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
&:hover {
background-color: var(--hl-xxs);
cursor: default;
}
&:last-child {
margin-bottom: var(--padding-md);
}
span {
margin: 0 0 0 var(--padding-sm);
}
div {
display: inline;
margin: 0;
}
div:nth-child(1) {
padding-left: var(--padding-sm);
}
div.tooltip {
padding: 0;
}
`;
const StyledGridItem: React.ComponentType<{}> = styled.li`
padding: 0 0 0 var(--padding-sm);
margin: 0;
display: grid;
grid-template-columns: 0.25fr 5fr;
column-gap: var(--padding-sm);
grid-template-rows: 1fr;
align-items: start;
white-space: nowrap;
font-size: var(--font-size-md);
line-height: var(--font-size-sm);
span {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
padding: 4px var(--padding-sm) var(--padding-xs) 0px;
}
a {
color: var(--hl-xl);
}
div:nth-child(1) {
text-align: right;
svg {
padding-left: var(--padding-sm);
}
}
&:hover {
background-color: var(--hl-xxs);
cursor: default;
}
&:last-child {
margin-bottom: var(--padding-md);
}
`;
const SidebarItem = ({ children, gridLayout }: Props) => {
if (gridLayout) {
return <StyledGridItem>{children}</StyledGridItem>;
} else {
return <StyledBlockItem>{children}</StyledBlockItem>;
}
};
export default SidebarItem;

View File

@ -0,0 +1,51 @@
// @flow
import * as React from 'react';
import styled from 'styled-components';
import { motion } from 'framer-motion';
type Props = {
children: React.Node,
childrenVisible: boolean,
};
const StyledPanel: React.ComponentType<{}> = styled(motion.div)`
height: 0;
.method {
h6 {
font-size: var(--font-size-xxs);
}
}
.method-post {
color: var(--color-success);
}
.method-get {
color: var(--color-surprise);
}
.method-delete {
color: var(--color-danger);
}
.method-parameters {
display: none;
}
.method-options-head,
.method-custom {
color: var(--color-info);
}
.method-patch {
color: var(--color-notice);
}
.method-put {
color: var(--color-warning);
}
`;
const SidebarPanel = ({ childrenVisible, children }: Props) => (
<StyledPanel
initial={{ height: childrenVisible ? '100%' : '0px' }}
animate={{ height: childrenVisible ? '100%' : '0px' }}
transition={{ duration: 0.2, ease: 'easeInOut', delay: 0 }}>
{children}
</StyledPanel>
);
export default SidebarPanel;

View File

@ -0,0 +1,54 @@
// @flow
import * as React from 'react';
import Tooltip from '../tooltip';
import SidebarItem from './sidebar-item';
import SvgIcon, { IconEnum } from '../svg-icon';
import SidebarSection from './sidebar-section';
type Props = {
parameters: Object,
};
let itemPath = [];
const handleClick = items => {
itemPath.push('parameter');
itemPath.push.apply(itemPath, items);
itemPath = [];
};
// Implemented as a class component because of a caveat with render props
// https://reactjs.org/docs/render-props.html#be-careful-when-using-render-props-with-reactpurecomponent
export default class SidebarParameters extends React.Component<Props> {
renderBody = (filter: string): null | React.Node => {
const filteredValues = Object.keys(this.props.parameters).filter(parameter =>
parameter.toLowerCase().includes(filter.toLocaleLowerCase()),
);
if (!filteredValues.length) {
return null;
}
return (
<div>
{filteredValues.map(parameter => (
<React.Fragment key={parameter}>
<SidebarItem>
<div>
<SvgIcon icon={IconEnum.indentation} />
</div>
<span onClick={() => handleClick([parameter])}>
<Tooltip message={this.props.parameters[parameter].description} position="right">
{parameter}
</Tooltip>
</span>
</SidebarItem>
</React.Fragment>
))}
</div>
);
};
render() {
return <SidebarSection title="PARAMETERS" renderBody={this.renderBody} />;
}
}

View File

@ -0,0 +1,66 @@
// @flow
import * as React from 'react';
import styled from 'styled-components';
import SidebarItem from './sidebar-item';
import SvgIcon, { IconEnum } from '../svg-icon';
import SidebarSection from './sidebar-section';
type Props = {
paths: Array<any>,
};
let itemPath = [];
const handleClick = items => {
itemPath.push('path');
itemPath.push.apply(itemPath, items);
itemPath = [];
};
const StyledMethods: React.ComponentType<{}> = styled.span`
padding-left: var(--padding-lg);
`;
// Implemented as a class component because of a caveat with render props
// https://reactjs.org/docs/render-props.html#be-careful-when-using-render-props-with-reactpurecomponent
export default class SidebarPaths extends React.Component<Props> {
renderBody = (filter: string): null | React.Node => {
const filteredValues = this.props.paths.filter(pathDetail =>
pathDetail[0].toLowerCase().includes(filter.toLocaleLowerCase()),
);
if (!filteredValues.length) {
return null;
}
return (
<div>
{filteredValues.map(([route, method]) => (
<React.Fragment key={route}>
<SidebarItem gridLayout>
<div>
<SvgIcon icon={IconEnum.indentation} />
</div>
<span onClick={() => handleClick([route])}>{route}</span>
</SidebarItem>
<SidebarItem>
<StyledMethods>
{Object.keys((method: any)).map(method => (
<span
key={method}
className={`method-${method}`}
onClick={() => handleClick([route, method])}>
{method}
</span>
))}
</StyledMethods>
</SidebarItem>
</React.Fragment>
))}
</div>
);
};
render() {
return <SidebarSection title="PATHS" renderBody={this.renderBody} />;
}
}

View File

@ -0,0 +1,88 @@
// @flow
import * as React from 'react';
import styled from 'styled-components';
import Tooltip from '../tooltip';
import SidebarItem from './sidebar-item';
import SvgIcon, { IconEnum } from '../svg-icon';
import SidebarSection from './sidebar-section';
type Props = {
requests: Object,
};
let itemPath = [];
const handleClick = items => {
itemPath.push('request');
itemPath.push.apply(itemPath, items);
itemPath = [];
};
const StyledRequestExample: React.ComponentType<{}> = styled.span`
color: var(--color-success);
&:first-of-type {
padding-left: var(--padding-lg);
}
`;
const StyledRequestFormat: React.ComponentType<{}> = styled.span`
padding-left: var(--padding-sm);
`;
// Implemented as a class component because of a caveat with render props
// https://reactjs.org/docs/render-props.html#be-careful-when-using-render-props-with-reactpurecomponent
export default class SidebarRequests extends React.Component<Props> {
renderBody = (filter: string): null | React.Node => {
const filteredValues = Object.keys(this.props.requests).filter(requestName =>
requestName.toLowerCase().includes(filter.toLocaleLowerCase()),
);
if (!filteredValues.length) {
return null;
}
return (
<div>
{filteredValues.map(requestName => {
const { description, content } = this.props.requests[requestName];
return (
<React.Fragment key={requestName}>
<SidebarItem gridLayout>
<div>
<SvgIcon icon={IconEnum.folderOpen} />
</div>
<span onClick={() => handleClick([requestName])}>
<Tooltip message={description} position="right">
{requestName}
</Tooltip>
</span>
</SidebarItem>
{Object.keys(content).map(requestFormat => (
<React.Fragment key={requestFormat}>
<SidebarItem>
<StyledRequestFormat>
<SvgIcon icon={IconEnum.indentation} />
<span onClick={() => handleClick([requestFormat])}>{requestFormat}</span>
</StyledRequestFormat>
</SidebarItem>
<SidebarItem>
{Object.keys(content[requestFormat].examples).map(requestExample => (
<StyledRequestExample
onClick={() => handleClick([requestExample])}
key={requestExample}>
{requestExample}
</StyledRequestExample>
))}
</SidebarItem>
</React.Fragment>
))}
</React.Fragment>
);
})}
</div>
);
};
render() {
return <SidebarSection title="REQUESTS" renderBody={this.renderBody} />;
}
}

View File

@ -0,0 +1,52 @@
// @flow
import * as React from 'react';
import Tooltip from '../tooltip';
import SidebarItem from './sidebar-item';
import SvgIcon, { IconEnum } from '../svg-icon';
import SidebarSection from './sidebar-section';
type Props = {
responses: Object,
};
let itemPath = [];
const handleClick = items => {
itemPath.push('response');
itemPath.push.apply(itemPath, items);
itemPath = [];
};
// Implemented as a class component because of a caveat with render props
// https://reactjs.org/docs/render-props.html#be-careful-when-using-render-props-with-reactpurecomponent
export default class SidebarResponses extends React.Component<Props> {
renderBody = (filter: string): null | React.Node => {
const filteredValues = Object.keys(this.props.responses).filter(response =>
response.toLowerCase().includes(filter.toLocaleLowerCase()),
);
if (!filteredValues.length) {
return null;
}
return (
<div>
{filteredValues.map(response => (
<SidebarItem key={response}>
<div>
<SvgIcon icon={IconEnum.indentation} />
</div>
<span onClick={() => handleClick([response])}>
<Tooltip message={this.props.responses[response].description} position="right">
{response}
</Tooltip>
</span>
</SidebarItem>
))}
</div>
);
};
render() {
return <SidebarSection title="RESPONSES" renderBody={this.renderBody} />;
}
}

View File

@ -0,0 +1,47 @@
// @flow
import * as React from 'react';
import SidebarItem from './sidebar-item';
import SvgIcon, { IconEnum } from '../svg-icon';
import SidebarSection from './sidebar-section';
type Props = {
schemas: Object,
};
let itemPath = [];
const handleClick = items => {
itemPath.push('schema');
itemPath.push.apply(itemPath, items);
itemPath = [];
};
// Implemented as a class component because of a caveat with render props
// https://reactjs.org/docs/render-props.html#be-careful-when-using-render-props-with-reactpurecomponent
export default class SidebarSchemas extends React.Component<Props> {
renderBody = (filter: string): null | React.Node => {
const filteredValues = Object.keys(this.props.schemas).filter(schema =>
schema.toLowerCase().includes(filter.toLocaleLowerCase()),
);
if (!filteredValues.length) {
return null;
}
return (
<div>
{filteredValues.map(schema => (
<SidebarItem key={schema}>
<div>
<SvgIcon icon={IconEnum.brackets} />
</div>
<span onClick={() => handleClick([schema])}>{schema}</span>
</SidebarItem>
))}
</div>
);
};
render() {
return <SidebarSection title="SCHEMAS" renderBody={this.renderBody} />;
}
}

View File

@ -0,0 +1,59 @@
// @flow
import * as React from 'react';
import { useLayoutEffect } from 'react';
import SidebarHeader from './sidebar-header';
import SidebarPanel from './sidebar-panel';
import SidebarFilter from './sidebar-filter';
import styled from 'styled-components';
import { motion } from 'framer-motion';
import { useToggle } from 'react-use';
type SectionProps = {
title: string,
renderBody: (filterValue: string) => React.Node,
};
const StyledSection: React.ComponentType<{}> = styled(motion.ul)`
overflow: hidden;
box-sizing: border-box;
border-bottom: 1px solid var(--hl-md);
`;
const StyledNoResults: React.ComponentType<{}> = styled.div`
padding: var(--padding-xs) var(--padding-xs) var(--padding-md) var(--padding-md);
color: var(--color-warning);
`;
const SidebarSection = ({ title, renderBody }: SectionProps) => {
const [bodyVisible, toggleBodyVisible] = useToggle(false);
const [filterVisible, toggleFilterVisible] = useToggle(false);
const [filterValue, setFilterValue] = React.useState('');
const handleFilterChange = React.useCallback((e: SyntheticInputEvent<HTMLInputElement>) => {
setFilterValue(e.target.value);
}, []);
useLayoutEffect(() => {
toggleFilterVisible(false);
setFilterValue('');
}, [bodyVisible, toggleFilterVisible]);
return (
<StyledSection>
<SidebarHeader
headerTitle={title}
sectionVisible={bodyVisible}
toggleSection={toggleBodyVisible}
toggleFilter={toggleFilterVisible}
/>
<SidebarPanel childrenVisible={bodyVisible}>
<SidebarFilter filter={filterVisible} onChange={handleFilterChange} />
{renderBody(filterValue) || (
<StyledNoResults>No results found for "{filterValue}"...</StyledNoResults>
)}
</SidebarPanel>
</StyledSection>
);
};
export default SidebarSection;

View File

@ -0,0 +1,48 @@
// @flow
import * as React from 'react';
import SidebarItem from './sidebar-item';
import SvgIcon, { IconEnum } from '../svg-icon';
import SidebarSection from './sidebar-section';
type Props = {
security: Object,
};
let itemPath = [];
const handleClick = items => {
itemPath.push('security');
itemPath.push.apply(itemPath, items);
itemPath = [];
};
// Implemented as a class component because of a caveat with render props
// https://reactjs.org/docs/render-props.html#be-careful-when-using-render-props-with-reactpurecomponent
export default class SidebarSecurity extends React.Component<Props> {
renderBody = (filter: string): null | React.Node => {
const filteredValues = Object.keys(this.props.security).filter(scheme =>
scheme.toLowerCase().includes(filter.toLocaleLowerCase()),
);
if (!filteredValues.length) {
return null;
}
return (
<div>
{filteredValues.map(scheme => (
<React.Fragment key={scheme}>
<SidebarItem>
<div>
<SvgIcon icon={IconEnum.key} />
</div>
<span onClick={() => handleClick([scheme])}>{scheme}</span>
</SidebarItem>
</React.Fragment>
))}
</div>
);
};
render() {
return <SidebarSection title="SECURITY" renderBody={this.renderBody} />;
}
}

View File

@ -0,0 +1,48 @@
// @flow
import * as React from 'react';
import SidebarItem from './sidebar-item';
import SvgIcon, { IconEnum } from '../svg-icon';
import SidebarSection from './sidebar-section';
type Props = {
servers: Array<any>,
};
let itemPath = [];
const handleClick = items => {
itemPath.push('server');
itemPath.push.apply(itemPath, items);
itemPath = [];
};
// Implemented as a class component because of a caveat with render props
// https://reactjs.org/docs/render-props.html#be-careful-when-using-render-props-with-reactpurecomponent
export default class SidebarServers extends React.Component<Props> {
renderBody = (filter: string): null | React.Node => {
const filteredValues = this.props.servers.filter(server =>
server.url.includes(filter.toLocaleLowerCase()),
);
if (!filteredValues.length) {
return null;
}
return (
<div>
{filteredValues.map(server => (
<React.Fragment key={server.url}>
<SidebarItem>
<div>
<SvgIcon icon={IconEnum.indentation} />
</div>
<span onClick={() => handleClick([server.url])}>{server.url}</span>
</SidebarItem>
</React.Fragment>
))}
</div>
);
};
render() {
return <SidebarSection title="SERVERS" renderBody={this.renderBody} />;
}
}

View File

@ -0,0 +1,32 @@
// @flow
import * as React from 'react';
import styled from 'styled-components';
type Props = {
label: string,
headline: string,
};
const StyledTextItem: React.ComponentType<{}> = styled.span`
display: block;
padding-left: var(--padding-sm);
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
`;
let itemPath = [];
const handleClick = items => {
itemPath.push('info');
itemPath.push.apply(itemPath, items);
itemPath = [];
};
const SidebarTextItem = ({ label, headline }: Props) => (
<StyledTextItem>
<strong>{label}</strong>
<span onClick={() => handleClick([headline])}>{headline}</span>
</StyledTextItem>
);
export default SidebarTextItem;

File diff suppressed because it is too large Load Diff

View File

@ -43,6 +43,8 @@ import MemoSvgIcnUser from '../assets/svgr/IcnUser';
import MemoSvgIcnWarningCircle from '../assets/svgr/IcnWarningCircle';
import MemoSvgIcnX from '../assets/svgr/IcnX';
import MemoSvgIcnInfo from '../assets/svgr/IcnInfo';
import MemoSvgIcnKey from '../assets/svgr/IcnKey';
import MemoSvgIcnBrackets from '../assets/svgr/IcnBrackets';
export const ThemeEnum = {
default: 'default',
@ -101,6 +103,8 @@ export const IconEnum = {
user: 'user',
warningCircle: 'warning-circle',
x: 'x',
key: 'key',
brackets: 'brackets',
// Blank icon
empty: 'empty',
@ -190,6 +194,8 @@ class SvgIcon extends React.Component<Props> {
[IconEnum.user]: [ThemeEnum.default, MemoSvgIcnUser],
[IconEnum.warningCircle]: [ThemeEnum.default, MemoSvgIcnWarningCircle],
[IconEnum.x]: [ThemeEnum.default, MemoSvgIcnX],
[IconEnum.key]: [ThemeEnum.default, MemoSvgIcnKey],
[IconEnum.brackets]: [ThemeEnum.default, MemoSvgIcnBrackets],
};
render() {

View File

@ -0,0 +1,7 @@
// @flow
import * as React from 'react';
declare module 'react-use' {
declare module.exports: *;
}

View File

@ -9,9 +9,9 @@ import _GravatarImg from './components/gravatar-img';
import _Header from './components/header';
import _MultiSwitch from './components/multi-switch';
import _NoticeTable from './components/notice-table';
import _RadioButtonGroup from './components/radio-button-group';
import _Sidebar from './components/sidebar';
import _SvgIcon from './components/svg-icon';
import _Sidebar from './components/sidebar/';
import _RadioButtonGroup from './components/radio-button-group';
import _Switch from './components/switch';
import _ToggleSwitch from './components/toggle-switch';
import * as table from './components/table';

View File

@ -2848,6 +2848,12 @@
"integrity": "sha512-iTs9HReBu7evG77Q4EC8hZnqRt57irBDkK9nvmHroiOIVwYMQc4IvYvdRgwKfYepunIY7Oh/dBuuld+Gj9uo6w==",
"dev": true
},
"@types/js-cookie": {
"version": "2.2.6",
"resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.6.tgz",
"integrity": "sha512-+oY0FDTO2GYKEV0YPvSshGq9t7YozVkgvXLty7zogQNuCxBhT9/3INX9Q7H1aRZ4SUDRXAKlJuA4EA5nTt7SNw==",
"dev": true
},
"@types/npmlog": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/@types/npmlog/-/npmlog-4.1.2.tgz",
@ -3100,6 +3106,12 @@
"@xtuc/long": "4.2.2"
}
},
"@xobotyi/scrollbar-width": {
"version": "1.9.5",
"resolved": "https://registry.npmjs.org/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz",
"integrity": "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==",
"dev": true
},
"@xtuc/ieee754": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
@ -4206,6 +4218,12 @@
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
"dev": true
},
"bowser": {
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/bowser/-/bowser-1.9.4.tgz",
"integrity": "sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==",
"dev": true
},
"boxen": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz",
@ -5263,6 +5281,24 @@
"resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
"integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU="
},
"css-in-js-utils": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz",
"integrity": "sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA==",
"dev": true,
"requires": {
"hyphenate-style-name": "^1.0.2",
"isobject": "^3.0.1"
},
"dependencies": {
"isobject": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
"dev": true
}
}
},
"css-loader": {
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.4.2.tgz",
@ -5866,6 +5902,15 @@
"is-arrayish": "^0.2.1"
}
},
"error-stack-parser": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.6.tgz",
"integrity": "sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ==",
"dev": true,
"requires": {
"stackframe": "^1.1.1"
}
},
"es-abstract": {
"version": "1.17.0",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.0.tgz",
@ -6313,6 +6358,18 @@
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
"dev": true
},
"fast-shallow-equal": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz",
"integrity": "sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==",
"dev": true
},
"fastest-stable-stringify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-1.0.1.tgz",
"integrity": "sha1-kSLUBtTJ2YvqZEpraFPVh0uHsCg=",
"dev": true
},
"fault": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz",
@ -7808,6 +7865,12 @@
"integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
"dev": true
},
"hyphenate-style-name": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz",
"integrity": "sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ==",
"dev": true
},
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@ -7950,6 +8013,16 @@
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
"dev": true
},
"inline-style-prefixer": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-4.0.2.tgz",
"integrity": "sha512-N8nVhwfYga9MiV9jWlwfdj1UDIaZlBFu4cJSJkIr7tZX7sHpHhGR5su1qdpW+7KPL8ISTvCIkcaFi/JdBknvPg==",
"dev": true,
"requires": {
"bowser": "^1.7.3",
"css-in-js-utils": "^2.0.0"
}
},
"inquirer": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.4.tgz",
@ -8458,6 +8531,12 @@
}
}
},
"js-cookie": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz",
"integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==",
"dev": true
},
"js-levenshtein": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz",
@ -9189,6 +9268,30 @@
"dev": true,
"optional": true
},
"nano-css": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/nano-css/-/nano-css-5.3.0.tgz",
"integrity": "sha512-uM/9NGK9/E9/sTpbIZ/bQ9xOLOIHZwrrb/CRlbDHBU/GFS7Gshl24v/WJhwsVViWkpOXUmiZ66XO7fSB4Wd92Q==",
"dev": true,
"requires": {
"css-tree": "^1.0.0-alpha.28",
"csstype": "^2.5.5",
"fastest-stable-stringify": "^1.0.1",
"inline-style-prefixer": "^4.0.0",
"rtl-css-js": "^1.9.0",
"sourcemap-codec": "^1.4.1",
"stacktrace-js": "^2.0.0",
"stylis": "3.5.0"
},
"dependencies": {
"stylis": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.0.tgz",
"integrity": "sha512-pP7yXN6dwMzAR29Q0mBrabPCe0/mNO1MSr93bhay+hcZondvMMTpeGyd8nbhYJdyperNT2DRxONQuUGcJr5iPw==",
"dev": true
}
}
},
"nanomatch": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
@ -10871,6 +10974,48 @@
"react-lifecycles-compat": "^3.0.4"
}
},
"react-universal-interface": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz",
"integrity": "sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==",
"dev": true
},
"react-use": {
"version": "15.3.2",
"resolved": "https://registry.npmjs.org/react-use/-/react-use-15.3.2.tgz",
"integrity": "sha512-DAbc+pVedZC4P5rLBKdIvTTB03+4T/pR6jZ2pKQPgqfq4UC1Oymmbehon5z8XXSUgZs0tgIvbBzVEdiWMS9k+g==",
"dev": true,
"requires": {
"@types/js-cookie": "2.2.6",
"@xobotyi/scrollbar-width": "1.9.5",
"copy-to-clipboard": "^3.2.0",
"fast-deep-equal": "^3.1.3",
"fast-shallow-equal": "^1.0.0",
"js-cookie": "^2.2.1",
"nano-css": "^5.2.1",
"react-universal-interface": "^0.6.2",
"resize-observer-polyfill": "^1.5.1",
"screenfull": "^5.0.0",
"set-harmonic-interval": "^1.0.1",
"throttle-debounce": "^2.1.0",
"ts-easing": "^0.2.0",
"tslib": "^2.0.0"
},
"dependencies": {
"fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true
},
"tslib": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.0.tgz",
"integrity": "sha512-lTqkx847PI7xEDYJntxZH89L2/aXInsyF2luSafe/+0fHOMjlBNXdH6th7f70qxLDhul7KZK0zC8V5ZIyHl0/g==",
"dev": true
}
}
},
"reactcss": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz",
@ -11245,6 +11390,15 @@
"inherits": "^2.0.1"
}
},
"rtl-css-js": {
"version": "1.14.0",
"resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.14.0.tgz",
"integrity": "sha512-Dl5xDTeN3e7scU1cWX8c9b6/Nqz3u/HgR4gePc1kWXYiQWVQbKCEyK6+Hxve9LbcJ5EieHy1J9nJCN3grTtGwg==",
"dev": true,
"requires": {
"@babel/runtime": "^7.1.2"
}
},
"run-async": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
@ -11320,6 +11474,12 @@
"ajv-keywords": "^3.1.0"
}
},
"screenfull": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/screenfull/-/screenfull-5.0.2.tgz",
"integrity": "sha512-cCF2b+L/mnEiORLN5xSAz6H3t18i2oHh9BA8+CQlAh5DRw2+NFAGQJOSYbcGw8B2k04g/lVvFcfZ83b3ysH5UQ==",
"dev": true
},
"select": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
@ -11430,6 +11590,12 @@
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
"dev": true
},
"set-harmonic-interval": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz",
"integrity": "sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==",
"dev": true
},
"set-value": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
@ -11827,6 +11993,12 @@
"integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
"dev": true
},
"sourcemap-codec": {
"version": "1.4.8",
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
"dev": true
},
"space-separated-tokens": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz",
@ -11863,6 +12035,50 @@
"integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==",
"dev": true
},
"stack-generator": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.5.tgz",
"integrity": "sha512-/t1ebrbHkrLrDuNMdeAcsvynWgoH/i4o8EGGfX7dEYDoTXOYVAkEpFdtshlvabzc6JlJ8Kf9YdFEoz7JkzGN9Q==",
"dev": true,
"requires": {
"stackframe": "^1.1.1"
}
},
"stackframe": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.0.tgz",
"integrity": "sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA==",
"dev": true
},
"stacktrace-gps": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/stacktrace-gps/-/stacktrace-gps-3.0.4.tgz",
"integrity": "sha512-qIr8x41yZVSldqdqe6jciXEaSCKw1U8XTXpjDuy0ki/apyTn/r3w9hDAAQOhZdxvsC93H+WwwEu5cq5VemzYeg==",
"dev": true,
"requires": {
"source-map": "0.5.6",
"stackframe": "^1.1.1"
},
"dependencies": {
"source-map": {
"version": "0.5.6",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
"integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=",
"dev": true
}
}
},
"stacktrace-js": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.2.tgz",
"integrity": "sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==",
"dev": true,
"requires": {
"error-stack-parser": "^2.0.6",
"stack-generator": "^2.0.5",
"stacktrace-gps": "^3.0.4"
}
},
"static-extend": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
@ -12453,6 +12669,12 @@
"integrity": "sha512-UGTRZu1evMw4uTPyYF66/KFd22XiU+jMaIuHrkIHQ2GivAXVlLV0v/vHrpOuTRf9BmpNHi/SO7Vd0rLu0y57jg==",
"dev": true
},
"ts-easing": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/ts-easing/-/ts-easing-0.2.0.tgz",
"integrity": "sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==",
"dev": true
},
"ts-pnp": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.1.5.tgz",

View File

@ -28,6 +28,7 @@
"babel-plugin-inline-react-svg": "^1.1.1",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-use": "^15.3.2",
"storybook-addon-designs": "^5.2.0",
"webpack": "^4.42.1",
"webpack-cli": "^3.3.11",