mirror of
https://github.com/zen-browser/www.git
synced 2025-07-08 09:20:00 +02:00
feat(preact): migrate react to lightweight preact
This commit is contained in:
parent
53efb5d87d
commit
fc07f4989a
9 changed files with 2924 additions and 1705 deletions
|
@ -2,7 +2,7 @@
|
|||
import { defineConfig } from 'astro/config'
|
||||
import tailwind from '@astrojs/tailwind'
|
||||
|
||||
import react from '@astrojs/react'
|
||||
import preact from '@astrojs/preact'
|
||||
|
||||
import sitemap from '@astrojs/sitemap'
|
||||
|
||||
|
@ -10,7 +10,7 @@ import sitemap from '@astrojs/sitemap'
|
|||
export default defineConfig({
|
||||
integrations: [
|
||||
tailwind(),
|
||||
react(),
|
||||
preact({ compat: true }),
|
||||
sitemap({
|
||||
// TODO: Maybe? Maybe not?
|
||||
// filter: (page) => !page.includes('mods/'),
|
||||
|
|
4558
package-lock.json
generated
4558
package-lock.json
generated
File diff suppressed because it is too large
Load diff
11
package.json
11
package.json
|
@ -10,10 +10,14 @@
|
|||
"wrangler": "wrangler",
|
||||
"astro": "astro"
|
||||
},
|
||||
"overrides": {
|
||||
"react": "npm:@preact/compat@latest",
|
||||
"react-dom": "npm:@preact/compat@latest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/check": "^0.9.4",
|
||||
"@astrojs/cloudflare": "^12.2.1",
|
||||
"@astrojs/react": "^4.2.0",
|
||||
"@astrojs/preact": "^4.0.4",
|
||||
"@astrojs/rss": "^4.0.11",
|
||||
"@astrojs/sitemap": "^3.2.1",
|
||||
"@astrojs/tailwind": "^6.0.0",
|
||||
|
@ -21,8 +25,6 @@
|
|||
"@fortawesome/fontawesome-svg-core": "^6.7.1",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.7.1",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.7.1",
|
||||
"@types/react": "^19.0.1",
|
||||
"@types/react-dom": "^19.0.2",
|
||||
"astro": "^5.3.0",
|
||||
"astro-navbar": "^2.3.7",
|
||||
"autoprefixer": "10.4.14",
|
||||
|
@ -32,11 +34,10 @@
|
|||
"lucide-react": "^0.475.0",
|
||||
"motion": "^11.13.5",
|
||||
"postcss": "^8.5.1",
|
||||
"preact": "^10.26.2",
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-astro": "^0.14.1",
|
||||
"prettier-plugin-tailwindcss": "^0.6.6",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"sharp": "^0.33.5",
|
||||
"tailwindcss": "^3.4.15",
|
||||
"typescript": "^5.6.3"
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import React, { useState } from 'react'
|
||||
import { useState } from 'preact/hooks'
|
||||
import MyLogo from './Mylogo'
|
||||
import { Menu } from 'lucide-react'
|
||||
import ThemeSwitch from './ThemeSwitch/ThemeSwitch'
|
||||
|
||||
const MobileNavbar: React.FC = () => {
|
||||
const MobileNavbar = () => {
|
||||
const [isMenuOpen, setMenuOpen] = useState(false)
|
||||
|
||||
const menuTransformClass = isMenuOpen ? 'translate-x-0' : 'translate-x-full'
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import type React from 'react'
|
||||
import { useState, useEffect } from 'react'
|
||||
import { useState, useEffect } from 'preact/hooks'
|
||||
import type { ZenTheme } from '../mods'
|
||||
import { library, icon } from '@fortawesome/fontawesome-svg-core'
|
||||
import { faSort, faSortUp, faSortDown } from '@fortawesome/free-solid-svg-icons'
|
||||
|
@ -48,15 +47,17 @@ export default function ModsList({ mods }: ModsListProps) {
|
|||
return defaultSortIcon
|
||||
}
|
||||
|
||||
function handleSearch(e: React.ChangeEvent<HTMLInputElement>) {
|
||||
setSearch(e.target.value)
|
||||
function handleSearch(e: Event) {
|
||||
const target = e.target as HTMLInputElement
|
||||
setSearch(target.value)
|
||||
}
|
||||
|
||||
function handleLimitChange(e: React.ChangeEvent<HTMLSelectElement>) {
|
||||
setLimit(Number.parseInt(e.target.value, 10))
|
||||
function handleLimitChange(e: Event) {
|
||||
const target = e.target as HTMLSelectElement
|
||||
setLimit(Number.parseInt(target.value, 10))
|
||||
}
|
||||
|
||||
function handlePageSubmit(e: React.FormEvent) {
|
||||
function handlePageSubmit(e: Event) {
|
||||
e.preventDefault()
|
||||
const newPage = Number.parseInt(pageInput, 10)
|
||||
if (!Number.isNaN(newPage) && newPage >= 1 && newPage <= totalPages) {
|
||||
|
@ -67,27 +68,24 @@ export default function ModsList({ mods }: ModsListProps) {
|
|||
}
|
||||
}
|
||||
|
||||
function handlePageInputChange(e: React.ChangeEvent<HTMLInputElement>) {
|
||||
setPageInput(e.target.value)
|
||||
function handlePageInputChange(e: Event) {
|
||||
const target = e.target as HTMLInputElement
|
||||
setPageInput(target.value)
|
||||
}
|
||||
|
||||
function getPageUrl(pageNum: number) {
|
||||
const params = new URLSearchParams(searchParams)
|
||||
|
||||
if (pageNum > 1) {
|
||||
params.set('page', pageNum.toString())
|
||||
} else {
|
||||
params.delete('page')
|
||||
}
|
||||
|
||||
const queryString = params.toString()
|
||||
return `/mods${queryString ? `?${queryString}` : ''}`
|
||||
}
|
||||
|
||||
function renderPagination() {
|
||||
if (totalPages <= 1) return null
|
||||
|
||||
// Render page input for larger page counts
|
||||
return (
|
||||
<div className="mx-auto mb-12 flex items-center justify-center gap-4 px-8">
|
||||
<a
|
||||
|
@ -105,7 +103,7 @@ export default function ModsList({ mods }: ModsListProps) {
|
|||
<input
|
||||
type="text"
|
||||
value={pageInput}
|
||||
onChange={handlePageInputChange}
|
||||
onInput={handlePageInputChange}
|
||||
className="w-16 rounded border border-dark bg-transparent px-2 py-1 text-center text-sm"
|
||||
aria-label="Page number"
|
||||
/>
|
||||
|
@ -137,7 +135,7 @@ export default function ModsList({ mods }: ModsListProps) {
|
|||
className="w-full rounded-full border-2 border-dark bg-transparent px-6 py-2 text-lg outline-none"
|
||||
placeholder="Type to search..."
|
||||
value={search}
|
||||
onChange={handleSearch}
|
||||
onInput={handleSearch}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
@ -179,7 +177,7 @@ export default function ModsList({ mods }: ModsListProps) {
|
|||
<select
|
||||
id="limit"
|
||||
value={limit}
|
||||
onChange={handleLimitChange}
|
||||
onInput={handleLimitChange}
|
||||
className="rounded border border-dark bg-transparent px-2 py-1 text-sm [&>option]:text-black"
|
||||
>
|
||||
<option value="12">12</option>
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
import React from 'react'
|
||||
|
||||
interface MyLogoProps {
|
||||
className?: string
|
||||
}
|
||||
|
||||
const MyLogo: React.FC<MyLogoProps> = ({ className }) => (
|
||||
const MyLogo = ({ className }: MyLogoProps) => (
|
||||
<svg
|
||||
className={className}
|
||||
width="32"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useEffect, useState } from 'react'
|
||||
import { useEffect, useState } from 'preact/hooks'
|
||||
import './index.css'
|
||||
|
||||
interface Props {
|
||||
|
@ -6,8 +6,8 @@ interface Props {
|
|||
className?: string
|
||||
}
|
||||
|
||||
const ThemeSwitch: React.FC<Props> = ({ label, className }) => {
|
||||
const [isLight, setIsLight] = useState<boolean>(() => {
|
||||
const ThemeSwitch = ({ label, className = '' }: Props) => {
|
||||
const [isLight, setIsLight] = useState(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
return localStorage.getItem('theme') === 'light'
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ const ThemeSwitch: React.FC<Props> = ({ label, className }) => {
|
|||
<path
|
||||
d="M12 9c1.654 0 3 1.346 3 3s-1.346 3-3 3-3-1.346-3-3 1.346-3 3-3zm0-2c-2.762 0-5 2.238-5 5s2.238 5 5 5 5-2.238 5-5-2.238-5-5-5zm-4.184-.599l-3.593-3.594-1.415 1.414 3.595 3.595c.401-.537.876-1.013 1.413-1.415zm4.184-1.401c.34 0 .672.033 1 .08v-5.08h-2v5.08c.328-.047.66-.08 1-.08zm5.598 2.815l3.595-3.595-1.414-1.414-3.595 3.595c.537.402 1.012.878 1.414 1.414zm-12.598 4.185c0-.34.033-.672.08-1h-5.08v2h5.08c-.047-.328-.08-.66-.08-1zm11.185 5.598l3.594 3.593 1.415-1.414-3.594-3.593c-.403.536-.879 1.012-1.415 1.414zm-9.784-1.414l-3.593 3.593 1.414 1.414 3.593-3.593c-.536-.402-1.011-.877-1.414-1.414zm12.519-5.184c.047.328.08.66.08 1s-.033.672-.08 1h5.08v-2h-5.08zm-6.92 8c-.34 0-.672-.033-1-.08v5.08h2v-5.08c-.328.047-.66.08-1 .08z"
|
||||
fill="currentColor"
|
||||
></path>
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
className="ac-theme-switch-icon ac-theme-switch-icon--light"
|
||||
|
@ -52,7 +52,7 @@ const ThemeSwitch: React.FC<Props> = ({ label, className }) => {
|
|||
<path
|
||||
d="M10.719 2.082c-2.572 2.028-4.719 5.212-4.719 9.918 0 4.569 1.938 7.798 4.548 9.895-4.829-.705-8.548-4.874-8.548-9.895 0-5.08 3.808-9.288 8.719-9.918zm1.281-2.082c-6.617 0-12 5.383-12 12s5.383 12 12 12c1.894 0 3.87-.333 5.37-1.179-3.453-.613-9.37-3.367-9.37-10.821 0-7.555 6.422-10.317 9.37-10.821-1.74-.682-3.476-1.179-5.37-1.179zm0 10.999c1.437.438 2.562 1.564 2.999 3.001.44-1.437 1.565-2.562 3.001-3-1.436-.439-2.561-1.563-3.001-3-.437 1.436-1.562 2.561-2.999 2.999zm8.001.001c.958.293 1.707 1.042 2 2.001.291-.959 1.042-1.709 1.999-2.001-.957-.292-1.707-1.042-2-2-.293.958-1.042 1.708-1.999 2zm-1-9c-.437 1.437-1.563 2.562-2.998 3.001 1.438.44 2.561 1.564 3.001 3.002.437-1.438 1.563-2.563 2.996-3.002-1.433-.437-2.559-1.564-2.999-3.001z"
|
||||
fill="currentColor"
|
||||
></path>
|
||||
/>
|
||||
</svg>
|
||||
{label ? (
|
||||
<span className="ac-theme-switch-label">{label}</span>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { useEffect, useState } from 'react'
|
||||
import { useEffect, useState } from 'preact/hooks'
|
||||
import type { ZenTheme } from '../mods'
|
||||
|
||||
type SortOrder = 'default' | 'asc' | 'desc'
|
||||
|
@ -70,7 +70,9 @@ export function useModsSearch(mods: ZenTheme[]) {
|
|||
searchParams.delete('limit')
|
||||
}
|
||||
|
||||
const newUrl = `${window.location.pathname}${searchParams.toString() ? `?${searchParams.toString()}` : ''}`
|
||||
const newUrl = `${window.location.pathname}${
|
||||
searchParams.toString() ? `?${searchParams.toString()}` : ''
|
||||
}`
|
||||
window.history.replaceState({}, '', newUrl)
|
||||
}, [state, searchParams])
|
||||
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
"extends": "astro/tsconfigs/strict",
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "react"
|
||||
"jsxImportSource": "preact"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue