diff --git a/client/components/AutocompleteInputBox/AutocompleteInputBox.tsx b/client/components/AutocompleteInputBox/AutocompleteInputBox.tsx index 4abcce90..e2bdae0f 100644 --- a/client/components/AutocompleteInputBox/AutocompleteInputBox.tsx +++ b/client/components/AutocompleteInputBox/AutocompleteInputBox.tsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react' +import React from 'react' import cx from 'classnames' import { WithClassName } from '../../../types' @@ -8,18 +8,15 @@ type AutocompleteInputBoxProps = React.PropsWithChildren & footer?: React.ReactNode } -class AutocompleteInputBox extends Component { - render() { - const { children, footer, className } = this.props - return ( -
- {children} - {footer && ( -
{footer}
- )} -
- ) - } +export function AutocompleteInputBox({ + children, + footer, + className, +}: AutocompleteInputBoxProps) { + return ( +
+ {children} + {footer &&
{footer}
} +
+ ) } - -export default AutocompleteInputBox diff --git a/client/components/AutocompleteInputBox/index.ts b/client/components/AutocompleteInputBox/index.ts index e7dfe149..f2405de7 100644 --- a/client/components/AutocompleteInputBox/index.ts +++ b/client/components/AutocompleteInputBox/index.ts @@ -1,3 +1 @@ -import AutocompleteInputBox from './AutocompleteInputBox' - -export default AutocompleteInputBox +export { AutocompleteInputBox } from './AutocompleteInputBox' diff --git a/client/components/BarGraph/BarGraph.tsx b/client/components/BarGraph/BarGraph.tsx index 96498920..5819aefc 100644 --- a/client/components/BarGraph/BarGraph.tsx +++ b/client/components/BarGraph/BarGraph.tsx @@ -1,73 +1,70 @@ -import React, { PureComponent } from 'react' +import React, { useMemo } from 'react' import { formatSize } from '../../../utils' import TreeShakeIcon from '../Icons/TreeShakeIcon' import SideEffectIcon from '../Icons/SideEffectIcon' -import { BarVersion } from '../BarVersion/BarVersion' +import { BarVersion } from '../BarVersion' +import { Reading } from './types' +import { useBarGraph } from './hooks/useBarGraph' -export type Reading = { - version: string - size: number - gzip: number - disabled: boolean - hasSideEffects: boolean - hasJSModule: boolean - hasJSNext: boolean - isModuleType: boolean -} - -type BarGraphProps = { +interface BarGraphProps { readings: Reading[] onBarClick: (reading: Reading) => void } -export default class BarGraph extends PureComponent { - getScale = () => { - const { readings } = this.props - - const gzipValues = readings - .filter(reading => !reading.disabled) - .map(reading => reading.gzip) - - const sizeValues = readings - .filter(reading => !reading.disabled) - .map(reading => reading.size) - - const maxValue = Math.max(...[...gzipValues, ...sizeValues]) - return 100 / maxValue - } - - getFirstSideEffectFreeIndex = () => { - const { readings } = this.props - const sideEffectFreeIntroducedRecently = !readings.every( - reading => !reading.hasSideEffects - ) - const firstSideEffectFreeIndex = readings.findIndex( - reading => !(reading.disabled || reading.hasSideEffects) - ) - - return sideEffectFreeIntroducedRecently ? firstSideEffectFreeIndex : -1 - } - - getFirstTreeshakeableIndex = () => { - const { readings } = this.props - const treeshakingIntroducedRecently = !readings.every( - reading => reading.hasJSModule - ) - const firstTreeshakingIndex = readings.findIndex( - reading => - !reading.disabled && - (reading.hasJSModule || reading.hasJSNext || reading.isModuleType) - ) +export function BarGraph({ onBarClick, readings }: BarGraphProps) { + const { firstSideEffectFreeIndex, firstTreeshakeableIndex, graphScale } = + useBarGraph({ readings }) + + return ( +
+
+ {readings.map((reading, index) => + reading.disabled ? ( + + ) : ( + + ) + )} +
+
+
+
+ Min +
+
+
+ GZIP +
+
+
+ ) +} - return treeshakingIntroducedRecently ? firstTreeshakingIndex : -1 - } +interface DisabledBarProps { + reading: Reading + onBarClick: (reading: Reading) => void +} - renderDisabledBar = (reading: Reading) => ( +function DisabledBar({ reading, onBarClick }: DisabledBarProps) { + return (
this.props.onBarClick(reading)} + onClick={() => onBarClick(reading)} >
{
) +} - renderActiveBar = ( - reading: Reading, - scale: number, - options: { isFirstTreeshakeable: boolean; isFirstSideEffectFree: boolean } - ) => { - const getTooltipMessage = (reading: Reading) => { - const formattedSize = formatSize(reading.size) - const formattedGzip = formatSize(reading.gzip) - return `Minified: ${parseFloat(formattedSize.size).toFixed(1)}${ - formattedSize.unit - } | Gzipped: ${parseFloat(formattedGzip.size).toFixed(1)}${ - formattedGzip.unit - }` - } - - return ( -
this.props.onBarClick(reading)} - key={reading.version} - className="bar-graph__bar-group" - > -
- {options.isFirstTreeshakeable && ( -
- -
- )} - {options.isFirstSideEffectFree && ( -
- -
- )} -
- -
-
- -
- ) - } - - render() { - const { readings } = this.props - const graphScale = this.getScale() - const firstTreeshakeableIndex = this.getFirstTreeshakeableIndex() - const firstSideEffectFreeIndex = this.getFirstSideEffectFreeIndex() +interface ActiveBarProps { + reading: Reading + graphScale: number + options: { isFirstTreeshakeable: boolean; isFirstSideEffectFree: boolean } + onBarClick: (reading: Reading) => void +} - return ( -
-
- {readings.map((reading, index) => - reading.disabled - ? this.renderDisabledBar(reading) - : this.renderActiveBar(reading, graphScale, { - isFirstTreeshakeable: index === firstTreeshakeableIndex, - isFirstSideEffectFree: index === firstSideEffectFreeIndex, - }) - )} -
-
-
-
- Min +function ActiveBar({ + reading, + options, + graphScale, + onBarClick, +}: ActiveBarProps) { + const tooltipMessage = useMemo(() => { + const formattedSize = formatSize(reading.size) + const formattedGzip = formatSize(reading.gzip) + return `Minified: ${parseFloat(formattedSize.size).toFixed(1)}${ + formattedSize.unit + } | Gzipped: ${parseFloat(formattedGzip.size).toFixed(1)}${ + formattedGzip.unit + }` + }, [reading]) + + return ( +
onBarClick(reading)} + key={reading.version} + className="bar-graph__bar-group" + > +
+ {options.isFirstTreeshakeable && ( +
+
-
-
- GZIP + )} + {options.isFirstSideEffectFree && ( +
+
-
+ )}
- ) - } + +
+
+ +
+ ) } diff --git a/client/components/BarGraph/hooks/useBarGraph.ts b/client/components/BarGraph/hooks/useBarGraph.ts new file mode 100644 index 00000000..d09d50d7 --- /dev/null +++ b/client/components/BarGraph/hooks/useBarGraph.ts @@ -0,0 +1,43 @@ +import { useMemo } from 'react' +import { Reading } from '../types' + +export function useBarGraph({ readings }: { readings: Reading[] }) { + const graphScale = useMemo(() => { + const gzipValues = readings + .filter(reading => !reading.disabled) + .map(reading => reading.gzip) + + const sizeValues = readings + .filter(reading => !reading.disabled) + .map(reading => reading.size) + + const maxValue = Math.max(...[...gzipValues, ...sizeValues]) + return 100 / maxValue + }, [readings]) + + const firstSideEffectFreeIndex = useMemo(() => { + const sideEffectFreeIntroducedRecently = !readings.every( + reading => !reading.hasSideEffects + ) + const firstSideEffectFreeIndex = readings.findIndex( + reading => !(reading.disabled || reading.hasSideEffects) + ) + + return sideEffectFreeIntroducedRecently ? firstSideEffectFreeIndex : -1 + }, [readings]) + + const firstTreeshakeableIndex = useMemo(() => { + const treeshakingIntroducedRecently = !readings.every( + reading => reading.hasJSModule + ) + const firstTreeshakingIndex = readings.findIndex( + reading => + !reading.disabled && + (reading.hasJSModule || reading.hasJSNext || reading.isModuleType) + ) + + return treeshakingIntroducedRecently ? firstTreeshakingIndex : -1 + }, [readings]) + + return { graphScale, firstSideEffectFreeIndex, firstTreeshakeableIndex } +} diff --git a/client/components/BarGraph/index.ts b/client/components/BarGraph/index.ts index 2b1f44da..b0466a6f 100644 --- a/client/components/BarGraph/index.ts +++ b/client/components/BarGraph/index.ts @@ -1,3 +1 @@ -import BarGraph from './BarGraph' - -export default BarGraph +export { BarGraph } from './BarGraph' diff --git a/client/components/BarGraph/types.ts b/client/components/BarGraph/types.ts new file mode 100644 index 00000000..97a21816 --- /dev/null +++ b/client/components/BarGraph/types.ts @@ -0,0 +1,10 @@ +export type Reading = { + version: string + size: number + gzip: number + disabled: boolean + hasSideEffects: boolean + hasJSModule: boolean + hasJSNext: boolean + isModuleType: boolean +} diff --git a/client/components/BarVersion/index.ts b/client/components/BarVersion/index.ts new file mode 100644 index 00000000..f0858442 --- /dev/null +++ b/client/components/BarVersion/index.ts @@ -0,0 +1 @@ +export { BarVersion } from './BarVersion' diff --git a/client/components/BlogLayout/BlogLayout.tsx b/client/components/BlogLayout/BlogLayout.tsx index 3f1fced0..907d75d2 100644 --- a/client/components/BlogLayout/BlogLayout.tsx +++ b/client/components/BlogLayout/BlogLayout.tsx @@ -1,14 +1,12 @@ import React from 'react' import { WithClassName } from '../../../types' -import ResultLayout from '../ResultLayout' +import { ResultLayout } from '../ResultLayout' type BlogLayoutProps = React.PropsWithChildren & WithClassName -const BlogLayout = ({ className, children }: BlogLayoutProps) => ( +export const BlogLayout = ({ className, children }: BlogLayoutProps) => (
{children}
) - -export default BlogLayout diff --git a/client/components/BlogLayout/index.ts b/client/components/BlogLayout/index.ts index d14384f2..f36f9379 100644 --- a/client/components/BlogLayout/index.ts +++ b/client/components/BlogLayout/index.ts @@ -1 +1 @@ -export { default } from './BlogLayout' +export { BlogLayout } from './BlogLayout' diff --git a/client/components/BuildProgressIndicator/BuildProgressIndicator.tsx b/client/components/BuildProgressIndicator/BuildProgressIndicator.tsx index 7e34432a..8b1c76db 100644 --- a/client/components/BuildProgressIndicator/BuildProgressIndicator.tsx +++ b/client/components/BuildProgressIndicator/BuildProgressIndicator.tsx @@ -1,6 +1,6 @@ -import React, { Component } from 'react' +import React, { useCallback, useEffect, useRef, useState } from 'react' -import ProgressHex from '../ProgressHex' +import { ProgressHex } from '../ProgressHex' const OptimisticLoadTimeout = 700 @@ -9,66 +9,18 @@ type BuildProgressIndicatorProps = { onDone: () => void } -type BuildProgressIndicatorState = { - started: boolean - progressText?: string -} - const order = ['resolving', 'building', 'minifying', 'calculating'] as const -export default class BuildProgressIndicator extends Component< - BuildProgressIndicatorProps, - BuildProgressIndicatorState -> { - stage: number - timeoutId?: ReturnType - - constructor(props: BuildProgressIndicatorProps) { - super(props) - this.stage = 0 - this.state = { - started: false, - } - } - - componentDidMount() { - setTimeout(() => { - if (!this.props.isDone) { - this.setState({ started: true }) - this.setMessage() - } - }, OptimisticLoadTimeout) - } - - componentWillReceiveProps(nextProps: BuildProgressIndicatorProps) { - if (nextProps.isDone) { - this.stage = 3 - this.props.onDone() - } - } - - shouldComponentUpdate( - props: BuildProgressIndicatorProps, - nextState: BuildProgressIndicatorState - ) { - return this.state.progressText !== nextState.progressText - } - - componentWillUnmount() { - clearTimeout(this.timeoutId) - } - - getProgressText = (stage: typeof order[number]) => { - const progressText = { - resolving: 'Resolving version and dependencies', - building: 'Bundling package', - minifying: 'Minifying, GZipping', - calculating: 'Calculating file sizes', - } - return progressText[stage] - } +export function BuildProgressIndicator({ + isDone, + onDone, +}: BuildProgressIndicatorProps) { + const timeout = useRef() + const [stage, setStage] = useState(0) + const [started, setStarted] = useState(false) + const [progressText, setProgressText] = useState(null) - setMessage = (stage = 0) => { + const setMessage = useCallback((stage = 0) => { const timings = { resolving: 3 + Math.random() * 2, building: 5 + Math.random() * 3, @@ -76,35 +28,57 @@ export default class BuildProgressIndicator extends Component< calculating: 20, } - if (this.stage === order.length) { - //this.props.onDone() - return - } + if (stage === order.length) return - this.setState({ - progressText: this.getProgressText(order[this.stage]), - }) + setProgressText(getProgressText(order[stage])) - this.timeoutId = setTimeout(() => { - if (this.stage < order.length) { - this.stage += 1 + timeout.current = setTimeout(() => { + if (stage < order.length) { + stage += 1 } - this.setMessage(this.stage) + setMessage(stage) }, timings[order[stage]] * 1000) - } + }, []) - render() { - const { progressText, started } = this.state - if (!started) { - return null + useEffect(() => { + setTimeout(() => { + if (!isDone) { + setStarted(true) + setMessage() + } + }, OptimisticLoadTimeout) + }, [isDone, setMessage]) + + useEffect(() => { + if (isDone) { + setStage(3) + onDone() + } + }, [isDone, onDone]) + + useEffect(() => { + return () => { + clearTimeout(timeout.current) } + }, []) + + if (!started) return null + + return ( +
+ +

{progressText}

+
+ ) +} - return ( -
- -

{progressText}

-
- ) +function getProgressText(stage: typeof order[number]) { + const progressText = { + resolving: 'Resolving version and dependencies', + building: 'Bundling package', + minifying: 'Minifying, GZipping', + calculating: 'Calculating file sizes', } + return progressText[stage] } diff --git a/client/components/BuildProgressIndicator/index.ts b/client/components/BuildProgressIndicator/index.ts index 6192fda0..98d892d7 100644 --- a/client/components/BuildProgressIndicator/index.ts +++ b/client/components/BuildProgressIndicator/index.ts @@ -1,3 +1 @@ -import BuildProgressIndicator from './BuildProgressIndicator' - -export default BuildProgressIndicator +export { BuildProgressIndicator } from './BuildProgressIndicator' diff --git a/client/components/Header/Header.tsx b/client/components/Header/Header.tsx index 0c2b6db9..fe047109 100644 --- a/client/components/Header/Header.tsx +++ b/client/components/Header/Header.tsx @@ -12,7 +12,8 @@ type HeaderState = { sidebarOpen: boolean } -export default class Header extends Component { +// TODO: this is not use, can be removed? +export class Header extends Component { mql!: MediaQueryList constructor(props: HeaderProps) { @@ -84,7 +85,11 @@ export default class Header extends Component { - + diff --git a/client/components/Header/index.ts b/client/components/Header/index.ts index 7cd29d7a..e0e2673a 100644 --- a/client/components/Header/index.ts +++ b/client/components/Header/index.ts @@ -1,3 +1 @@ -import Header from './Header' - -export default Header +export { Header } from './Header' diff --git a/client/components/JumpingDots/JumpingDots.tsx b/client/components/JumpingDots/JumpingDots.tsx index df10d85b..8d6f6c5b 100644 --- a/client/components/JumpingDots/JumpingDots.tsx +++ b/client/components/JumpingDots/JumpingDots.tsx @@ -1,6 +1,6 @@ import React from 'react' -export default function JumpingDots() { +export function JumpingDots() { return ( diff --git a/client/components/JumpingDots/index.ts b/client/components/JumpingDots/index.ts index 17496e84..56c271e7 100644 --- a/client/components/JumpingDots/index.ts +++ b/client/components/JumpingDots/index.ts @@ -1 +1 @@ -export { default } from './JumpingDots' +export { JumpingDots } from './JumpingDots' diff --git a/client/components/Layout/Layout.tsx b/client/components/Layout/Layout.tsx index a3ad0d77..a88da717 100644 --- a/client/components/Layout/Layout.tsx +++ b/client/components/Layout/Layout.tsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react' +import React, { Component, useEffect, useState } from 'react' import Link from 'next/link' import API from '../../api' @@ -8,96 +8,93 @@ import { WithClassName } from '../../../types' type LayoutProps = React.PropsWithChildren & WithClassName -type LayoutState = { - recentSearches: string[] -} - -export default class Layout extends Component { - state = { - recentSearches: [], - } +export function Layout({ children, className }: LayoutProps) { + const [recentSearches, setRecentSearches] = useState([]) - componentDidMount() { + useEffect(() => { API.getRecentSearches(5).then(searches => { - this.setState({ - recentSearches: Object.keys(searches), - }) + setRecentSearches(Object.keys(searches)) }) - } + }, []) - render() { - const { children, className } = this.props - const { recentSearches } = this.state + return ( +
+
{children}
- return ( -
-
{children}
- -
-
-
-

Recent searches

-
    - {recentSearches.map(search => ( -
  • - {search} -
  • - ))} -
-
+
+
+
+

Recent searches

+
    + {recentSearches.map(search => ( +
  • + {search} +
  • + ))} +
-
-
-

What does Bundlephobia do?

-

- JavaScript bloat is more real today than it ever was. Sites - continuously get bigger as more (often redundant) libraries are - thrown to solve new problems. Until of-course, the{' '} - big rewrite - happens. -

-

- Bundlephobia lets you understand the performance cost of - npm install ing a new npm package before it - becomes a part of your bundle. Analyze size, compositions and - exports -

-

- Credits to{' '} - - {' '} - @thekitze{' '} - - for the name. -

-
- Hosted on - - - -
-
-
- ️ +
+
+
+

What does Bundlephobia do?

+

+ JavaScript bloat is more real today than it ever was. Sites + continuously get bigger as more (often redundant) libraries are + thrown to solve new problems. Until of-course, the{' '} + big rewrite + happens. +

+

+ Bundlephobia lets you understand the performance cost of + npm install ing a new npm package before it + becomes a part of your bundle. Analyze size, compositions and + exports +

+

+ Credits to{' '} - @pastelsky + {' '} + @thekitze{' '} + for the name. +

+ -
-
-
- ) - } +
+ + + + + ) } diff --git a/client/components/Layout/index.ts b/client/components/Layout/index.ts index edae7904..358469a0 100644 --- a/client/components/Layout/index.ts +++ b/client/components/Layout/index.ts @@ -1,3 +1 @@ -import Layout from './Layout' - -export default Layout +export { Layout } from './Layout' diff --git a/client/components/MetaTags.tsx b/client/components/MetaTags.tsx index 1352226b..b8ea9dcb 100644 --- a/client/components/MetaTags.tsx +++ b/client/components/MetaTags.tsx @@ -13,7 +13,7 @@ type MetaTagsProps = { isLargeImage?: boolean } -export default function MetaTags({ +export function MetaTags({ description, twitterDescription, title, diff --git a/client/components/PageNav/PageNav.tsx b/client/components/PageNav/PageNav.tsx index 9a36c1bf..5a8ba87f 100644 --- a/client/components/PageNav/PageNav.tsx +++ b/client/components/PageNav/PageNav.tsx @@ -6,7 +6,7 @@ type PageNavProps = { minimal?: boolean } -const PageNav = ({ minimal }: PageNavProps) => ( +export const PageNav = ({ minimal }: PageNavProps) => (
{!minimal && (
@@ -47,11 +47,13 @@ const PageNav = ({ minimal }: PageNavProps) => ( )} - +
) - -export default PageNav diff --git a/client/components/PageNav/index.ts b/client/components/PageNav/index.ts index ad8b65ae..85f3d530 100644 --- a/client/components/PageNav/index.ts +++ b/client/components/PageNav/index.ts @@ -1 +1 @@ -export { default } from './PageNav' +export { PageNav } from './PageNav' diff --git a/client/components/ProgressHex/ProgressHex.tsx b/client/components/ProgressHex/ProgressHex.tsx index 4bfe1dab..76a399bb 100644 --- a/client/components/ProgressHex/ProgressHex.tsx +++ b/client/components/ProgressHex/ProgressHex.tsx @@ -1,117 +1,105 @@ -import React, { Component } from 'react' +import React, { Component, useEffect, useReducer, useRef } from 'react' import ProgressHexAnimator from './progress-hex-timeline' -type ProgressHexProps = { +interface ProgressHexProps { compact?: boolean } -class ProgressHex extends Component { - svgRef: React.RefObject - animator?: ProgressHexAnimator - timeline?: ReturnType +export function ProgressHex({ compact }: ProgressHexProps) { + const svgRef = useRef(null) - constructor(props: ProgressHexProps) { - super(props) - this.svgRef = React.createRef() - } + useEffect(() => { + const animator = new ProgressHexAnimator({ svg: svgRef.current! }) + const timeline = animator.createTimeline() + timeline.play() - componentDidMount() { - this.animator = new ProgressHexAnimator({ svg: this.svgRef.current! }) - this.timeline = this.animator.createTimeline() - this.timeline.play() - } + return () => { + timeline.pause() + } + }, []) - componentWillUnmount() { - this.timeline?.pause() - } - - render() { - const { compact } = this.props - return ( - - {!compact && ( - - - - - - - - - - - - - - - - - - - - - - - - - - - )} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + return ( + + {!compact && ( + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - ) - } + )} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) } - -export default ProgressHex diff --git a/client/components/ProgressHex/index.ts b/client/components/ProgressHex/index.ts index 6252fc9d..efdaa9ff 100644 --- a/client/components/ProgressHex/index.ts +++ b/client/components/ProgressHex/index.ts @@ -1 +1 @@ -export { default } from './ProgressHex' +export { ProgressHex } from './ProgressHex' diff --git a/client/components/QuickStatsBar/QuickStatsBar.tsx b/client/components/QuickStatsBar/QuickStatsBar.tsx index f9ff11a8..57954e3a 100644 --- a/client/components/QuickStatsBar/QuickStatsBar.tsx +++ b/client/components/QuickStatsBar/QuickStatsBar.tsx @@ -19,7 +19,7 @@ type QuickStatsBarProps = Pick< | 'hasSideEffects' > -class QuickStatsBar extends Component { +export class QuickStatsBar extends Component { static defaultProps = { description: '', } @@ -127,5 +127,3 @@ class QuickStatsBar extends Component { ) } } - -export default QuickStatsBar diff --git a/client/components/QuickStatsBar/index.ts b/client/components/QuickStatsBar/index.ts index 8a9ed344..30dd2ecb 100644 --- a/client/components/QuickStatsBar/index.ts +++ b/client/components/QuickStatsBar/index.ts @@ -1,3 +1 @@ -import QuickStatsBar from './QuickStatsBar' - -export default QuickStatsBar +export { QuickStatsBar } from './QuickStatsBar' diff --git a/client/components/ResultLayout/ResultLayout.tsx b/client/components/ResultLayout/ResultLayout.tsx index 316e7f03..472b90f0 100644 --- a/client/components/ResultLayout/ResultLayout.tsx +++ b/client/components/ResultLayout/ResultLayout.tsx @@ -1,22 +1,19 @@ -import React, { Component } from 'react' +import React from 'react' import cx from 'classnames' -import Layout from '../../components/Layout' -import PageNav from '../PageNav' +import { Layout } from '../../components/Layout' +import { PageNav } from '../PageNav' import { WithClassName } from '../../../types' -export default class ResultLayout extends Component< - React.PropsWithChildren & WithClassName -> { - render() { - const { children, className } = this.props - return ( - -
- -
{children}
-
-
- ) - } +type ResultLayoutProps = React.PropsWithChildren + +export function ResultLayout({ children, className }: ResultLayoutProps) { + return ( + +
+ +
{children}
+
+
+ ) } diff --git a/client/components/ResultLayout/index.ts b/client/components/ResultLayout/index.ts index 6f02c3c2..bbbb469a 100644 --- a/client/components/ResultLayout/index.ts +++ b/client/components/ResultLayout/index.ts @@ -1,3 +1 @@ -import ResultLayout from './ResultLayout' - -export default ResultLayout +export { ResultLayout } from './ResultLayout' diff --git a/client/components/Separator.tsx b/client/components/Separator.tsx index 0dd19aaf..82bc59f7 100644 --- a/client/components/Separator.tsx +++ b/client/components/Separator.tsx @@ -7,7 +7,7 @@ type SeparatorProps = { containerStyles?: React.CSSProperties } -export default function Separator({ +export function Separator({ text = 'or', align = 'center', showLeft = true, diff --git a/client/components/SimilarPackageCard/SimilarPackageCard.tsx b/client/components/SimilarPackageCard/SimilarPackageCard.tsx index a2000724..a23aba26 100644 --- a/client/components/SimilarPackageCard/SimilarPackageCard.tsx +++ b/client/components/SimilarPackageCard/SimilarPackageCard.tsx @@ -14,129 +14,131 @@ type SimilarPackageCardProps = { category?: string } & ( | { isEmpty: true } ) -export default class SimilarPackageCard extends Component { - getSuggestionIssueUrl = () => { +export function SimilarPackageCard({ + category, + ...props +}: SimilarPackageCardProps) { + const getSuggestionIssueUrl = () => { const params = queryString.stringify({ labels: 'similar suggestion', template: '2-similar-package-suggestion.md', - title: `Package suggestion: for \`${this.props.category}\``, + title: `Package suggestion: for \`${category}\``, }) return `https://github.com/pastelsky/bundlephobia/issues/new?${params}` } - render() { - if ('isEmpty' in this.props) { - return ( - -
- -

Suggest another

-
-
- ) - } - - const { pack, comparisonSizePercent } = this.props - const { size, unit } = formatSize(pack.gzip) - const sizeDiff = Math.abs( - (comparisonSizePercent / 100) * pack.gzip - pack.gzip + if ('isEmpty' in props) { + return ( + +
+ +

Suggest another

+
+
) + } - const getComparisonNumber = (comparisonSizePercent: number) => { - if (sizeDiff < 1500) { - return ( -
-
- Similar
size -
+ const { size, unit } = formatSize(props.pack.gzip) + const sizeDiff = Math.abs( + (props.comparisonSizePercent / 100) * props.pack.gzip - props.pack.gzip + ) + + const getComparisonNumber = (comparisonSizePercent: number) => { + if (sizeDiff < 1500) { + return ( +
+
+ Similar
size
- ) - } else if (Math.abs(comparisonSizePercent) > 100) { - return ( -
-
- {(1 + Math.abs(comparisonSizePercent) / 100).toFixed(1)}{' '} - × -
-
- {comparisonSizePercent > 0 ? 'Larger' : 'Smaller'} -
+
+ ) + } else if (Math.abs(comparisonSizePercent) > 100) { + return ( +
+
+ {(1 + Math.abs(comparisonSizePercent) / 100).toFixed(1)}{' '} + ×
- ) - } else { - return ( -
-
- {Math.abs(comparisonSizePercent).toFixed(0)}{' '} - % -
-
- {comparisonSizePercent > 0 ? 'Larger' : 'Smaller'} -
+
+ {comparisonSizePercent > 0 ? 'Larger' : 'Smaller'}
- ) - } - } - - const footer = ( -
-
0, - })} - > - {getComparisonNumber(comparisonSizePercent)}
-
+ ) + } else { + return ( +
- {size.toFixed(2)} - {unit} + {Math.abs(comparisonSizePercent).toFixed(0)}{' '} + % +
+
+ {comparisonSizePercent > 0 ? 'Larger' : 'Smaller'}
-
Min + Gzip
+ ) + } + } - {(pack.hasJSModule || pack.hasJSNext || pack.isModuleType) && ( - - )} + const footer = ( +
+
0, + })} + > + {getComparisonNumber(props.comparisonSizePercent)} +
+
+
+ {size.toFixed(2)} + {unit} +
+
Min + Gzip
- ) - return ( - -
- -

+ {(props.pack.hasJSModule || + props.pack.hasJSNext || + props.pack.isModuleType) && ( + + )} +

+ ) + + return ( + +
+
+

{props.pack.name}

+ {props.pack.repository && ( + { + e.stopPropagation() + window.location = props.pack.repository + }} + > + + + )}
- {footer} - - ) - } +

+

+ {footer} + + ) } diff --git a/client/components/SimilarPackageCard/index.ts b/client/components/SimilarPackageCard/index.ts index 0d7f3f71..a6054471 100644 --- a/client/components/SimilarPackageCard/index.ts +++ b/client/components/SimilarPackageCard/index.ts @@ -1,3 +1 @@ -import SimilarPackageCard from './SimilarPackageCard' - -export default SimilarPackageCard +export { SimilarPackageCard } from './SimilarPackageCard' diff --git a/client/components/Stat/Stat.tsx b/client/components/Stat/Stat.tsx index 785ca7a3..dbaede1b 100644 --- a/client/components/Stat/Stat.tsx +++ b/client/components/Stat/Stat.tsx @@ -17,7 +17,7 @@ type StatProps = WithClassName & { compact?: boolean } -export default function Stat({ +export function Stat({ value, label, type, diff --git a/client/components/Stat/index.ts b/client/components/Stat/index.ts index 13c3dedd..7811bc7e 100644 --- a/client/components/Stat/index.ts +++ b/client/components/Stat/index.ts @@ -1 +1 @@ -export { default } from './Stat' +export { Stat } from './Stat' diff --git a/client/components/Treemap/Treemap.tsx b/client/components/Treemap/Treemap.tsx index df7ceed4..a1bec677 100644 --- a/client/components/Treemap/Treemap.tsx +++ b/client/components/Treemap/Treemap.tsx @@ -8,7 +8,7 @@ type TreeMapProps = { } & React.PropsWithChildren & React.HTMLAttributes -class TreeMap extends Component { +export class TreeMap extends Component { render() { const { width, height, children, ...others } = this.props @@ -59,5 +59,3 @@ class TreeMap extends Component { ) } } - -export default TreeMap diff --git a/client/components/Treemap/TreemapSquare.tsx b/client/components/Treemap/TreemapSquare.tsx index 95b00d42..b30c601f 100644 --- a/client/components/Treemap/TreemapSquare.tsx +++ b/client/components/Treemap/TreemapSquare.tsx @@ -9,7 +9,7 @@ type TreemapSquareProps = { 'left' | 'top' | 'width' | 'height' | 'borderRadius' > -function TreemapSquare({ +export function TreemapSquare({ children, left, top, @@ -44,5 +44,3 @@ function TreemapSquare({
) } - -export default TreemapSquare diff --git a/client/components/Treemap/index.ts b/client/components/Treemap/index.ts index 309a279b..23d3570c 100644 --- a/client/components/Treemap/index.ts +++ b/client/components/Treemap/index.ts @@ -1,4 +1,2 @@ -import Treemap from './Treemap' -import TreemapSquare from './TreemapSquare' - -export { Treemap, TreemapSquare } +export { TreeMap } from './Treemap' +export { TreemapSquare } from './TreemapSquare' diff --git a/client/components/Warning/Warning.tsx b/client/components/Warning/Warning.tsx index 4842f7d0..a152ddf8 100644 --- a/client/components/Warning/Warning.tsx +++ b/client/components/Warning/Warning.tsx @@ -1,9 +1,7 @@ import React, { Component } from 'react' -class Warning extends Component { +export class Warning extends Component { render() { return
{this.props.children}
} } - -export default Warning diff --git a/client/components/Warning/index.ts b/client/components/Warning/index.ts index 60da752b..437882fc 100644 --- a/client/components/Warning/index.ts +++ b/client/components/Warning/index.ts @@ -1 +1 @@ -export { default } from './Warning' +export { Warning } from './Warning' diff --git a/package.json b/package.json index d9c0bd0f..84305a18 100644 --- a/package.json +++ b/package.json @@ -137,6 +137,7 @@ "@types/react-autocomplete": "^1.8.6", "@types/react-dom": "^18.0.8", "@types/react-sidebar": "^3.0.2", + "@types/semver": "^7.3.13", "autoprefixer": "^9.8.6", "eslint": "^8.26.0", "eslint-config-next": "^13.0.1", diff --git a/pages/blog/components/Article.tsx b/pages/blog/components/Article.tsx index e27e795a..17aacb1b 100644 --- a/pages/blog/components/Article.tsx +++ b/pages/blog/components/Article.tsx @@ -1,6 +1,6 @@ import { useRouter } from 'next/router' import React from 'react' -import BlogLayout from '../../../client/components/BlogLayout' +import { BlogLayout } from '../../../client/components/BlogLayout' import { useContentful } from 'react-contentful' import BlogPost from './Post' import ContentfulProvider from './ContentfulProvider' diff --git a/pages/blog/index.page.tsx b/pages/blog/index.page.tsx index 6dfe932e..efe6c01c 100644 --- a/pages/blog/index.page.tsx +++ b/pages/blog/index.page.tsx @@ -1,7 +1,7 @@ import React from 'react' -import BlogLayout from '../../client/components/BlogLayout' +import { BlogLayout } from '../../client/components/BlogLayout' import { useContentful } from 'react-contentful' -import Separator from '../../client/components/Separator' +import { Separator } from '../../client/components/Separator' import Post from './components/Post' import ContentfulProvider from './components/ContentfulProvider' diff --git a/pages/compare/ComparePage.js b/pages/compare/ComparePage.js index e2ad4dbc..cac067ab 100644 --- a/pages/compare/ComparePage.js +++ b/pages/compare/ComparePage.js @@ -1,19 +1,14 @@ import React, { PureComponent } from 'react' -import Head from 'next/head' -import Layout from '../../client/components/Layout' -import BarGraph from '../../client/components/BarGraph' -import AutocompleteInput from '../../client/components/AutocompleteInput' -import BuildProgressIndicator from '../../client/components/BuildProgressIndicator' +import { Layout } from '../../client/components/Layout' +import { AutocompleteInput } from '../../client/components/AutocompleteInput' import Router from 'next/router' import Link from 'next/link' import isEmptyObject from 'is-empty-object' -import { parsePackageString } from '../../utils/common.utils' import API from '../../client/api' import GithubLogo from '../../client/assets/github-logo.svg' -import EmptyBox from '../../client/assets/empty-box.svg' export default class ResultPage extends PureComponent { fetchResults = packageString => { diff --git a/pages/index.page.tsx b/pages/index.page.tsx index 7c510dbf..74a479bb 100644 --- a/pages/index.page.tsx +++ b/pages/index.page.tsx @@ -4,10 +4,10 @@ import Link from 'next/link' import Analytics from '../client/analytics' import { AutocompleteInput } from '../client/components/AutocompleteInput' -import AutocompleteInputBox from '../client/components/AutocompleteInputBox/AutocompleteInputBox' -import Layout from '../client/components/Layout' -import MetaTags from '../client/components/MetaTags' -import PageNav from '../client/components/PageNav' +import { AutocompleteInputBox } from '../client/components/AutocompleteInputBox' +import { Layout } from '../client/components/Layout' +import { MetaTags } from '../client/components/MetaTags' +import { PageNav } from '../client/components/PageNav' const Logo = () => ( (this.treemapSection = ts)} >

Composition

- + {compactedDependencies.map((dep, index) => ( ))} - +

Note: These sizes represent the contribution made by dependencies (direct or transitive) to {packageName} diff --git a/pages/scan-results/ScanResults.js b/pages/scan-results/ScanResults.js index 8c8b5196..a30492bd 100644 --- a/pages/scan-results/ScanResults.js +++ b/pages/scan-results/ScanResults.js @@ -6,9 +6,9 @@ import cx from 'classnames' const PromiseQueue = require('p-queue') const queryString = require('query-string') -import Stat from '../../client/components/Stat' +import { Stat } from '../../client/components/Stat' import Link from 'next/link' -import ResultLayout from '../../client/components/ResultLayout' +import { ResultLayout } from '../../client/components/ResultLayout' import { parsePackageString } from '../../utils/common.utils' import API from '../../client/api' diff --git a/pages/scan/Scan.js b/pages/scan/Scan.js index 112a6a4a..154eee94 100644 --- a/pages/scan/Scan.js +++ b/pages/scan/Scan.js @@ -1,8 +1,8 @@ import React, { Component } from 'react' import Analytics from '../../client/analytics' -import ResultLayout from '../../client/components/ResultLayout' -import Separator from '../../client/components/Separator' -import MetaTags from '../../client/components/MetaTags' +import { ResultLayout } from '../../client/components/ResultLayout' +import { Separator } from '../../client/components/Separator' +import { MetaTags } from '../../client/components/MetaTags' import scanBlacklist from '../../client/config/scanBlacklist' import Dropzone from 'react-dropzone' import Router from 'next/router' diff --git a/yarn.lock b/yarn.lock index 7263036c..7061c1fb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3746,6 +3746,13 @@ __metadata: languageName: node linkType: hard +"@types/semver@npm:^7.3.13": + version: 7.3.13 + resolution: "@types/semver@npm:7.3.13" + checksum: 00c0724d54757c2f4bc60b5032fe91cda6410e48689633d5f35ece8a0a66445e3e57fa1d6e07eb780f792e82ac542948ec4d0b76eb3484297b79bd18b8cf1cb0 + languageName: node + linkType: hard + "@types/serve-static@npm:*": version: 1.15.0 resolution: "@types/serve-static@npm:1.15.0" @@ -5690,6 +5697,7 @@ __metadata: "@types/react-autocomplete": ^1.8.6 "@types/react-dom": ^18.0.8 "@types/react-sidebar": ^3.0.2 + "@types/semver": ^7.3.13 animejs: ^3.2.1 array-to-sentence: ^2.0.0 autoprefixer: ^9.8.6