diff --git a/packages/insomnia-app/.storybook/preview-head.html b/packages/insomnia-app/.storybook/preview-head.html index 2ec429a1175..97d7de2f75c 100644 --- a/packages/insomnia-app/.storybook/preview-head.html +++ b/packages/insomnia-app/.storybook/preview-head.html @@ -3,3 +3,735 @@ document.body.setAttribute('theme', 'default'); }; + + + + + + + + + diff --git a/packages/insomnia-app/app/ui/css/layout/base.less b/packages/insomnia-app/app/ui/css/layout/base.less index 958de770049..e6e016d3728 100644 --- a/packages/insomnia-app/app/ui/css/layout/base.less +++ b/packages/insomnia-app/app/ui/css/layout/base.less @@ -27,16 +27,50 @@ body { padding: 0; } +h1, +h2, +h3, +h4, +h5, +h6 { + line-height: var(--font-line-height-md); +} + h1 { - font-size: var(--font-size-xxl); + font-size: var(--font-size-xxxl); + font-weight: var(--font-weight-regular); } h2 { - font-size: var(--font-size-xl); + font-size: var(--font-size-xxl); + font-weight: var(--font-weight-regular); } h3 { + font-size: var(--font-size-xl); + font-weight: var(--font-weight-medium); +} + +h4 { font-size: var(--font-size-lg); + font-weight: var(--font-weight-medium); +} + +h5 { + font-size: var(--font-size-md); + font-weight: var(--font-weight-medium); +} + +h6 { + font-size: var(--font-size-xs); + font-weight: var(--font-weight-bold); + text-transform: uppercase; +} + +p { + font-size: var(--font-size-md); + font-weight: var(--font-weight-regular); + line-height: var(--font-line-height-lg); } p, @@ -68,10 +102,6 @@ label { padding-top: var(--padding-xs); } -p { - line-height: 1.7em; -} - ul.ul--pretty { list-style: disc; padding-left: var(--padding-lg); diff --git a/packages/insomnia-components/.storybook/main.js b/packages/insomnia-components/.storybook/main.js index 74322dc6c92..32ae9fbf70f 100644 --- a/packages/insomnia-components/.storybook/main.js +++ b/packages/insomnia-components/.storybook/main.js @@ -2,5 +2,6 @@ module.exports = { addons: [ '@storybook/addon-knobs/register', '@storybook/addon-contexts/register', - ] + 'storybook-addon-designs/register', + ], }; diff --git a/packages/insomnia-components/.storybook/preview-head.html b/packages/insomnia-components/.storybook/preview-head.html index c13d6490f99..0c3dca1cfd4 100644 --- a/packages/insomnia-components/.storybook/preview-head.html +++ b/packages/insomnia-components/.storybook/preview-head.html @@ -132,9 +132,9 @@ @@ -179,16 +180,44 @@ - + [theme='studio-light'] .theme--dropdown__menu, + [subtheme='studio-light'] .theme--dropdown__menu--sub { + /* Background */ + --color-info: rgb(0, 91, 158); + --color-info-rgb: 0, 91, 158; + } + + [theme='studio-light'] .theme--tooltip, + [subtheme='studio-light'] .theme--tooltip--sub { + /* Background */ + --color-info: rgb(0, 91, 158); + --color-info-rgb: 0, 91, 158; + } + + [theme='studio-light'] .theme--transparent-overlay, + [subtheme='studio-light'] .theme--transparent-overlay--sub { + /* Background */ + --color-bg: rgba(230, 240, 250, 0.8); + --color-bg-rgb: 230, 240, 250, 0.8; + + /* Foreground */ + --color-font: rgb(85, 85, 85); + --color-font-rgb: 85, 85, 85; + } + + [theme='studio-light'] .theme--dialog, + [subtheme='studio-light'] .theme--dialog--sub { + /* Background */ + --color-info: rgb(0, 91, 158); + --color-info-rgb: 0, 91, 158; + } + + [theme='studio-light'] .theme--sidebar, + [subtheme='studio-light'] .theme--sidebar--sub { + /* Background */ + --color-bg: rgb(247, 250, 252); + --color-bg-rgb: 247, 250, 252; + --color-success: rgb(80, 161, 79); + --color-success-rgb: 80, 161, 79; + --color-notice: rgb(193, 132, 1); + --color-notice-rgb: 193, 132, 1; + --color-warning: rgb(193, 132, 1); + --color-warning-rgb: 193, 132, 1; + --color-danger: rgb(228, 86, 73); + --color-danger-rgb: 228, 86, 73; + --color-surprise: rgb(166, 38, 164); + --color-surprise-rgb: 166, 38, 164; + --color-info: rgb(1, 132, 188); + --color-info-rgb: 1, 132, 188; + + /* Foreground */ + --color-font: rgb(68, 68, 68); + --color-font-rgb: 68, 68, 68; + + /* Highlight */ + } + + [theme='studio-light'] .theme--link, + [subtheme='studio-light'] .theme--link--sub { + /* Foreground */ + --color-font: rgb(104, 169, 162); + --color-font-rgb: 104, 169, 162; + } + + [theme='studio-light'] .theme--editor, + [subtheme='studio-light'] .theme--editor--sub { + /* Background */ + --color-surprise: rgb(0, 48, 82); + --color-surprise-rgb: 0, 48, 82; + --color-info: rgb(132, 103, 195); + --color-info-rgb: 132, 103, 195; + } + + [theme='studio-light'] .CodeMirror-info, + [subtheme='studio-light'] .CodeMirror-info--sub { + /* Background */ + --color-info: rgb(0, 91, 158); + --color-info-rgb: 0, 91, 158; + } + + [theme='studio-light'] .theme--activity-bar, + [subtheme='studio-light'] .theme--activity-bar--sub { + /* Background */ + --color-bg: rgb(0, 48, 82); + --color-bg-rgb: 0, 48, 82; + + /* Foreground */ + --color-font: rgb(255, 255, 255); + --color-font-rgb: 255, 255, 255; + + /* Highlight */ + --hl: rgb(23, 130, 207); + --hl-rgb: 23, 130, 207; + --hl-xxs: rgba(23, 130, 207, 0.05); + --hl-xxs-rgb: 23, 130, 207, 0.05; + --hl-xs: rgba(23, 130, 207, 0.1); + --hl-xs-rgb: 23, 130, 207, 0.1; + --hl-sm: rgba(23, 130, 207, 0.2); + --hl-sm-rgb: 23, 130, 207, 0.2; + --hl-md: rgba(23, 130, 207, 0.3); + --hl-md-rgb: 23, 130, 207, 0.3; + --hl-lg: rgba(23, 130, 207, 0.5); + --hl-lg-rgb: 23, 130, 207, 0.5; + --hl-xl: rgba(23, 130, 207, 0.8); + --hl-xl-rgb: 23, 130, 207, 0.8; + } + + [theme='studio-light'] .theme--dropdown__menu, + [subtheme='studio-light'] .theme--dropdown__menu--sub { + /* Background */ + --color-info: rgb(0, 91, 158); + --color-info-rgb: 0, 91, 158; + } + + [theme='studio-light'] .theme--tooltip, + [subtheme='studio-light'] .theme--tooltip--sub { + /* Background */ + --color-info: rgb(0, 91, 158); + --color-info-rgb: 0, 91, 158; + } + + [theme='studio-light'] .theme--transparent-overlay, + [subtheme='studio-light'] .theme--transparent-overlay--sub { + /* Background */ + --color-bg: rgba(230, 240, 250, 0.8); + --color-bg-rgb: 230, 240, 250, 0.8; + + /* Foreground */ + --color-font: rgb(85, 85, 85); + --color-font-rgb: 85, 85, 85; + } + + [theme='studio-light'] .theme--dialog, + [subtheme='studio-light'] .theme--dialog--sub { + /* Background */ + --color-info: rgb(0, 91, 158); + --color-info-rgb: 0, 91, 158; + } + + [theme='studio-light'] .theme--sidebar, + [subtheme='studio-light'] .theme--sidebar--sub { + /* Background */ + --color-bg: rgb(247, 250, 252); + --color-bg-rgb: 247, 250, 252; + --color-success: rgb(80, 161, 79); + --color-success-rgb: 80, 161, 79; + --color-notice: rgb(193, 132, 1); + --color-notice-rgb: 193, 132, 1; + --color-warning: rgb(193, 132, 1); + --color-warning-rgb: 193, 132, 1; + --color-danger: rgb(228, 86, 73); + --color-danger-rgb: 228, 86, 73; + --color-surprise: rgb(166, 38, 164); + --color-surprise-rgb: 166, 38, 164; + --color-info: rgb(1, 132, 188); + --color-info-rgb: 1, 132, 188; + + /* Foreground */ + --color-font: rgb(68, 68, 68); + --color-font-rgb: 68, 68, 68; + + /* Highlight */ + } - diff --git a/packages/insomnia-components/assets/icn-bitbucket-logo.svg b/packages/insomnia-components/assets/icn-bitbucket-logo.svg new file mode 100644 index 00000000000..d9998c6f4a4 --- /dev/null +++ b/packages/insomnia-components/assets/icn-bitbucket-logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/assets/icn-burger-menu.svg b/packages/insomnia-components/assets/icn-burger-menu.svg new file mode 100644 index 00000000000..583af7a86d9 --- /dev/null +++ b/packages/insomnia-components/assets/icn-burger-menu.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/assets/icn-checkmark.svg b/packages/insomnia-components/assets/icn-checkmark.svg new file mode 100644 index 00000000000..3fea7d39b93 --- /dev/null +++ b/packages/insomnia-components/assets/icn-checkmark.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/assets/icn-cookie.svg b/packages/insomnia-components/assets/icn-cookie.svg new file mode 100644 index 00000000000..b9c34863c0b --- /dev/null +++ b/packages/insomnia-components/assets/icn-cookie.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/assets/icn-drag-grip.svg b/packages/insomnia-components/assets/icn-drag-grip.svg new file mode 100644 index 00000000000..5da53c9ba9e --- /dev/null +++ b/packages/insomnia-components/assets/icn-drag-grip.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/assets/icn-elevator.svg b/packages/insomnia-components/assets/icn-elevator.svg new file mode 100644 index 00000000000..aa1a7d7c124 --- /dev/null +++ b/packages/insomnia-components/assets/icn-elevator.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/insomnia-components/assets/icn-ellipsis-circle.svg b/packages/insomnia-components/assets/icn-ellipsis-circle.svg new file mode 100644 index 00000000000..b47111da2a8 --- /dev/null +++ b/packages/insomnia-components/assets/icn-ellipsis-circle.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/packages/insomnia-components/assets/icn-file.svg b/packages/insomnia-components/assets/icn-file.svg new file mode 100644 index 00000000000..1345e3e27e3 --- /dev/null +++ b/packages/insomnia-components/assets/icn-file.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/assets/icn-folder-open.svg b/packages/insomnia-components/assets/icn-folder-open.svg new file mode 100644 index 00000000000..53e2c090b3b --- /dev/null +++ b/packages/insomnia-components/assets/icn-folder-open.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/assets/icn-folder.svg b/packages/insomnia-components/assets/icn-folder.svg new file mode 100644 index 00000000000..9c331851aaa --- /dev/null +++ b/packages/insomnia-components/assets/icn-folder.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/assets/icn-gear.svg b/packages/insomnia-components/assets/icn-gear.svg new file mode 100644 index 00000000000..07f7833371e --- /dev/null +++ b/packages/insomnia-components/assets/icn-gear.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/assets/icn-gitlab-logo.svg b/packages/insomnia-components/assets/icn-gitlab-logo.svg new file mode 100644 index 00000000000..fbaf3e2e162 --- /dev/null +++ b/packages/insomnia-components/assets/icn-gitlab-logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/assets/icn-gui.svg b/packages/insomnia-components/assets/icn-gui.svg new file mode 100644 index 00000000000..0ad7dfdf31f --- /dev/null +++ b/packages/insomnia-components/assets/icn-gui.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/assets/icn-indentation.svg b/packages/insomnia-components/assets/icn-indentation.svg new file mode 100644 index 00000000000..463affc2e8b --- /dev/null +++ b/packages/insomnia-components/assets/icn-indentation.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/assets/icn-minus-circle-fill.svg b/packages/insomnia-components/assets/icn-minus-circle-fill.svg new file mode 100644 index 00000000000..ec4e1ff3738 --- /dev/null +++ b/packages/insomnia-components/assets/icn-minus-circle-fill.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/assets/icn-minus-circle.svg b/packages/insomnia-components/assets/icn-minus-circle.svg new file mode 100644 index 00000000000..828cd8ff446 --- /dev/null +++ b/packages/insomnia-components/assets/icn-minus-circle.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/assets/icn-placeholder.svg b/packages/insomnia-components/assets/icn-placeholder.svg new file mode 100644 index 00000000000..e4b719f3d1c --- /dev/null +++ b/packages/insomnia-components/assets/icn-placeholder.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/packages/insomnia-components/assets/icn-play.svg b/packages/insomnia-components/assets/icn-play.svg new file mode 100644 index 00000000000..6361e3afef4 --- /dev/null +++ b/packages/insomnia-components/assets/icn-play.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/assets/icn-plus.svg b/packages/insomnia-components/assets/icn-plus.svg new file mode 100644 index 00000000000..7c965470e0c --- /dev/null +++ b/packages/insomnia-components/assets/icn-plus.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/assets/icn-prohibited.svg b/packages/insomnia-components/assets/icn-prohibited.svg new file mode 100644 index 00000000000..e870f28b62a --- /dev/null +++ b/packages/insomnia-components/assets/icn-prohibited.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/assets/icn-question-fill.svg b/packages/insomnia-components/assets/icn-question-fill.svg new file mode 100644 index 00000000000..23d9857c201 --- /dev/null +++ b/packages/insomnia-components/assets/icn-question-fill.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/assets/icn-question.svg b/packages/insomnia-components/assets/icn-question.svg new file mode 100644 index 00000000000..4bc68e227a3 --- /dev/null +++ b/packages/insomnia-components/assets/icn-question.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/packages/insomnia-components/assets/icn-search.svg b/packages/insomnia-components/assets/icn-search.svg index a3883ba4022..5ba3378a493 100644 --- a/packages/insomnia-components/assets/icn-search.svg +++ b/packages/insomnia-components/assets/icn-search.svg @@ -1,4 +1,4 @@ - + diff --git a/packages/insomnia-components/assets/icn-sec-cert.svg b/packages/insomnia-components/assets/icn-sec-cert.svg new file mode 100644 index 00000000000..73e7b9be411 --- /dev/null +++ b/packages/insomnia-components/assets/icn-sec-cert.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/assets/icn-sync.svg b/packages/insomnia-components/assets/icn-sync.svg new file mode 100644 index 00000000000..c49ff7fa55e --- /dev/null +++ b/packages/insomnia-components/assets/icn-sync.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/insomnia-components/assets/icn-trashcan.svg b/packages/insomnia-components/assets/icn-trashcan.svg new file mode 100644 index 00000000000..9addd1d9c29 --- /dev/null +++ b/packages/insomnia-components/assets/icn-trashcan.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/assets/icn-triangle.svg b/packages/insomnia-components/assets/icn-triangle.svg new file mode 100644 index 00000000000..0bcac6200c2 --- /dev/null +++ b/packages/insomnia-components/assets/icn-triangle.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/assets/icn-user.svg b/packages/insomnia-components/assets/icn-user.svg new file mode 100644 index 00000000000..3a382f9c84b --- /dev/null +++ b/packages/insomnia-components/assets/icn-user.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/assets/icn-warning-circle.svg b/packages/insomnia-components/assets/icn-warning-circle.svg new file mode 100644 index 00000000000..a757d679f00 --- /dev/null +++ b/packages/insomnia-components/assets/icn-warning-circle.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/assets/icn-x.svg b/packages/insomnia-components/assets/icn-x.svg new file mode 100644 index 00000000000..67a04cf01d2 --- /dev/null +++ b/packages/insomnia-components/assets/icn-x.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/insomnia-components/components/breadcrumb.stories.js b/packages/insomnia-components/components/breadcrumb.stories.js index affc1619380..78f1e7ee62b 100644 --- a/packages/insomnia-components/components/breadcrumb.stories.js +++ b/packages/insomnia-components/components/breadcrumb.stories.js @@ -1,6 +1,8 @@ import React from 'react'; import Breadcrumb from './breadcrumb'; -export default { title: 'Breadcrumb' }; +export default { title: '1st Party | Breadcrumb' }; -export const _default = () => ; +export const _default = () => ( + +); diff --git a/packages/insomnia-components/components/button.stories.js b/packages/insomnia-components/components/button.stories.js index d32b887692b..f32d48f9c99 100644 --- a/packages/insomnia-components/components/button.stories.js +++ b/packages/insomnia-components/components/button.stories.js @@ -6,7 +6,7 @@ import styled from 'styled-components'; import SvgIcon, { IconEnum } from './svg-icon'; export default { - title: 'Button', + title: '1st Party | Button', decorators: [withKnobs], }; @@ -90,7 +90,9 @@ export const reference = () => ( {['default', 'small'].map(s => ( -

size={s}

+

+ size={s} +

- )}> + ( + + )}> Awesome Dropdown - }> - Check Time - + }>Check Time } right="CTRL+A"> Create Branch } disabled> Disabled Action - }> - Other Action - + }>Other Action - }> - Don't Do it! - + }>Don't Do it! ); export const rightAlign = () => ( - ( - - )}> + ( + + )}> Item 1 Item 2 Item 3 @@ -57,11 +54,13 @@ export const manyItems = () => { } return ( - ( - - )}> + ( + + )}> {items} ); diff --git a/packages/insomnia-components/components/gravatar-img.stories.js b/packages/insomnia-components/components/gravatar-img.stories.js index 81328147199..b3a4e36bcff 100644 --- a/packages/insomnia-components/components/gravatar-img.stories.js +++ b/packages/insomnia-components/components/gravatar-img.stories.js @@ -1,7 +1,7 @@ import React from 'react'; import GravatarImg from './gravatar-img'; -export default { title: 'Gravatar Image' }; +export default { title: '1st Party | Gravatar' }; export const _default = () => ; diff --git a/packages/insomnia-components/components/header.stories.js b/packages/insomnia-components/components/header.stories.js index e4d9662e82c..bbec4d4262e 100644 --- a/packages/insomnia-components/components/header.stories.js +++ b/packages/insomnia-components/components/header.stories.js @@ -4,29 +4,28 @@ import GravatarImg from './gravatar-img'; import Breadcrumb from './breadcrumb'; import Switch from './switch'; -export default { title: 'Header' }; +export default { title: '1st Party | Header' }; export const _default = () =>
; -export const _primary = () => -
- - - - )} - gridCenter={( - - )} - gridRight={( - -
right
-
- )} - />; +export const _primary = () => ( +
+ + + + } + gridCenter={} + gridRight={ + +
right
+
+ } + /> +); diff --git a/packages/insomnia-components/components/notice-table.stories.js b/packages/insomnia-components/components/notice-table.stories.js index 1bd3913351d..8758cb57952 100644 --- a/packages/insomnia-components/components/notice-table.stories.js +++ b/packages/insomnia-components/components/notice-table.stories.js @@ -2,7 +2,7 @@ import * as React from 'react'; import NoticeTable from './notice-table'; -export default { title: 'NoticeTable' }; +export default { title: '1st Party | NoticeTable' }; const notices = [ { type: 'error', line: 3, message: 'This must be fixed now!' }, @@ -10,15 +10,15 @@ const notices = [ { type: 'warning', line: 40, - message: 'Another small warning because you didn\'t the right thing', + message: "Another small warning because you didn't the right thing", }, { type: 'error', line: 3212, message: 'This is a really, really, really, long error message and I hope it makes sense ' + - 'because it\'s just made up of random thoughts and things. But, don\'t let that fool you ' + - 'it\'s really important and you should fix it as soon as possible!', + "because it's just made up of random thoughts and things. But, don't let that fool you " + + "it's really important and you should fix it as soon as possible!", }, ]; diff --git a/packages/insomnia-components/components/radio-button-group.stories.js b/packages/insomnia-components/components/radio-button-group.stories.js index 3690c60610f..ecfce92875d 100644 --- a/packages/insomnia-components/components/radio-button-group.stories.js +++ b/packages/insomnia-components/components/radio-button-group.stories.js @@ -3,11 +3,40 @@ import * as React from 'react'; import RadioButtonGroup from './radio-button-group'; -export default { title: 'Radio Button Group' }; +export default { title: '1st Party | Radio Button Group' }; -export const _default = () => - - - - -; +export const _default = () => ( + + + + + + +); diff --git a/packages/insomnia-components/components/sidebar.js b/packages/insomnia-components/components/sidebar.js new file mode 100644 index 00000000000..bbd682ae5e8 --- /dev/null +++ b/packages/insomnia-components/components/sidebar.js @@ -0,0 +1,345 @@ +// @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 ( + + + +
INFO
+
+
+ + + +
SERVERS
+
+ + + + + + + + + + + +
+
+ + + + + + +
+ +
+
development.konghq.com
+
+ +
+ +
+
staging.konghq.com
+
+ +
+ +
+
production.konghq.com
+
+
+
+ + + +
PATHS
+
+ + + + + + + + + + + +
+
+ + + + + +
+ +
+
pet
+
+ +
+
POST
+

/store/inventory/(orderId)

+
+ +
+
GET
+

/store/inventory/(orderId)

+
+ +
+
PUT
+

/store/inventory/(orderId)

+
+ +
+
DEL
+

/store/inventory/(orderId)

+
+ +
+
POST
+

/store/inventory/(orderId)

+
+ +
+
PUT
+

/store/inventory/(orderId)

+
+ +
+ +
+
store
+
+ +
+
PUT
+

/store/inventory/(orderId)

+
+ +
+
DEL
+

/store/inventory/(orderId)

+
+ +
+
POST
+

/store/inventory/(orderId)

+
+ +
+
PUT
+

/store/inventory/(orderId)

+
+ +
+ +
+
user
+
+
+
+ + + +
MODELS
+ +
+
+ + + +
SECURITY
+ +
+
+
+ ); +} + +export default Sidebar; diff --git a/packages/insomnia-components/components/sidebar.stories.js b/packages/insomnia-components/components/sidebar.stories.js new file mode 100644 index 00000000000..00ff4e1e6a8 --- /dev/null +++ b/packages/insomnia-components/components/sidebar.stories.js @@ -0,0 +1,20 @@ +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 = () => ; + +_default.story = { + parameters: { + design: { + type: 'figma', + url: 'https://www.figma.com/file/sS7oBbKmDvhtq5lXyTckVe/Style-Guide-Components?node-id=0%3A2', + }, + }, +}; diff --git a/packages/insomnia-components/components/svg-icon.js b/packages/insomnia-components/components/svg-icon.js index fc2738b45a5..9ccb5dfcc18 100644 --- a/packages/insomnia-components/components/svg-icon.js +++ b/packages/insomnia-components/components/svg-icon.js @@ -5,14 +5,43 @@ import MemoSvgIcnArrowRight from '../assets/svgr/IcnArrowRight'; import MemoSvgIcnChevronDown from '../assets/svgr/IcnChevronDown'; import MemoSvgIcnChevronUp from '../assets/svgr/IcnChevronUp'; import MemoSvgIcnClock from '../assets/svgr/IcnClock'; -import MemoSvgIcnEllipsis from '../assets/svgr/IcnEllipsis'; import MemoSvgIcnEmpty from '../assets/svgr/IcnEmpty'; import MemoSvgIcnErrors from '../assets/svgr/IcnErrors'; import MemoSvgIcnGitBranch from '../assets/svgr/IcnGitBranch'; import MemoSvgIcnGithubLogo from '../assets/svgr/IcnGithubLogo'; -import MemoSvgIcnInfo from '../assets/svgr/IcnInfo'; -import MemoSvgIcnSearch from '../assets/svgr/IcnSearch'; +import MemoSvgIcnBitbucketLogo from '../assets/svgr/IcnBitbucketLogo'; import MemoSvgIcnWarning from '../assets/svgr/IcnWarning'; +import MemoSvgIcnEllipsis from '../assets/svgr/IcnEllipsis'; +import MemoSvgIcnBurgerMenu from '../assets/svgr/IcnBurgerMenu'; +import MemoSvgIcnCheckmark from '../assets/svgr/IcnCheckmark'; +import MemoSvgIcnCookie from '../assets/svgr/IcnCookie'; +import MemoSvgIcnDragGrip from '../assets/svgr/IcnDragGrip'; +import MemoSvgIcnElevator from '../assets/svgr/IcnElevator'; +import MemoSvgIcnEllipsisCircle from '../assets/svgr/IcnEllipsisCircle'; +import MemoSvgIcnFile from '../assets/svgr/IcnFile'; +import MemoSvgIcnFolderOpen from '../assets/svgr/IcnFolderOpen'; +import MemoSvgIcnFolder from '../assets/svgr/IcnFolder'; +import MemoSvgIcnGear from '../assets/svgr/IcnGear'; +import MemoSvgIcnGitlabLogo from '../assets/svgr/IcnGitlabLogo'; +import MemoSvgIcnGUI from '../assets/svgr/IcnGui'; +import MemoSvgIcnIndendation from '../assets/svgr/IcnIndentation'; +import MemoSvgIcnMinusCircleFill from '../assets/svgr/IcnMinusCircleFill'; +import MemoSvgIcnMinusCircle from '../assets/svgr/IcnMinusCircle'; +import MemoSvgIcnPlaceholder from '../assets/svgr/IcnPlaceholder'; +import MemoSvgIcnPlay from '../assets/svgr/IcnPlay'; +import MemoSvgIcnPlus from '../assets/svgr/IcnPlus'; +import MemoSvgIcnProhibited from '../assets/svgr/IcnProhibited'; +import MemoSvgIcnQuestionFill from '../assets/svgr/IcnQuestionFill'; +import MemoSvgIcnQuestion from '../assets/svgr/IcnQuestion'; +import MemoSvgIcnSearch from '../assets/svgr/IcnSearch'; +import MemoSvgIcnSecCert from '../assets/svgr/IcnSecCert'; +import MemoSvgIcnSync from '../assets/svgr/IcnSync'; +import MemoSvgIcnTrashcan from '../assets/svgr/IcnTrashcan'; +import MemoSvgIcnTriangle from '../assets/svgr/IcnTriangle'; +import MemoSvgIcnUser from '../assets/svgr/IcnUser'; +import MemoSvgIcnWarningCircle from '../assets/svgr/IcnWarningCircle'; +import MemoSvgIcnX from '../assets/svgr/IcnX'; +import MemoSvgIcnInfo from '../assets/svgr/IcnInfo'; export const ThemeEnum = { default: 'default', @@ -38,9 +67,38 @@ export const IconEnum = { error: 'error', gitBranch: 'git-branch', github: 'github', + bitbucket: 'bitbucket', info: 'info', search: 'search', warning: 'warning', + burgerMenu: 'burger-menu', + checkmark: 'checkmark', + cookie: 'cookie', + dragGrip: 'drag-grip', + elevator: 'elevator', + ellipsesCircle: 'ellipses-circle', + file: 'file', + folder: 'folder', + folderOpen: 'folder-open', + gear: 'gear', + gitlabLogo: 'gitlab-logo', + gui: 'gui', + indentation: 'indentation', + minusCircle: 'minus-circle', + minusCircleFill: 'minus-circle-fill', + placeholder: 'placeholder', + play: 'play', + plus: 'plus', + prohibited: 'prohibited', + questionFill: 'question-fill', + question: 'question', + secCert: 'sec-cert', + sync: 'sync', + trashcan: 'trashcan', + triangle: 'triangle', + user: 'user', + warningCircle: 'warning-circle', + x: 'x', // Blank icon empty: 'empty', @@ -49,7 +107,7 @@ export const IconEnum = { type IconKeys = $Values; type Props = { - icon: IconKeys; + icon: IconKeys, label?: React.Node, }; @@ -63,27 +121,27 @@ const SvgIconStyled: React.ComponentType<{ theme: ThemeKeys, hasLabel: boolean } user-select: none; ${({ hasLabel }) => (hasLabel ? 'margin-right: var(--padding-xs);' : null)} ${({ theme }) => { - switch (theme) { - case ThemeEnum.danger: - case ThemeEnum.info: - case ThemeEnum.notice: - case ThemeEnum.success: - case ThemeEnum.surprise: - case ThemeEnum.warning: - return `fill: var(--color-${theme}); color: var(--color-font-${theme});`; - case ThemeEnum.highlight: - return 'fill: var(--hl); color: var(--color-font-danger);'; - case ThemeEnum.default: - default: - return 'fill: var(--color-font); color: var(--color-font);'; - } -}} + switch (theme) { + case ThemeEnum.danger: + case ThemeEnum.info: + case ThemeEnum.notice: + case ThemeEnum.success: + case ThemeEnum.surprise: + case ThemeEnum.warning: + return `fill: var(--color-${theme}); color: var(--color-font-${theme});`; + case ThemeEnum.highlight: + return 'fill: var(--hl); color: var(--color-font-danger);'; + case ThemeEnum.default: + default: + return 'fill: var(--color-font); color: var(--color-font);'; + } + }} } `; type IconDictionary = { - [IconKeys]: [ThemeKeys, React.ComponentType]; -} + [IconKeys]: [ThemeKeys, React.ComponentType], +}; class SvgIcon extends React.Component { static icons: IconDictionary = { @@ -96,9 +154,39 @@ class SvgIcon extends React.Component { [IconEnum.error]: [ThemeEnum.danger, MemoSvgIcnErrors], [IconEnum.gitBranch]: [ThemeEnum.default, MemoSvgIcnGitBranch], [IconEnum.github]: [ThemeEnum.default, MemoSvgIcnGithubLogo], + [IconEnum.bitbucket]: [ThemeEnum.default, MemoSvgIcnBitbucketLogo], [IconEnum.info]: [ThemeEnum.highlight, MemoSvgIcnInfo], [IconEnum.search]: [ThemeEnum.default, MemoSvgIcnSearch], [IconEnum.warning]: [ThemeEnum.notice, MemoSvgIcnWarning], + [IconEnum.burgerMenu]: [ThemeEnum.default, MemoSvgIcnBurgerMenu], + [IconEnum.checkmark]: [ThemeEnum.default, MemoSvgIcnCheckmark], + [IconEnum.cookie]: [ThemeEnum.default, MemoSvgIcnCookie], + [IconEnum.dragGrip]: [ThemeEnum.default, MemoSvgIcnDragGrip], + [IconEnum.elevator]: [ThemeEnum.default, MemoSvgIcnElevator], + [IconEnum.ellipsesCircle]: [ThemeEnum.default, MemoSvgIcnEllipsisCircle], + [IconEnum.elevator]: [ThemeEnum.default, MemoSvgIcnElevator], + [IconEnum.file]: [ThemeEnum.default, MemoSvgIcnFile], + [IconEnum.folder]: [ThemeEnum.default, MemoSvgIcnFolder], + [IconEnum.folderOpen]: [ThemeEnum.default, MemoSvgIcnFolderOpen], + [IconEnum.gear]: [ThemeEnum.default, MemoSvgIcnGear], + [IconEnum.gitlabLogo]: [ThemeEnum.default, MemoSvgIcnGitlabLogo], + [IconEnum.gui]: [ThemeEnum.default, MemoSvgIcnGUI], + [IconEnum.indentation]: [ThemeEnum.default, MemoSvgIcnIndendation], + [IconEnum.minusCircle]: [ThemeEnum.default, MemoSvgIcnMinusCircle], + [IconEnum.minusCircleFill]: [ThemeEnum.default, MemoSvgIcnMinusCircleFill], + [IconEnum.placeholder]: [ThemeEnum.default, MemoSvgIcnPlaceholder], + [IconEnum.play]: [ThemeEnum.default, MemoSvgIcnPlay], + [IconEnum.plus]: [ThemeEnum.default, MemoSvgIcnPlus], + [IconEnum.prohibited]: [ThemeEnum.default, MemoSvgIcnProhibited], + [IconEnum.question]: [ThemeEnum.default, MemoSvgIcnQuestion], + [IconEnum.questionFill]: [ThemeEnum.default, MemoSvgIcnQuestionFill], + [IconEnum.secCert]: [ThemeEnum.default, MemoSvgIcnSecCert], + [IconEnum.sync]: [ThemeEnum.default, MemoSvgIcnSync], + [IconEnum.trashcan]: [ThemeEnum.default, MemoSvgIcnTrashcan], + [IconEnum.triangle]: [ThemeEnum.default, MemoSvgIcnTriangle], + [IconEnum.user]: [ThemeEnum.default, MemoSvgIcnUser], + [IconEnum.warningCircle]: [ThemeEnum.default, MemoSvgIcnWarningCircle], + [IconEnum.x]: [ThemeEnum.default, MemoSvgIcnX], }; render() { diff --git a/packages/insomnia-components/components/svg-icon.stories.js b/packages/insomnia-components/components/svg-icon.stories.js index 849d6450909..f70085de80a 100644 --- a/packages/insomnia-components/components/svg-icon.stories.js +++ b/packages/insomnia-components/components/svg-icon.stories.js @@ -6,7 +6,7 @@ import { Table, TableBody, TableData, TableHead, TableHeader, TableRow } from '. import styled from 'styled-components'; export default { - title: 'SvgIcon', + title: '1st Party | SvgIcon', decorators: [withKnobs], }; @@ -20,7 +20,9 @@ Wrapper.displayName = '...'; export const _default = () => ; -export const labelled = () => ; +export const labelled = () => ( + +); export const reference = () => ( diff --git a/packages/insomnia-components/components/switch.stories.js b/packages/insomnia-components/components/switch.stories.js index 4e912016bc9..84e6b7c2f4a 100644 --- a/packages/insomnia-components/components/switch.stories.js +++ b/packages/insomnia-components/components/switch.stories.js @@ -1,8 +1,22 @@ import React from 'react'; import Switch from './switch'; -export default { title: 'Sliding Switch' }; +export default { title: '1st Party | Sliding Switch' }; -export const _design = () => ; +export const _design = () => ( + +); -export const _debug = () => ; +export const _debug = () => ( + +); diff --git a/packages/insomnia-components/components/table.stories.js b/packages/insomnia-components/components/table.stories.js index b973ad700b6..580fce33b12 100644 --- a/packages/insomnia-components/components/table.stories.js +++ b/packages/insomnia-components/components/table.stories.js @@ -2,7 +2,7 @@ import * as React from 'react'; import { Table, TableBody, TableData, TableHead, TableHeader, TableRow } from './table'; -export default { title: 'Table' }; +export default { title: '1st Party | Table' }; export const _default = () => ( diff --git a/packages/insomnia-components/components/toggle-switch.stories.js b/packages/insomnia-components/components/toggle-switch.stories.js index 7b9f5545aef..fb30b1ff0e0 100644 --- a/packages/insomnia-components/components/toggle-switch.stories.js +++ b/packages/insomnia-components/components/toggle-switch.stories.js @@ -1,7 +1,7 @@ import * as React from 'react'; import ToggleSwitch from './toggle-switch'; -export default { title: '1 | 2 / Toggle Switch' }; +export default { title: '3rd Party | Toggle Switch' }; const defaultOnChange = () => {}; diff --git a/packages/insomnia-components/components/tooltip.js b/packages/insomnia-components/components/tooltip.js new file mode 100644 index 00000000000..46b0f79ed80 --- /dev/null +++ b/packages/insomnia-components/components/tooltip.js @@ -0,0 +1,236 @@ +// @flow +import * as React from 'react'; +import autobind from 'autobind-decorator'; +import classnames from 'classnames'; +import ReactDOM from 'react-dom'; +import styled from 'styled-components'; + +type Props = { + children: React.Node, + message: React.Node, + position?: 'bottom' | 'top' | 'right' | 'left', + + // Optional + className?: string, + delay?: number, + selectable?: boolean, + wide?: boolean, +}; + +type State = { + visible: boolean, +}; + +const StyledTooltip: React.ComponentType<{}> = styled.div` + position: relative; + display: inline-block; +`; + +const StyledTooltipBubble: React.ComponentType<{}> = styled.div` + position: fixed; + left: -999999px; + opacity: 0; + background: var(--color-bg); + border: 1px solid var(--hl-sm); + box-shadow: 0 0 1em rgba(0, 0, 0, 0.1); + color: var(--color-font); + padding: var(--padding-sm) var(--padding-md); + border-radius: var(--radius-sm); + font-size: var(--font-size-sm); + max-width: 20rem; + text-align: center; + z-index: 10; + white-space: normal !important; + word-wrap: break-word; + + &.tooltip__bubble--visible { + opacity: 1; + z-index: 99999; + transition: opacity 200ms; + + // Back to normal + height: auto; + line-height: normal; + } + + &.tooltip__bubble--wide { + max-width: 30rem; + } +`; + +@autobind +class Tooltip extends React.PureComponent { + _showTimeout: TimeoutID; + _hideTimeout: TimeoutID; + + // TODO: Figure out what type these should be + _tooltip: ?any; + _bubble: ?any; + _id: string; + + constructor(props: any) { + super(props); + + this.state = { + left: null, + top: null, + bottom: null, + right: null, + maxWidth: null, + maxHeight: null, + visible: false, + }; + + this._id = Math.random() + ''; + } + + _setTooltipRef(n: ?any) { + this._tooltip = n; + } + + _setBubbleRef(n: ?any) { + this._bubble = n; + } + + _handleStopClick(e: MouseEvent): void { + e.stopPropagation(); + } + + _handleMouseEnter(e: MouseEvent): void { + clearTimeout(this._showTimeout); + clearTimeout(this._hideTimeout); + this._showTimeout = setTimeout((): void => { + const tooltip = this._tooltip; + const bubble = this._bubble; + + if (!tooltip) { + return; + } + + if (!bubble) { + return; + } + + const tooltipRect = tooltip.getBoundingClientRect(); + const bubbleRect = bubble.getBoundingClientRect(); + const margin = 3; + + let left = 0; + let top = 0; + switch (this.props.position) { + case 'right': + top = tooltipRect.top - bubbleRect.height / 2 + tooltipRect.height / 2; + left = tooltipRect.left + tooltipRect.width + margin; + break; + + case 'left': + top = tooltipRect.top - bubbleRect.height / 2 + tooltipRect.height / 2; + left = tooltipRect.left - bubbleRect.width - margin; + break; + + case 'bottom': + top = tooltipRect.top + tooltipRect.height + margin; + left = tooltipRect.left - bubbleRect.width / 2 + tooltipRect.width / 2; + break; + + case 'top': + default: + top = tooltipRect.top - bubbleRect.height - margin; + left = tooltipRect.left - bubbleRect.width / 2 + tooltipRect.width / 2; + break; + } + + bubble.style.left = `${Math.max(0, left)}px`; + bubble.style.top = `${Math.max(0, top)}px`; + + this.setState({ visible: true }); + }, this.props.delay || 400); + } + + _handleMouseLeave(): void { + clearTimeout(this._showTimeout); + clearTimeout(this._hideTimeout); + this._hideTimeout = setTimeout(() => { + this.setState({ visible: false }); + + const bubble = this._bubble; + if (!bubble) { + return; + } + + // Reset positioning stuff + bubble.style.left = ''; + bubble.style.top = ''; + bubble.style.bottom = ''; + bubble.style.right = ''; + }, 100); + } + + _getContainer(): HTMLElement { + let container = document.querySelector('#tooltips-container'); + if (!container) { + container = document.createElement('div'); + container.id = 'tooltips-container'; + container.style.zIndex = '1000000'; + container.style.position = 'relative'; + + document.body && document.body.appendChild(container); + } + + return container; + } + + componentDidMount() { + // Move the element to the body so we can position absolutely + if (this._bubble) { + const el = ReactDOM.findDOMNode(this._bubble); + el && this._getContainer().appendChild(el); + } + } + + componentWillUnmount() { + // Remove the element from the body + if (this._bubble) { + const el = ReactDOM.findDOMNode(this._bubble); + el && this._getContainer().removeChild(el); + } + } + + render() { + const { children, message, className, selectable, wide } = this.props; + const { visible } = this.state; + + if (!message) { + return children; + } + + const tooltipClasses = classnames(className, 'tooltip'); + const bubbleClasses = classnames('tooltip__bubble theme--tooltip', { + 'tooltip__bubble--visible': visible, + 'tooltip__bubble--wide': wide, + selectable: selectable, + }); + + return ( + + + {message} + + {children} + + ); + } +} + +export default Tooltip; diff --git a/packages/insomnia-components/components/tooltip.stories.js b/packages/insomnia-components/components/tooltip.stories.js new file mode 100644 index 00000000000..b30cf08be76 --- /dev/null +++ b/packages/insomnia-components/components/tooltip.stories.js @@ -0,0 +1,56 @@ +import React from 'react'; +import Tooltip from './tooltip'; + +export default { title: 'Tooltip' }; + +export const onTop = () => ( +
+ + + +
+); + +export const onRight = () => ( +
+ + + +
+); + +export const onLeft = () => ( +
+ + + +
+); + +export const withDelay = () => ( +
+ + + +
+); + +export const withChildren = () => { + const message = ( + + This is a{' '} + e.preventDefault()}> + Link + + . + + ); + + return ( +
+ + + +
+ ); +}; diff --git a/packages/insomnia-components/flow-typed/@storybook/framer-motion.js b/packages/insomnia-components/flow-typed/@storybook/framer-motion.js new file mode 100644 index 00000000000..23b1cf374a2 --- /dev/null +++ b/packages/insomnia-components/flow-typed/@storybook/framer-motion.js @@ -0,0 +1,10 @@ +// @flow + +declare module 'framer-motion' { + declare module.exports: { + motion: Object, + useCycle: Object, + AnimatePresence: Object, + withKnobs: Object, + } +} \ No newline at end of file diff --git a/packages/insomnia-components/flow-typed/autobind-decorator.js b/packages/insomnia-components/flow-typed/autobind-decorator.js new file mode 100644 index 00000000000..b29d11d9e0d --- /dev/null +++ b/packages/insomnia-components/flow-typed/autobind-decorator.js @@ -0,0 +1,5 @@ +// @flow + +declare module 'autobind-decorator' { + declare module.exports: *; +} diff --git a/packages/insomnia-components/index.js b/packages/insomnia-components/index.js index 44802b8fd94..c9d053ccc48 100644 --- a/packages/insomnia-components/index.js +++ b/packages/insomnia-components/index.js @@ -9,6 +9,7 @@ import _GravatarImg from './components/gravatar-img'; import _Header from './components/header'; import _NoticeTable from './components/notice-table'; import _SvgIcon from './components/svg-icon'; +import _Sidebar from './components/sidebar'; import _Switch from './components/switch'; import _ToggleSwitch from './components/toggle-switch'; import * as table from './components/table'; @@ -25,6 +26,7 @@ export const Header = _Header; export const NoticeTable = _NoticeTable; export const SvgIcon = _SvgIcon; export const Switch = _Switch; +export const Sidebar = _Sidebar; export const Table = table.Table; export const TableBody = table.TableBody; export const TableData = table.TableData; diff --git a/packages/insomnia-components/package-lock.json b/packages/insomnia-components/package-lock.json index 86bb8ae30a8..2d313c55cdc 100644 --- a/packages/insomnia-components/package-lock.json +++ b/packages/insomnia-components/package-lock.json @@ -1367,6 +1367,23 @@ "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", "dev": true }, + "@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.2.1", "resolved": "https://registry.npmjs.org/@reach/router/-/router-1.2.1.tgz", @@ -6624,6 +6641,31 @@ "map-cache": "^0.2.2" } }, + "framer-motion": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-1.10.3.tgz", + "integrity": "sha512-VooCzGWg7brSO4Gc0YwpY5AadJe4OPS74ZyOlOHWll5rMXCoOc6Ia3uDQ6RfOJlwCP/D9TQuRGtboyJiVXjVcw==", + "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", @@ -7613,6 +7655,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.13.1", "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.13.1.tgz", @@ -8590,6 +8637,12 @@ "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", "dev": true }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=", + "dev": true + }, "lodash.throttle": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", @@ -8639,6 +8692,12 @@ "semver": "^5.6.0" } }, + "make-event-props": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/make-event-props/-/make-event-props-1.2.0.tgz", + "integrity": "sha512-BmWFkm/jZzVH9A0tEBdkjAARUz/eha+5IRyfOndeSMKRadkgR5DawoBHoRwLxkYmjJOI5bHkXKpaZocxj+dKgg==", + "dev": true + }, "map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", @@ -8776,6 +8835,12 @@ "is-what": "^3.3.1" } }, + "merge-class-names": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/merge-class-names/-/merge-class-names-1.3.0.tgz", + "integrity": "sha512-k0Qaj36VBpKgdc8c188LEZvo6v/zzry/FUufwopWbMSp6/knfVFU/KIB55/hJjeIpg18IH2WskXJCRnM/1BrdQ==", + "dev": true + }, "merge-deep": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.2.tgz", @@ -9166,6 +9231,12 @@ "minimatch": "^3.0.2" } }, + "node-ensure": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/node-ensure/-/node-ensure-0.0.0.tgz", + "integrity": "sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc=", + "dev": true + }, "node-fetch": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", @@ -9737,6 +9808,16 @@ "sha.js": "^2.4.8" } }, + "pdfjs-dist": { + "version": "2.1.266", + "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.1.266.tgz", + "integrity": "sha512-Jy7o1wE3NezPxozexSbq4ltuLT0Z21ew/qrEiAEeUZzHxMHGk4DUV1D7RuCXg5vJDvHmjX1YssN+we9QfRRgXQ==", + "dev": true, + "requires": { + "node-ensure": "^0.0.0", + "worker-loader": "^2.0.0" + } + }, "picomatch": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz", @@ -9830,6 +9911,19 @@ "@babel/runtime": "^7.6.3" } }, + "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", @@ -10625,6 +10719,20 @@ "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==", "dev": true }, + "react-pdf": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/react-pdf/-/react-pdf-4.1.0.tgz", + "integrity": "sha512-SYwkWc+vRQHfrpDls3DOgn4G+wT0mYGJRor20e28GPRW8VB+6o8WqZ4QZxsl50z+dKM7UscXFnK/02eN3NXi2g==", + "dev": true, + "requires": { + "@babel/runtime": "^7.0.0", + "lodash.once": "^4.1.1", + "make-event-props": "^1.1.0", + "merge-class-names": "^1.1.1", + "pdfjs-dist": "2.1.266", + "prop-types": "^15.6.2" + } + }, "react-popper": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.7.tgz", @@ -11766,6 +11874,15 @@ "integrity": "sha512-tWEpK0snS2RPUq1i3R6OahfJNjWCQYNxq0+by1amCSuw0mXtymJpzmZIeYpA1UAa+7B0grCpNYIbDcd7AgTbFg==", "dev": true }, + "storybook-addon-designs": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/storybook-addon-designs/-/storybook-addon-designs-5.2.0.tgz", + "integrity": "sha512-53+d15uqoAaNQffbpvuSkcgubZh7cKNC+44azS+aDMzQubgHj9hQZ255XSmtXGxfyVsngGpK1QnHCCZ+13KH/Q==", + "dev": true, + "requires": { + "react-pdf": "^4.0.5" + } + }, "stream-browserify": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", @@ -11931,6 +12048,15 @@ } } }, + "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" + } + }, "styled-components": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-4.4.1.tgz", @@ -11951,6 +12077,18 @@ "supports-color": "^5.5.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" + } + }, "stylis": { "version": "3.5.4", "resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz", @@ -12302,8 +12440,7 @@ "tslib": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", - "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", - "dev": true + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" }, "tty-browserify": { "version": "0.0.0", @@ -13062,6 +13199,28 @@ "errno": "~0.1.7" } }, + "worker-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-2.0.0.tgz", + "integrity": "sha512-tnvNp4K3KQOpfRnD20m8xltE3eWh89Ye+5oj7wXEEHKac1P4oZ6p9oTj8/8ExqoSBnk9nu5Pr4nKfQ1hn2APJw==", + "dev": true, + "requires": { + "loader-utils": "^1.0.0", + "schema-utils": "^0.4.0" + }, + "dependencies": { + "schema-utils": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", + "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, "worker-rpc": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/worker-rpc/-/worker-rpc-0.1.1.tgz", diff --git a/packages/insomnia-components/package.json b/packages/insomnia-components/package.json index c594b86efe2..41e2e44e511 100644 --- a/packages/insomnia-components/package.json +++ b/packages/insomnia-components/package.json @@ -25,6 +25,7 @@ "@storybook/addon-contexts": "^5.3.10", "@storybook/addon-info": "^5.3.9", "@storybook/addon-knobs": "^5.3.10", + "storybook-addon-designs": "^5.2.0", "@storybook/react": "^5.3.9", "@svgr/cli": "^5.3.0", "babel-loader": "^8.0.6", @@ -36,6 +37,7 @@ "autobind-decorator": "^2.4.0", "classnames": "^2.2.6", "fuzzysort": "^1.1.4", + "framer-motion": "^1.10.3", "prop-types": "^15.7.2", "react": "^16.8.6", "react-dom": "^16.8.6", diff --git a/packages/openapi-2-kong/src/common.js b/packages/openapi-2-kong/src/common.js index 390bb6a2435..51f61973d4e 100644 --- a/packages/openapi-2-kong/src/common.js +++ b/packages/openapi-2-kong/src/common.js @@ -37,15 +37,24 @@ export function getName( api: OpenApi3Spec, defaultValue?: string, slugifyOptions?: SlugifyOptions, + isKubernetes?: boolean, ): string { - let name = api['x-kong-name'] || ''; + let rawName = ''; - if (!name && typeof api.info?.title === 'string') { - name = api.info.title; - } + // Get $.info.x-kubernetes-ingress-metadata.name + rawName = isKubernetes && api.info?.['x-kubernetes-ingress-metadata']?.name; + + // Get $.x-kong-name + rawName = rawName || api['x-kong-name']; + + // Get $.info.title + rawName = rawName || api.info?.title; - name = name || defaultValue || 'openapi'; + // Make sure the name is a string + const defaultName = defaultValue || 'openapi'; + const name = typeof rawName === 'string' && rawName ? rawName : defaultName; + // Sluggify return generateSlug(name, slugifyOptions); } diff --git a/packages/openapi-2-kong/src/kubernetes/__tests__/index.test.js b/packages/openapi-2-kong/src/kubernetes/__tests__/index.test.js index 20c378185f6..e9a51b955cb 100644 --- a/packages/openapi-2-kong/src/kubernetes/__tests__/index.test.js +++ b/packages/openapi-2-kong/src/kubernetes/__tests__/index.test.js @@ -56,7 +56,7 @@ describe('index', () => { 'x-kong-name': 'Kong Name', info: { 'x-kubernetes-ingress-metadata': { - name: 'k8s-name', + name: 'K8s name', }, }, }); @@ -100,18 +100,21 @@ describe('index', () => { expect(result).toEqual({ 'konghq.com/override': 'name' }); }); - it('gets all annotations correctly', async () => { - const api: OpenApi3Spec = await parseSpec({ + it('gets all annotations correctly', () => { + const originalAnnotations = { + 'nginx.ingress.kubernetes.io/rewrite-target': '/', + }; + + const api: OpenApi3Spec = { ...spec, info: { + ...spec.info, 'x-kubernetes-ingress-metadata': { name: 'info-name', - annotations: { - 'nginx.ingress.kubernetes.io/rewrite-target': '/', - }, + annotations: { ...originalAnnotations }, }, }, - }); + }; const result = generateMetadataAnnotations(api, { pluginNames: ['one', 'two'], overrideName: 'name', @@ -121,6 +124,11 @@ describe('index', () => { 'konghq.com/plugins': 'one, two', 'konghq.com/override': 'name', }); + + // Should not modify source metadata annotations object + expect(api.info['x-kubernetes-ingress-metadata']?.annotations).toStrictEqual( + originalAnnotations, + ); }); }); @@ -225,8 +233,6 @@ describe('index', () => { expect(generateServicePath(basePath)).toBe('/api/v1/.*'); }); - // This state arises when a serverUrl is https://api.insomnia.rest/api/{var} and no paths exist on spec. - // Is this correct? it('adds closing wildcard if basePath ends with wildcard and no specific path exists', () => { const serverBasePath = '/api/.*'; expect(generateServicePath(serverBasePath)).toBe('/api/.*/.*'); @@ -252,7 +258,7 @@ describe('index', () => { it('handles basic server at root', () => { const result = generateRulesForServer(0, { url: 'http://api.insomnia.rest' }, 'my-ingress'); - expect(result).toEqual({ + expect(result).toStrictEqual({ host: 'api.insomnia.rest', http: { paths: [ @@ -454,7 +460,7 @@ describe('index', () => { const result = generateKongForKubernetesConfigFromSpec(api, []); - expect(result.documents).toEqual([ + expect(result.documents).toStrictEqual([ keyAuthPluginDoc('g0'), dummyPluginDoc('g1'), ingressDoc([keyAuthName('g0'), dummyName('g1')], 'api.insomnia.rest', 'my-api-s0'), @@ -483,7 +489,7 @@ describe('index', () => { const result = generateKongForKubernetesConfigFromSpec(api, []); - expect(result.documents).toEqual([ + expect(result.documents).toStrictEqual([ keyAuthPluginDoc('g0'), keyAuthPluginDoc('s1'), keyAuthPluginDoc('s2'), @@ -512,7 +518,7 @@ describe('index', () => { const result = generateKongForKubernetesConfigFromSpec(api, []); - expect(result.documents).toEqual([ + expect(result.documents).toStrictEqual([ keyAuthPluginDoc('g0'), keyAuthPluginDoc('p1'), keyAuthPluginDoc('p2'), @@ -548,7 +554,7 @@ describe('index', () => { const result = generateKongForKubernetesConfigFromSpec(api, []); - expect(result.documents).toEqual([ + expect(result.documents).toStrictEqual([ methodDoc('get'), methodDoc('put'), methodDoc('post'), diff --git a/packages/openapi-2-kong/src/kubernetes/__tests__/util/plugin-helpers.js b/packages/openapi-2-kong/src/kubernetes/__tests__/util/plugin-helpers.js index 1ba34c19412..b320e61a674 100644 --- a/packages/openapi-2-kong/src/kubernetes/__tests__/util/plugin-helpers.js +++ b/packages/openapi-2-kong/src/kubernetes/__tests__/util/plugin-helpers.js @@ -66,26 +66,30 @@ export const ingressDoc = ( host: string, serviceName: string, path: ?string, -) => ({ - apiVersion: 'extensions/v1beta1', - kind: 'Ingress', - metadata: { - annotations: { - 'konghq.com/plugins': plugins.join(', '), +) => { + const backend = { serviceName, servicePort: 80 }; + const paths = path ? { path, backend } : { backend }; + return { + apiVersion: 'extensions/v1beta1', + kind: 'Ingress', + metadata: { + annotations: { + 'konghq.com/plugins': plugins.join(', '), + }, + name: 'my-api', }, - name: 'my-api', - }, - spec: { - rules: [ - { - host, - http: { - paths: [{ backend: { serviceName, servicePort: 80 }, path }], + spec: { + rules: [ + { + host, + http: { + paths: [paths], + }, }, - }, - ], - }, -}); + ], + }, + }; +}; export const ingressDocWithOverride = ( plugins: Array, diff --git a/packages/openapi-2-kong/src/kubernetes/index.js b/packages/openapi-2-kong/src/kubernetes/index.js index 4e23d14fcdb..5331ea4633c 100644 --- a/packages/openapi-2-kong/src/kubernetes/index.js +++ b/packages/openapi-2-kong/src/kubernetes/index.js @@ -105,12 +105,7 @@ type CustomAnnotations = { }; export function generateMetadataName(api: OpenApi3Spec): string { - const name = api.info?.['x-kubernetes-ingress-metadata']?.name; - if (name) { - return name; - } - - return getName(api, 'openapi', { lower: true, replacement: '-' }); + return getName(api, 'openapi', { lower: true, replacement: '-' }, true); } export function generateMetadataAnnotations( @@ -121,17 +116,18 @@ export function generateMetadataAnnotations( // Only continue if metadata annotations, or plugins, or overrides exist if (metadata?.annotations || pluginNames.length || overrideName) { - const annotations = metadata?.annotations || {}; + const customAnnotations = {}; if (pluginNames.length) { - annotations['konghq.com/plugins'] = pluginNames.join(', '); + customAnnotations['konghq.com/plugins'] = pluginNames.join(', '); } if (overrideName) { - annotations['konghq.com/override'] = overrideName; + customAnnotations['konghq.com/override'] = overrideName; } - return annotations; + const originalAnnotations = metadata?.annotations || {}; + return { ...originalAnnotations, ...customAnnotations }; } return null; @@ -152,10 +148,11 @@ export function generateRulesForServer( const backend = { serviceName, servicePort }; const pathsToUse: Array = (paths?.length && paths) || ['']; // Make flow happy - const k8sPaths: Array = pathsToUse.map(p => ({ - path: generateServicePath(pathname, p), - backend, - })); + const k8sPaths: Array = pathsToUse.map(p => { + const path = generateServicePath(pathname, p); + + return path ? { path, backend } : { backend }; + }); const tlsConfig = generateTlsConfig(server); if (tlsConfig) { @@ -226,8 +223,8 @@ export function generateServicePath( return undefined; } - const fullPath = urlJoin(serverBasePath, specificPath); + const fullPath = urlJoin(serverBasePath, specificPath, specificPath ? '' : '.*'); const pathname = pathVariablesToWildcard(fullPath); - return pathname + (specificPath ? '' : '/.*'); + return pathname; }