Skip to content

Commit

Permalink
saving progress
Browse files Browse the repository at this point in the history
  • Loading branch information
darasus committed Nov 13, 2022
1 parent 17f247f commit 010a7c5
Show file tree
Hide file tree
Showing 48 changed files with 606 additions and 640 deletions.
27 changes: 12 additions & 15 deletions client/components/AutocompleteInputBox/AutocompleteInputBox.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { Component } from 'react'
import React from 'react'
import cx from 'classnames'

import { WithClassName } from '../../../types'
Expand All @@ -8,18 +8,15 @@ type AutocompleteInputBoxProps = React.PropsWithChildren &
footer?: React.ReactNode
}

class AutocompleteInputBox extends Component<AutocompleteInputBoxProps> {
render() {
const { children, footer, className } = this.props
return (
<div className={cx('autocomplete-input-box', className)}>
{children}
{footer && (
<div className="autocomplete-input-box__footer">{footer}</div>
)}
</div>
)
}
export function AutocompleteInputBox({
children,
footer,
className,
}: AutocompleteInputBoxProps) {
return (
<div className={cx('autocomplete-input-box', className)}>
{children}
{footer && <div className="autocomplete-input-box__footer">{footer}</div>}
</div>
)
}

export default AutocompleteInputBox
4 changes: 1 addition & 3 deletions client/components/AutocompleteInputBox/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
import AutocompleteInputBox from './AutocompleteInputBox'

export default AutocompleteInputBox
export { AutocompleteInputBox } from './AutocompleteInputBox'
265 changes: 119 additions & 146 deletions client/components/BarGraph/BarGraph.tsx
Original file line number Diff line number Diff line change
@@ -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<BarGraphProps> {
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 (
<div className="bar-graph-container">
<figure className="bar-graph">
{readings.map((reading, index) =>
reading.disabled ? (
<DisabledBar
key={reading.version}
reading={reading}
onBarClick={onBarClick}
/>
) : (
<ActiveBar
key={reading.version}
reading={reading}
graphScale={graphScale}
options={{
isFirstTreeshakeable: index === firstTreeshakeableIndex,
isFirstSideEffectFree: index === firstSideEffectFreeIndex,
}}
onBarClick={onBarClick}
/>
)
)}
</figure>
<div className="bar-graph__legend">
<div className="bar-graph__legend__bar1">
<div className="bar-graph__legend__colorbox" />
Min
</div>
<div className="bar-graph__legend__bar2">
<div className="bar-graph__legend__colorbox" />
GZIP
</div>
</div>
</div>
)
}

return treeshakingIntroducedRecently ? firstTreeshakingIndex : -1
}
interface DisabledBarProps {
reading: Reading
onBarClick: (reading: Reading) => void
}

renderDisabledBar = (reading: Reading) => (
function DisabledBar({ reading, onBarClick }: DisabledBarProps) {
return (
<div
key={reading.version}
className="bar-graph__bar-group bar-graph__bar-group--disabled"
onClick={() => this.props.onBarClick(reading)}
onClick={() => onBarClick(reading)}
>
<div
className="bar-graph__bar"
Expand All @@ -77,99 +74,75 @@ export default class BarGraph extends PureComponent<BarGraphProps> {
<BarVersion version={reading.version} />
</div>
)
}

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 (
<div
onClick={() => this.props.onBarClick(reading)}
key={reading.version}
className="bar-graph__bar-group"
>
<div className="bar-graph__bar-symbols">
{options.isFirstTreeshakeable && (
<div
data-balloon={`ES2015 exports introduced. ${
reading.hasSideEffects
? 'Not side-effect free yet, hence limited tree-shake ability.'
: ''
}`}
className="bar-graph__bar-symbol"
>
<TreeShakeIcon />
</div>
)}
{options.isFirstSideEffectFree && (
<div
data-balloon={`Was marked side-effect free. ${
reading.hasJSNext || reading.hasJSModule || reading.isModuleType
? 'Supports ES2015 exports also, hence fully tree-shakeable'
: "Doesn't export ESM yet, limited tree-shake ability"
}`}
className="bar-graph__bar-symbol"
>
<SideEffectIcon />
</div>
)}
</div>

<div
className="bar-graph__bar"
style={{ height: `${(reading.size - reading.gzip) * scale}%` }}
data-balloon={getTooltipMessage(reading)}
/>
<div
className="bar-graph__bar2"
style={{ height: `${reading.gzip * scale}%` }}
data-balloon={getTooltipMessage(reading)}
/>
<BarVersion version={reading.version} />
</div>
)
}

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 (
<div className="bar-graph-container">
<figure className="bar-graph">
{readings.map((reading, index) =>
reading.disabled
? this.renderDisabledBar(reading)
: this.renderActiveBar(reading, graphScale, {
isFirstTreeshakeable: index === firstTreeshakeableIndex,
isFirstSideEffectFree: index === firstSideEffectFreeIndex,
})
)}
</figure>
<div className="bar-graph__legend">
<div className="bar-graph__legend__bar1">
<div className="bar-graph__legend__colorbox" />
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 (
<div
onClick={() => onBarClick(reading)}
key={reading.version}
className="bar-graph__bar-group"
>
<div className="bar-graph__bar-symbols">
{options.isFirstTreeshakeable && (
<div
data-balloon={`ES2015 exports introduced. ${
reading.hasSideEffects
? 'Not side-effect free yet, hence limited tree-shake ability.'
: ''
}`}
className="bar-graph__bar-symbol"
>
<TreeShakeIcon />
</div>
<div className="bar-graph__legend__bar2">
<div className="bar-graph__legend__colorbox" />
GZIP
)}
{options.isFirstSideEffectFree && (
<div
data-balloon={`Was marked side-effect free. ${
reading.hasJSNext || reading.hasJSModule || reading.isModuleType
? 'Supports ES2015 exports also, hence fully tree-shakeable'
: "Doesn't export ESM yet, limited tree-shake ability"
}`}
className="bar-graph__bar-symbol"
>
<SideEffectIcon />
</div>
</div>
)}
</div>
)
}

<div
className="bar-graph__bar"
style={{ height: `${(reading.size - reading.gzip) * graphScale}%` }}
data-balloon={tooltipMessage}
/>
<div
className="bar-graph__bar2"
style={{ height: `${reading.gzip * graphScale}%` }}
data-balloon={tooltipMessage}
/>
<BarVersion version={reading.version} />
</div>
)
}
43 changes: 43 additions & 0 deletions client/components/BarGraph/hooks/useBarGraph.ts
Original file line number Diff line number Diff line change
@@ -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 }
}
4 changes: 1 addition & 3 deletions client/components/BarGraph/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
import BarGraph from './BarGraph'

export default BarGraph
export { BarGraph } from './BarGraph'
10 changes: 10 additions & 0 deletions client/components/BarGraph/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export type Reading = {
version: string
size: number
gzip: number
disabled: boolean
hasSideEffects: boolean
hasJSModule: boolean
hasJSNext: boolean
isModuleType: boolean
}
1 change: 1 addition & 0 deletions client/components/BarVersion/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { BarVersion } from './BarVersion'
Loading

0 comments on commit 010a7c5

Please sign in to comment.