Drop graph/linechart from web header

This resolves #1669.

Also bumped some dependencies.
This commit is contained in:
Brenden Matthews 2023-11-08 14:32:02 -05:00
parent 42cdca055f
commit 370a02f087
7 changed files with 258 additions and 1048 deletions

View File

@ -1,12 +1,10 @@
import Link from 'next/link'
import { useRouter } from 'next/router'
import GitHub from './GitHub'
import { LineChart } from './LineChart'
import ThemeSwitcher from './ThemeSwitcher'
type HeaderProps = {
name: string
darkMode: boolean
setDarkMode: (state: boolean) => void
searchIndex: SearchIndex
}
@ -14,7 +12,7 @@ type HeaderProps = {
import * as React from 'react'
import Search from './Search'
import { SearchIndex, SearchItem } from '../utils/search'
import Fuse from 'fuse.js'
import Fuse, { IFuseOptions } from 'fuse.js'
interface NavLinkProps {
href: string
@ -38,13 +36,12 @@ const NavLink: React.FunctionComponent<NavLinkProps> = (props) => {
export default function Header({
name,
darkMode,
setDarkMode,
searchIndex,
}: HeaderProps) {
const router = useRouter()
const fuse = React.useMemo(() => {
const options: Fuse.IFuseOptions<SearchItem> = {}
const options: IFuseOptions<SearchItem> = {}
return new Fuse(
searchIndex.list,
options,
@ -67,7 +64,7 @@ export default function Header({
<NavLink href="/lua" name="Lua" />
</div>
)}
<LineChart width={380} height={40} darkMode={darkMode} />
<div className="flex-grow" />
<Search fuse={fuse} />
<div className="flex">
<div className="border-r mx-1 px-1 border-slate-700">

View File

@ -51,7 +51,6 @@ export default function Layout({ children, searchIndex }: LayoutProps) {
<Header
searchIndex={searchIndex}
name="Conky"
darkMode={darkMode}
setDarkMode={setDarkMode}
/>
</div>

View File

@ -1,124 +0,0 @@
import { useEffect, useMemo, useRef } from 'react'
import * as d3 from 'd3'
import { random } from 'colord'
type DataPoint = { x: number; y: number }
type LineChartProps = {
width: number
height: number
darkMode: boolean
}
function getRandomArbitrary(min: number, max: number): number {
return Math.random() * (max - min) + min
}
function updateData(width: number, data: Array<DataPoint>): Array<DataPoint> {
while (data.length >= width) {
data.shift()
}
const prev = data.at(data.length - 1)
if (prev) {
data.push({
x: prev.x + 1,
y: Math.max(0, prev.y + getRandomArbitrary(-120, 120)),
})
} else {
data.push({
x: 0,
y: getRandomArbitrary(0, 100),
})
}
return data
}
function fetchData() {
const storedData =
typeof window === 'undefined'
? '[]'
: localStorage.getItem('chartData') || '[]'
const data = JSON.parse(storedData)
return data || []
}
const data = fetchData()
export const LineChart = ({ width, height, darkMode }: LineChartProps) => {
const timerRef = useRef<NodeJS.Timeout>()
const svgRef = useRef(null)
const stroke = useMemo(() => random(), [])
useEffect(() => {
const doIt = (data: DataPoint[]) => {
data = updateData(width, data)
// Y axis
const [min, max] = d3.extent(data, (d) => d.y)
const yScale = d3
.scaleLinear()
.domain([min || 0, max || 0])
.range([height, 0])
// X axis
const [, xMax] = d3.extent(data, (d) => d.x)
const xScale = d3
.scaleLinear()
.domain([(xMax || 0) - width, xMax || 0])
.range([0, width])
if (!svgRef.current) {
return
}
d3.select(svgRef.current)
.selectAll('rect')
.data(data)
.join(
(enter) =>
enter
.append('rect')
.style(
'stroke',
darkMode ? stroke.lighten().toHex() : stroke.darken().toHex()
)
.style('stroke-opacity', '0.7')
.attr('x', (d) => xScale(d.x))
.attr('y', (d) => yScale(d.y))
.attr('height', (d) => yScale((max || 0) - d.y))
.attr('width', () => 1),
(update) =>
update
.transition()
.duration(1000)
.style(
'stroke',
darkMode ? stroke.lighten().toHex() : stroke.darken().toHex()
)
.attr('x', (d) => xScale(d.x))
.attr('y', (d) => yScale(d.y))
.attr('height', (d) => yScale((max || 0) - d.y))
.attr('width', () => 1),
(exit) => exit.call((d) => d.transition().remove())
)
localStorage.setItem('chartData', JSON.stringify(data))
timerRef.current = setTimeout(() => {
doIt(data)
}, 1000)
}
doIt(data)
return () => clearTimeout(timerRef.current)
}, [darkMode, stroke, height, width])
return (
<svg
width={width}
height={height}
viewBox={`0 0 ${width} ${height}`}
preserveAspectRatio="none"
ref={svgRef}
className="fill-transparent bg-transparent grow"
/>
)
}

View File

@ -1,4 +1,4 @@
import Fuse from 'fuse.js'
import Fuse, { FuseResult } from 'fuse.js'
import React, { Fragment, useCallback, useEffect, useState } from 'react'
import { Search as SearchIcon } from 'react-feather'
import { SearchItem } from '../utils/search'
@ -10,7 +10,7 @@ export interface SearchProps {
}
interface SearchResultProps {
result: Fuse.FuseResult<SearchItem>
result: FuseResult<SearchItem>
selected: boolean
active: boolean
}
@ -60,9 +60,9 @@ const SearchResult: React.FunctionComponent<SearchResultProps> = (props) => {
const Search: React.FunctionComponent<SearchProps> = ({ fuse }) => {
const router = useRouter()
const [searchText, setSearchText] = useState('')
const [searchResults, setSearchResults] = useState<
Fuse.FuseResult<SearchItem>[]
>([])
const [searchResults, setSearchResults] = useState<FuseResult<SearchItem>[]>(
[]
)
const [isOpen, setIsOpen] = useState(false)
const handleKeyPress = useCallback(
@ -94,7 +94,7 @@ const Search: React.FunctionComponent<SearchProps> = ({ fuse }) => {
const searchResult = fuse.search(value)
setSearchResults(searchResult)
}
const onChange = (value?: Fuse.FuseResult<SearchItem>) => {
const onChange = (value?: FuseResult<SearchItem>) => {
if (value) {
if (value.item.kind === 'var') {
router.push(`/variables#${value.item.name}`, undefined, {

1114
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -21,40 +21,38 @@
"e2e:headless": "start-server-and-test dev http://localhost:3000 \"cypress run --e2e\""
},
"dependencies": {
"@fontsource-variable/fira-code": "^5.0.13",
"@fontsource-variable/inter": "^5.0.13",
"@fontsource-variable/newsreader": "^5.0.14",
"@fontsource-variable/fira-code": "^5.0.15",
"@fontsource-variable/inter": "^5.0.15",
"@fontsource-variable/newsreader": "^5.0.16",
"@headlessui/react": "^1.7.17",
"@mapbox/rehype-prism": "^0.8.0",
"@netlify/plugin-nextjs": "^4.40.2",
"@netlify/plugin-nextjs": "^4.41.1",
"@tailwindcss/typography": "^0.5.10",
"classnames": "^2.3.2",
"colord": "^2.9.3",
"d3": "^7.8.5",
"fuse.js": "^6.6.2",
"fuse.js": "^7.0.0",
"gray-matter": "^4.0.3",
"inter-ui": "^3.19.3",
"next": "^13.5.4",
"next": "^14.0.1",
"prismjs": "^1.29.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-feather": "^2.0.10"
},
"devDependencies": {
"@types/d3": "^7.4.1",
"@types/eslint": "^8.44.4",
"@types/js-yaml": "^4.0.6",
"@types/eslint": "^8.44.7",
"@types/js-yaml": "^4.0.9",
"@types/mapbox__rehype-prism": "^0.8.1",
"@types/node": "^20.8.4",
"@types/prismjs": "^1.26.1",
"@types/react": "^18.2.27",
"@types/react-dom": "^18.2.12",
"@typescript-eslint/eslint-plugin": "^6.7.5",
"@typescript-eslint/parser": "^6.7.5",
"autoprefixer": "^10.4.15",
"cypress": "^13.3.0",
"eslint": "^8.51.0",
"eslint-config-next": "^13.5.4",
"@types/node": "^20.9.0",
"@types/prismjs": "^1.26.3",
"@types/react": "^18.2.37",
"@types/react-dom": "^18.2.15",
"@typescript-eslint/eslint-plugin": "^6.10.0",
"@typescript-eslint/parser": "^6.10.0",
"autoprefixer": "^10.4.16",
"cypress": "^13.4.0",
"eslint": "^8.53.0",
"eslint-config-next": "^14.0.1",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-cypress": "^2.15.1",
"eslint-plugin-mdx": "^2.2.0",
@ -65,8 +63,8 @@
"postcss": "^8.4.31",
"rehype-stringify": "^9.0.4",
"remark-gfm": "^3.0.1",
"start-server-and-test": "^2.0.1",
"tailwindcss": "^3.3.3",
"start-server-and-test": "^2.0.2",
"tailwindcss": "^3.3.5",
"typescript": "^5.2.2"
}
}

View File

@ -1,4 +1,4 @@
import Fuse from 'fuse.js'
import Fuse, { FuseIndexRecords } from 'fuse.js'
import { getConfigSettings, getLua, getVariables } from './doc-utils'
export interface SearchItem {
kind: string
@ -8,7 +8,7 @@ export interface SearchItem {
export interface SearchIndex {
index: {
keys: readonly string[]
records: Fuse.FuseIndexRecords
records: FuseIndexRecords
}
list: SearchItem[]
}