diff --git a/frontend/packages/app/package.json b/frontend/packages/app/package.json index 55f747560a..88a902be5d 100644 --- a/frontend/packages/app/package.json +++ b/frontend/packages/app/package.json @@ -18,7 +18,9 @@ "@types/react-dom": "^16.9.0", "@types/react-router-dom": "^5.1.3", "@types/zen-observable": "^0.8.0", + "classnames": "^2.2.6", "cross-env": "^7.0.0", + "rc-progress": "^2.5.2", "react": "^16.12.0", "react-dom": "^16.12.0", "react-router-dom": "^5.1.2", diff --git a/frontend/packages/shared/components/CircleProgress.js b/frontend/packages/core/src/components/CircleProgress.js similarity index 84% rename from frontend/packages/shared/components/CircleProgress.js rename to frontend/packages/core/src/components/CircleProgress.js index a279e0a194..271896702d 100644 --- a/frontend/packages/shared/components/CircleProgress.js +++ b/frontend/packages/core/src/components/CircleProgress.js @@ -2,7 +2,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { withStyles } from '@material-ui/core'; import { Circle } from 'rc-progress'; -import { COLORS, V1 } from 'core/app/Themes'; +import { COLORS } from '@backstage/core'; const styles = theme => ({ root: { @@ -43,7 +43,7 @@ class CircleProgress extends Component { static getProgressColor(value, inverse, max /* , classes */) { if (isNaN(value)) { - return V1.palette.textVerySubtle; + return 'grey'; } max = max ? max : CircleProgress.defaultProps.max; @@ -70,10 +70,17 @@ class CircleProgress extends Component { percent={asPercentage} strokeWidth="12" trailWidth="12" - strokeColor={CircleProgress.getProgressColor(asActual, inverse, max, classes)} + strokeColor={CircleProgress.getProgressColor( + asActual, + inverse, + max, + classes, + )} className={classes.circle} /> -
{isNaN(value) ? 'N/A' : `${asActual}${unit}`}
+
+ {isNaN(value) ? 'N/A' : `${asActual}${unit}`} +
); } diff --git a/frontend/packages/shared/components/CircleProgress.test.js b/frontend/packages/core/src/components/CircleProgress.test.js similarity index 100% rename from frontend/packages/shared/components/CircleProgress.test.js rename to frontend/packages/core/src/components/CircleProgress.test.js diff --git a/frontend/packages/shared/components/HorizontalScrollGrid.test.js b/frontend/packages/core/src/components/HorizontalScrollGrid.test.js similarity index 100% rename from frontend/packages/shared/components/HorizontalScrollGrid.test.js rename to frontend/packages/core/src/components/HorizontalScrollGrid.test.js diff --git a/frontend/packages/shared/components/HorizontalScrollGrid.tsx b/frontend/packages/core/src/components/HorizontalScrollGrid.tsx similarity index 89% rename from frontend/packages/shared/components/HorizontalScrollGrid.tsx rename to frontend/packages/core/src/components/HorizontalScrollGrid.tsx index 99f216a5a0..d23f60e0c6 100644 --- a/frontend/packages/shared/components/HorizontalScrollGrid.tsx +++ b/frontend/packages/core/src/components/HorizontalScrollGrid.tsx @@ -3,8 +3,7 @@ import classNames from 'classnames'; import { makeStyles, Theme } from '@material-ui/core/styles'; import ChevronLeftIcon from '@material-ui/icons/ChevronLeft'; import ChevronRightIcon from '@material-ui/icons/ChevronRight'; -import { IconButton } from '.'; -import { Grid } from '@material-ui/core'; +import { Grid, IconButton } from '@material-ui/core'; // Generated with https://larsenwork.com/easing-gradients/ const fadeGradient = ` @@ -79,8 +78,12 @@ const useStyles = makeStyles(theme => ({ })); // Returns scroll distance from left and right -function useScrollDistance(ref: React.MutableRefObject): [number, number] { - const [[scrollLeft, scrollRight], setScroll] = React.useState<[number, number]>([0, 0]); +function useScrollDistance( + ref: React.MutableRefObject, +): [number, number] { + const [[scrollLeft, scrollRight], setScroll] = React.useState< + [number, number] + >([0, 0]); React.useLayoutEffect(() => { const el = ref.current; @@ -110,7 +113,11 @@ function useScrollDistance(ref: React.MutableRefObject) // Used to animate scrolling. Returns a single setScrollTarger function, when called with e.g. 200, // the element pointer to by the ref will be scrolled 200px forwards over time. -function useSmoothScroll(ref: React.MutableRefObject, speed: number, minDistance: number) { +function useSmoothScroll( + ref: React.MutableRefObject, + speed: number, + minDistance: number, +) { const [scrollTarget, setScrollTarget] = React.useState(0); React.useLayoutEffect(() => { @@ -145,7 +152,13 @@ function useSmoothScroll(ref: React.MutableRefObject, s } const HorizontalScrollGrid: FC = props => { - const { scrollStep = 100, scrollSpeed = 50, minScrollDistance = 5, children, ...otherProps } = props; + const { + scrollStep = 100, + scrollSpeed = 50, + minScrollDistance = 5, + children, + ...otherProps + } = props; const classes = useStyles(props); const ref = React.useRef(); @@ -162,7 +175,13 @@ const HorizontalScrollGrid: FC = props => { return (
- + {children}
+ + + +
+ ); + } +} + +export default withStyles(styles)(ProgressCard); diff --git a/frontend/packages/core/src/components/ProgressCard.test.js b/frontend/packages/core/src/components/ProgressCard.test.js new file mode 100644 index 0000000000..5720f328a1 --- /dev/null +++ b/frontend/packages/core/src/components/ProgressCard.test.js @@ -0,0 +1,31 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import { wrapInThemedTestApp } from 'testUtils'; + +import ProgressCard from './ProgressCard'; + +const minProps = { title: 'Tingle upgrade', progress: 0.12 }; + +describe('', () => { + it('renders without exploding', () => { + const { getByText } = render(wrapInThemedTestApp()); + expect(getByText(/Tingle.*/)).toBeInTheDocument(); + }); + + it('renders progress and title', () => { + const { getByText } = render(wrapInThemedTestApp()); + expect(getByText(/Tingle.*/)).toBeInTheDocument(); + expect(getByText(/12%.*/)).toBeInTheDocument(); + }); + + it('does not render deepLink', () => { + const { queryByText } = render(wrapInThemedTestApp()); + expect(queryByText('View more')).not.toBeInTheDocument(); + }); + + it('handles invalid numbers', () => { + const badProps = { title: 'Tingle upgrade', progress: 'hejjo' }; + const { getByText } = render(wrapInThemedTestApp()); + expect(getByText(/N\/A.*/)).toBeInTheDocument(); + }); +}); diff --git a/frontend/packages/core/src/index.ts b/frontend/packages/core/src/index.ts index ccca30231a..a746fbc130 100644 --- a/frontend/packages/core/src/index.ts +++ b/frontend/packages/core/src/index.ts @@ -10,3 +10,8 @@ export { default as HeaderLabel } from '../src/layout/HeaderLabel'; export { default as InfoCard } from '../src/layout/InfoCard'; export { default as ErrorBoundary } from '../src/layout/ErrorBoundary'; export { default as BackstageTheme } from '../src/theme/BackstageTheme'; +export { COLORS } from '../src/theme/BackstageTheme'; +export { default as HorizontalScrollGrid } from './components/HorizontalScrollGrid'; +export { default as ProgressCard } from './components/ProgressCard'; +export { default as CircleProgress } from './components/CircleProgress'; +export { default as Progress } from './components/Progress'; diff --git a/frontend/packages/plugins/home-page/src/components/HomePage/HomePage.tsx b/frontend/packages/plugins/home-page/src/components/HomePage/HomePage.tsx index d84256ac42..73c680591a 100644 --- a/frontend/packages/plugins/home-page/src/components/HomePage/HomePage.tsx +++ b/frontend/packages/plugins/home-page/src/components/HomePage/HomePage.tsx @@ -1,20 +1,29 @@ -import { EntityLink, InfoCard } from '@backstage/core'; -import { Typography } from '@material-ui/core'; import React, { FC } from 'react'; +import { EntityLink, InfoCard } from '@backstage/core'; +import SquadTechHealth from './SquadTechHealth'; +import { Grid, Typography } from '@material-ui/core'; + const HomePage: FC<{}> = () => { return ( - - Welcome to Backstage! -
- - Backstage Backend - - - Backstage LB CI/CD - -
-
+ + + + + + + Welcome to Backstage! +
+ + Backstage Backend + + + Backstage LB CI/CD + +
+
+
+
); }; diff --git a/frontend/packages/plugins/home-page/src/components/HomePage/SquadTechHealth.test.js b/frontend/packages/plugins/home-page/src/components/HomePage/SquadTechHealth.test.js new file mode 100644 index 0000000000..67c4f46815 --- /dev/null +++ b/frontend/packages/plugins/home-page/src/components/HomePage/SquadTechHealth.test.js @@ -0,0 +1,26 @@ +import SquadTechHealth from './SquadTechHealth'; +import { buildComponentInApp } from 'testUtils'; + +const minProps = { + user: { + googleCloudPlatformProjects: [], + squads: [{ id: 'tools', googleCloudPlatformProjects: [], services: [] }], + }, + squads: ['tools'], + insights: { + testCertified: 0.5, + }, +}; + +describe('', () => { + it('renders without exploding', () => { + const rendered = buildComponentInApp(SquadTechHealth) + .withTheme() + .render(minProps); + + expect(rendered.getByText('Test Certified')).toBeInTheDocument(); + expect(rendered.getByText('50%')).toBeInTheDocument(); + + expect(rendered.getByText('Cloud Cost')).toBeInTheDocument(); + }); +}); diff --git a/frontend/packages/plugins/home-page/src/components/HomePage/SquadTechHealth.tsx b/frontend/packages/plugins/home-page/src/components/HomePage/SquadTechHealth.tsx new file mode 100644 index 0000000000..5eeaeafc7f --- /dev/null +++ b/frontend/packages/plugins/home-page/src/components/HomePage/SquadTechHealth.tsx @@ -0,0 +1,36 @@ +import React, { FC } from 'react'; +import { Grid, Typography } from '@material-ui/core'; + +import { HorizontalScrollGrid, ProgressCard } from '@backstage/core'; + +const SquadTechHealth: FC<{}> = () => { + return ( + <> + Team Metrics + + + + + + + + + + ); +}; + +export default SquadTechHealth; diff --git a/frontend/packages/shared/components/InfoCard/BottomLink.js b/frontend/packages/shared/components/InfoCard/BottomLink.js deleted file mode 100644 index a6f0937114..0000000000 --- a/frontend/packages/shared/components/InfoCard/BottomLink.js +++ /dev/null @@ -1,31 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import Link from 'shared/components/Link'; -import { Divider, ListItemText } from '@material-ui/core'; -import { ListItem, ListItemIcon } from '@material-ui/core'; -import ArrowIcon from '@material-ui/icons/ArrowForward'; - -export default class BottomLink extends Component { - static propTypes = { - link: PropTypes.string, - title: PropTypes.string, - onClick: PropTypes.func, - }; - - render() { - const { link, title, onClick } = this.props; - return ( -
- - - - - - - {title} - - -
- ); - } -} diff --git a/frontend/packages/shared/components/InfoCard/BottomLink.test.js b/frontend/packages/shared/components/InfoCard/BottomLink.test.js deleted file mode 100644 index 3941c53b53..0000000000 --- a/frontend/packages/shared/components/InfoCard/BottomLink.test.js +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; -import { render } from '@testing-library/react'; -import { wrapInTestApp } from 'testUtils'; - -import BottomLink from './BottomLink'; - -const minProps = { - title: 'A deepLink title', - link: '/mocked', -}; - -describe('', () => { - it('renders without exploding', () => { - const rendered = render(wrapInTestApp()); - expect(rendered.getByText('A deepLink title')).toBeInTheDocument(); - }); -}); diff --git a/frontend/packages/shared/components/InfoCard/InfoCard.js b/frontend/packages/shared/components/InfoCard/InfoCard.js deleted file mode 100644 index b1a50a9b38..0000000000 --- a/frontend/packages/shared/components/InfoCard/InfoCard.js +++ /dev/null @@ -1,169 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { Card, CardActions, CardContent, CardHeader, Divider, withStyles } from '@material-ui/core'; -import ErrorBoundary from 'shared/components/ErrorBoundary'; -import BottomLink from './BottomLink'; - -import textContent from 'react-addons-text-content'; - -const BoldHeader = withStyles({ title: { fontWeight: '700' } })(CardHeader); -const CardActionsTopRight = withStyles({ - root: { - display: 'inline-block', - paddingRight: '16px', - paddingTop: '16px', - float: 'right', - }, -})(CardActions); - -const VARIANT_STYLES = { - card: { - flex: { - display: 'flex', - flexDirection: 'column', - }, - widget: { - height: 430, - }, - fullHeight: { - height: '100%', - }, - height100: { - display: 'flex', - flexDirection: 'column', - height: 'calc(100% - 10px)', // for pages without content header - marginBottom: '10px', - }, - contentheader: { - height: 'calc(100% - 40px)', // for pages with content header - }, - contentheadertabs: { - height: 'calc(100% - 97px)', // for pages with content header and tabs (Tingle) - }, - noShrink: { - flexShrink: 0, - }, - minheight300: { - minHeight: 300, - overflow: 'initial', - }, - }, - cardContent: { - widget: { - overflowY: 'auto', - height: 332, - width: '100%', - }, - fullHeight: { - height: 'calc(100% - 50px)', - }, - height100: { - height: 'calc(100% - 50px)', - }, - contentRow: { - display: 'flex', - flexDirection: 'row', - }, - }, -}; - -/** - * InfoCard is used to display a paper-styled block on the screen, similar to a panel. - * - * You can custom style an InfoCard with the 'style' (outer container) and 'cardStyle' (inner container) - * styles. - * - * The InfoCard serves as an error boundary. As a result, if you provide a 'slackChannel' property this - * specifies the channel to display in the error component that is displayed if an error occurs - * in any descendent components. - * - * By default the InfoCard has no custom layout of its children, but is treated as a block element. A - * couple common variants are provided and can be specified via the variant property: - * - * Display the card full height suitable for DataGrid: - * - * ... - * - * Variants can be combined in a whitespace delimited list like so: - * - * ... - */ -class InfoCard extends Component { - static propTypes = { - title: PropTypes.oneOfType([PropTypes.element, PropTypes.string]), - subheader: PropTypes.oneOfType([PropTypes.node, PropTypes.string]), - divider: PropTypes.bool, - deepLink: PropTypes.object, - slackChannel: PropTypes.string, - variant: PropTypes.string, - }; - - render() { - const { - title, - subheader, - divider, - deepLink, - children, - actions, - actionsTopRight, - headerStyle, - headerProps, - classes, - slackChannel, - variant, - } = this.props; - - if (this.props.style) { - console.warn('InfoCard: using `style` property directly, consider migrating your style to variant in InfoCard'); - } - if (this.props.cardStyle) { - console.warn( - 'InfoCard: using `cardStyle` property directly, consider migrating your style to variant in InfoCard', - ); - } - - /** - * If variant is specified, we build up styles for that particular variant for both - * the Card and the CardContent (since these need to be synced) - */ - let calculatedStyle = {}; - let calculatedCardStyle = {}; - - if (variant) { - let variants = variant.split(/[\s]+/g); - variants.forEach(name => { - calculatedStyle = { ...calculatedStyle, ...VARIANT_STYLES.card[name] }; - calculatedCardStyle = { ...calculatedCardStyle, ...VARIANT_STYLES.cardContent[name] }; - }); - } - - // Apply the passed styles on top - const computedStyle = { ...calculatedStyle, ...this.props.style }; - const computedCardStyle = { ...calculatedCardStyle, ...this.props.cardStyle }; - - return ( - - - {title && ( - - )} - {actionsTopRight && {actionsTopRight}} - {divider && } - - {children} - - {actions && {actions}} - {deepLink && } - - - ); - } -} - -export default InfoCard; diff --git a/frontend/packages/shared/components/InfoCard/InfoCard.test.js b/frontend/packages/shared/components/InfoCard/InfoCard.test.js deleted file mode 100644 index 88c0e08fa9..0000000000 --- a/frontend/packages/shared/components/InfoCard/InfoCard.test.js +++ /dev/null @@ -1,24 +0,0 @@ -import React from 'react'; -import { render } from '@testing-library/react'; -import { wrapInTestApp } from 'testUtils'; -import InfoCard from './InfoCard'; - -const minProps = { - title: 'Some title', - deepLink: { - title: 'A deepLink title', - link: '/mocked', - }, -}; - -describe('', () => { - it('renders without exploding', () => { - const rendered = render(wrapInTestApp()); - expect(rendered.getByText('Some title')).toBeInTheDocument(); - }); - - it('renders a deepLink when prop is set', () => { - const rendered = render(wrapInTestApp()); - expect(rendered.getByText('A deepLink title')).toBeInTheDocument(); - }); -}); diff --git a/frontend/packages/shared/components/InfoCard/index.js b/frontend/packages/shared/components/InfoCard/index.js deleted file mode 100644 index 6e402b0695..0000000000 --- a/frontend/packages/shared/components/InfoCard/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './InfoCard'; diff --git a/frontend/packages/shared/components/sidebar/README.md b/frontend/packages/shared/components/sidebar/README.md deleted file mode 100644 index bbdf730898..0000000000 --- a/frontend/packages/shared/components/sidebar/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Sidebar Components - -This is a collection of components that appear inside sidebars across the app. - -In particular, the `SidebarList` hierarchy defines some common variants of lists, that are actually -themed MUI MenuList/List components. diff --git a/frontend/packages/shared/components/sidebar/SidebarList.tsx b/frontend/packages/shared/components/sidebar/SidebarList.tsx deleted file mode 100644 index 83465eebb6..0000000000 --- a/frontend/packages/shared/components/sidebar/SidebarList.tsx +++ /dev/null @@ -1,114 +0,0 @@ -import React, { FC } from 'react'; -import { - createMuiTheme, - makeStyles, - MuiThemeProvider, - MenuList, - MenuItem, - ListItemText, - ListSubheader, - ListItemIcon, - ListItemSecondaryAction, -} from '@material-ui/core'; -import { useLocation } from 'react-router-dom'; -import { Link } from 'shared/components'; - -const themes = { - large: createMuiTheme({ - overrides: { - MuiList: { root: { outline: 'none' } }, - MuiMenuItem: { root: { lineHeight: 1 } }, - MuiListItemIcon: { root: { minWidth: 36 } }, - MuiListItemText: { primary: { fontWeight: 600 } }, - MuiListSubheader: { root: { lineHeight: 'unset', textTransform: 'uppercase', fontWeight: 'unset' } }, - MuiListItemSecondaryAction: { root: { pointerEvents: 'none' } }, - }, - }), - medium: createMuiTheme({ - overrides: { - MuiList: { root: { outline: 'none' } }, - MuiMenuItem: { root: { lineHeight: 1 }, dense: { paddingTop: 0, paddingBottom: 0 } }, - MuiListItemIcon: { root: { minWidth: 36 } }, - MuiListItemText: { primary: { fontWeight: 600 } }, - MuiListSubheader: { root: { lineHeight: 'unset', textTransform: 'uppercase', fontWeight: 'unset' } }, - MuiListItemSecondaryAction: { root: { pointerEvents: 'none' } }, - }, - }), - small: createMuiTheme({ - overrides: { - MuiList: { root: { outline: 'none' } }, - MuiMenuItem: { root: { lineHeight: 1 }, dense: { paddingTop: 0, paddingBottom: 0 } }, - MuiListItemIcon: { root: { minWidth: 36 } }, - MuiListItemText: { primary: {} }, - MuiListSubheader: { root: { lineHeight: 'unset', textTransform: 'uppercase', fontWeight: 'unset' } }, - MuiListItemSecondaryAction: { root: { pointerEvents: 'none' } }, - }, - }), -}; - -const useStyles = makeStyles(() => ({ - active: { - '&::before': { - content: "''", - position: 'absolute', - left: 0, - top: 0, - bottom: 0, - width: 4, - backgroundColor: 'green', - }, - backgroundColor: 'rgba(0, 0, 0, 0.1)', - }, -})); - -// Hook that decides if the current page location matches the given link -function useLocationMatch(linkTo?: string) { - const { pathname } = useLocation(); - - if (!linkTo) { - return false; - } else if (linkTo === '/') { - return pathname === '' || pathname === '/'; - } - - const l = linkTo.replace(/\/*$/, ''); - - return pathname === l || pathname.startsWith(`${l}/`); -} - -export type SidebarListProps = { - variant: 'large' | 'medium' | 'small'; - subheader?: string; -}; - -export type SidebarListItemProps = { - linkTo?: string; - onClick?: () => any; - icon?: React.ReactElement; - secondary?: React.ReactElement; - children: string; -}; - -export const SidebarList: FC = ({ variant, subheader, children }) => { - return ( - - {subheader} : undefined}> - {children} - - - ); -}; - -export const SidebarListItem: FC = ({ linkTo, onClick, icon, secondary, children }) => { - const classes = useStyles(); - const isActive = useLocationMatch(linkTo); - return ( - onClick && onClick()}> - - {icon ? {icon} : null} - - {secondary ? {secondary} : null} - - - ); -}; diff --git a/frontend/packages/shared/components/sidebar/common.tsx b/frontend/packages/shared/components/sidebar/common.tsx deleted file mode 100644 index 909cb22de0..0000000000 --- a/frontend/packages/shared/components/sidebar/common.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import React, { FC } from 'react'; -import { Divider as MuiDivider, Typography, IconButton, makeStyles } from '@material-ui/core'; -import BackIcon from '@material-ui/icons/ChevronLeftOutlined'; -import { useColumnStackControls } from 'shared/components/ColumnStack'; - -const useStyles = makeStyles(theme => ({ - root: { - display: 'flex', - flexDirection: 'column', - minHeight: '100%', - }, - header: { - padding: theme.spacing(1, 2, 1, 2), - }, - headerTitle: { - display: 'flex', - alignItems: 'center', - }, - spacer: { - flex: `0 0 ${theme.spacing(2)}px`, - }, - flex: { - flex: 1, - }, - backButton: { - margin: theme.spacing(0, 1, 0, -1), - }, - secondaryText: { - color: theme.palette.grey[500], - fontSize: '85%', - pointerEvents: 'none', - userSelect: 'none', - }, -})); - -export type ColumnProps = { - width: number; -}; - -export const BackButton: FC<{}> = () => { - const columnStack = useColumnStackControls(); - const classes = useStyles(); - return ( - columnStack.pop()} - size="small" - className={classes.backButton} - data-testid="sidebar-back-button" - > - - - ); -}; - -export const Column: FC = ({ width, children }) => { - const classes = useStyles(); - return ( -
- {children} -
- ); -}; - -export const Header: FC<{}> = ({ children }) => { - const classes = useStyles(); - return
{children}
; -}; - -export const HeaderTitle: FC<{}> = ({ children }) => { - const classes = useStyles(); - return ( - - {children} - - ); -}; - -export const Spacer: FC<{}> = () => { - const classes = useStyles(); - return
; -}; - -export const Flex: FC<{}> = () => { - const classes = useStyles(); - return
; -}; - -export const Divider: FC<{}> = () => ; - -export const SecondaryText: FC<{}> = ({ children }) => { - const classes = useStyles(); - return
{children}
; -}; diff --git a/frontend/packages/shared/components/sidebar/index.ts b/frontend/packages/shared/components/sidebar/index.ts deleted file mode 100644 index 28b415fbed..0000000000 --- a/frontend/packages/shared/components/sidebar/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './common'; -export * from './SidebarList'; diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 09e79a8aca..158d2029aa 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -3913,7 +3913,7 @@ babel-preset-react-app@^9.1.0: babel-plugin-macros "2.8.0" babel-plugin-transform-react-remove-prop-types "0.4.24" -babel-runtime@^6.23.0, babel-runtime@^6.26.0: +babel-runtime@6.x, babel-runtime@^6.23.0, babel-runtime@^6.26.0: version "6.26.0" resolved "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= @@ -4563,6 +4563,11 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" +classnames@^2.2.6: + version "2.2.6" + resolved "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" + integrity sha1-Q5Nb/90pHzJtrQogUwmzjQD2UM4= + clean-css@4.2.x: version "4.2.3" resolved "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" @@ -13185,7 +13190,7 @@ promzard@^0.3.0: dependencies: read "1" -prop-types@^15.5.4, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@^15.5.4, prop-types@^15.5.8, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -13385,6 +13390,14 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" +rc-progress@^2.5.2: + version "2.5.2" + resolved "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/rc-progress/-/rc-progress-2.5.2.tgz#ab01ba4e5d2fa36fc9f6f058b10b720e7315560c" + integrity sha1-qwG6Tl0vo2/J9vBYsQtyDnMVVgw= + dependencies: + babel-runtime "6.x" + prop-types "^15.5.8" + rc@^1.0.1, rc@^1.1.6, rc@^1.2.8: version "1.2.8" resolved "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" @@ -15724,7 +15737,7 @@ ts-protoc-gen@^0.12.0: dependencies: google-protobuf "^3.6.1" -tslib@^1.8.1, tslib@^1.9.0: +tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0: version "1.10.0" resolved "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==