mirror of
https://github.com/ourongxing/newsnow.git
synced 2025-01-19 03:09:14 +08:00
feat: better animation
This commit is contained in:
parent
a1d25f7d6f
commit
a05f0d54b5
@ -28,6 +28,7 @@
|
||||
"@atlaskit/pragmatic-drag-and-drop": "^1.4.0",
|
||||
"@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^1.4.0",
|
||||
"@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.0.3",
|
||||
"@formkit/auto-animate": "^0.8.2",
|
||||
"@iconify-json/si": "^1.2.1",
|
||||
"@tanstack/react-query-devtools": "^5.59.9",
|
||||
"@tanstack/react-router": "^1.64.0",
|
||||
|
79
pnpm-lock.yaml
generated
79
pnpm-lock.yaml
generated
@ -26,6 +26,9 @@ importers:
|
||||
'@atlaskit/pragmatic-drag-and-drop-hitbox':
|
||||
specifier: ^1.0.3
|
||||
version: 1.0.3
|
||||
'@formkit/auto-animate':
|
||||
specifier: ^0.8.2
|
||||
version: 0.8.2
|
||||
'@iconify-json/si':
|
||||
specifier: ^1.2.1
|
||||
version: 1.2.1
|
||||
@ -89,6 +92,9 @@ importers:
|
||||
md5:
|
||||
specifier: ^2.3.0
|
||||
version: 2.3.0
|
||||
motion:
|
||||
specifier: ^10.18.0
|
||||
version: 10.18.0
|
||||
ofetch:
|
||||
specifier: ^1.4.1
|
||||
version: 1.4.1
|
||||
@ -1473,6 +1479,9 @@ packages:
|
||||
resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
'@formkit/auto-animate@0.8.2':
|
||||
resolution: {integrity: sha512-SwPWfeRa5veb1hOIBMdzI+73te5puUBHmqqaF1Bu7FjvxlYSz/kJcZKSa9Cg60zL0uRNeJL2SbRxV6Jp6Q1nFQ==}
|
||||
|
||||
'@humanfs/core@0.19.0':
|
||||
resolution: {integrity: sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==}
|
||||
engines: {node: '>=18.18.0'}
|
||||
@ -1540,6 +1549,24 @@ packages:
|
||||
resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==}
|
||||
hasBin: true
|
||||
|
||||
'@motionone/animation@10.18.0':
|
||||
resolution: {integrity: sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw==}
|
||||
|
||||
'@motionone/dom@10.18.0':
|
||||
resolution: {integrity: sha512-bKLP7E0eyO4B2UaHBBN55tnppwRnaE3KFfh3Ps9HhnAkar3Cb69kUCJY9as8LrccVYKgHA+JY5dOQqJLOPhF5A==}
|
||||
|
||||
'@motionone/easing@10.18.0':
|
||||
resolution: {integrity: sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg==}
|
||||
|
||||
'@motionone/generators@10.18.0':
|
||||
resolution: {integrity: sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg==}
|
||||
|
||||
'@motionone/types@10.17.1':
|
||||
resolution: {integrity: sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A==}
|
||||
|
||||
'@motionone/utils@10.18.0':
|
||||
resolution: {integrity: sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw==}
|
||||
|
||||
'@napi-rs/pinyin-android-arm-eabi@1.7.5':
|
||||
resolution: {integrity: sha512-dnurqJdedbU8D1Ngudf10nXvc4BbVSe4ki9U2LUZoGMDGa069t4c87BHRXvcy2By3YpOozORv9/QTMxAQFVOLg==}
|
||||
engines: {node: '>= 10.0'}
|
||||
@ -3971,6 +3998,9 @@ packages:
|
||||
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
hey-listen@1.0.8:
|
||||
resolution: {integrity: sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==}
|
||||
|
||||
hookable@5.5.3:
|
||||
resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
|
||||
|
||||
@ -4605,6 +4635,9 @@ packages:
|
||||
mockdate@3.0.5:
|
||||
resolution: {integrity: sha512-iniQP4rj1FhBdBYS/+eQv7j1tadJ9lJtdzgOpvsOHng/GbcDh2Fhdeq+ZRldrPYdXvCyfFUmFeEwEGXZB5I/AQ==}
|
||||
|
||||
motion@10.18.0:
|
||||
resolution: {integrity: sha512-MVAZZmwM/cp77BrNe1TxTMldxRPjwBNHheU5aPToqT4rJdZxLiADk58H+a0al5jKLxkB0OdgNq6DiVn11cjvIQ==}
|
||||
|
||||
mri@1.2.0:
|
||||
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
|
||||
engines: {node: '>=4'}
|
||||
@ -7441,6 +7474,8 @@ snapshots:
|
||||
|
||||
'@fastify/busboy@2.1.1': {}
|
||||
|
||||
'@formkit/auto-animate@0.8.2': {}
|
||||
|
||||
'@humanfs/core@0.19.0': {}
|
||||
|
||||
'@humanfs/node@0.16.5':
|
||||
@ -7534,6 +7569,41 @@ snapshots:
|
||||
- encoding
|
||||
- supports-color
|
||||
|
||||
'@motionone/animation@10.18.0':
|
||||
dependencies:
|
||||
'@motionone/easing': 10.18.0
|
||||
'@motionone/types': 10.17.1
|
||||
'@motionone/utils': 10.18.0
|
||||
tslib: 2.8.0
|
||||
|
||||
'@motionone/dom@10.18.0':
|
||||
dependencies:
|
||||
'@motionone/animation': 10.18.0
|
||||
'@motionone/generators': 10.18.0
|
||||
'@motionone/types': 10.17.1
|
||||
'@motionone/utils': 10.18.0
|
||||
hey-listen: 1.0.8
|
||||
tslib: 2.8.0
|
||||
|
||||
'@motionone/easing@10.18.0':
|
||||
dependencies:
|
||||
'@motionone/utils': 10.18.0
|
||||
tslib: 2.8.0
|
||||
|
||||
'@motionone/generators@10.18.0':
|
||||
dependencies:
|
||||
'@motionone/types': 10.17.1
|
||||
'@motionone/utils': 10.18.0
|
||||
tslib: 2.8.0
|
||||
|
||||
'@motionone/types@10.17.1': {}
|
||||
|
||||
'@motionone/utils@10.18.0':
|
||||
dependencies:
|
||||
'@motionone/types': 10.17.1
|
||||
hey-listen: 1.0.8
|
||||
tslib: 2.8.0
|
||||
|
||||
'@napi-rs/pinyin-android-arm-eabi@1.7.5':
|
||||
optional: true
|
||||
|
||||
@ -10357,6 +10427,8 @@ snapshots:
|
||||
dependencies:
|
||||
function-bind: 1.1.2
|
||||
|
||||
hey-listen@1.0.8: {}
|
||||
|
||||
hookable@5.5.3: {}
|
||||
|
||||
hosted-git-info@2.8.9: {}
|
||||
@ -10973,6 +11045,13 @@ snapshots:
|
||||
|
||||
mockdate@3.0.5: {}
|
||||
|
||||
motion@10.18.0:
|
||||
dependencies:
|
||||
'@motionone/animation': 10.18.0
|
||||
'@motionone/dom': 10.18.0
|
||||
'@motionone/types': 10.17.1
|
||||
'@motionone/utils': 10.18.0
|
||||
|
||||
mri@1.2.0: {}
|
||||
|
||||
mrmime@2.0.0: {}
|
||||
|
@ -1,11 +1,12 @@
|
||||
import type { PropsWithChildren } from "react"
|
||||
import type { SourceID } from "@shared/types"
|
||||
import { motion } from "framer-motion"
|
||||
import type { BaseEventPayload, ElementDragType } from "@atlaskit/pragmatic-drag-and-drop/dist/types/internal-types"
|
||||
import { extractClosestEdge } from "@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge"
|
||||
import { reorderWithEdge } from "@atlaskit/pragmatic-drag-and-drop-hitbox/util/reorder-with-edge"
|
||||
import { createPortal } from "react-dom"
|
||||
import { useThrottleFn } from "ahooks"
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react"
|
||||
import { motion } from "framer-motion"
|
||||
import { DndContext } from "../common/dnd"
|
||||
import { useSortable } from "../common/dnd/useSortable"
|
||||
import type { ItemsProps } from "./card"
|
||||
@ -15,12 +16,14 @@ import { currentSourcesAtom } from "~/atoms"
|
||||
const AnimationDuration = 200
|
||||
export function Dnd() {
|
||||
const [items, setItems] = useAtom(currentSourcesAtom)
|
||||
const [parent] = useAutoAnimate({ duration: AnimationDuration })
|
||||
useEntireQuery(items)
|
||||
|
||||
return (
|
||||
<DndWrapper items={items} setItems={setItems}>
|
||||
<motion.ol
|
||||
className="grid w-full gap-6"
|
||||
ref={parent}
|
||||
style={{
|
||||
gridTemplateColumns: "repeat(auto-fill, minmax(350px, 1fr))",
|
||||
}}
|
||||
@ -42,7 +45,6 @@ export function Dnd() {
|
||||
{items.map(id => (
|
||||
<motion.li
|
||||
key={id}
|
||||
layout
|
||||
transition={{
|
||||
type: "tween",
|
||||
duration: AnimationDuration / 1000,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { AnimatePresence, motion } from "framer-motion"
|
||||
import { useCallback, useMemo, useRef } from "react"
|
||||
import { useHoverDirty, useMount, useUpdateEffect, useWindowSize } from "react-use"
|
||||
import { useMount, useWindowSize } from "react-use"
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react"
|
||||
import type { ToastItem } from "~/atoms/types"
|
||||
import { Timer } from "~/utils"
|
||||
|
||||
@ -12,33 +12,20 @@ export function Toast() {
|
||||
return t > width * 0.9 ? width * 0.9 : t
|
||||
}, [width])
|
||||
const toastItems = useAtomValue(toastAtom)
|
||||
|
||||
const [parent] = useAutoAnimate({ duration: 200 })
|
||||
return (
|
||||
<AnimatePresence>
|
||||
{toastItems.length && (
|
||||
<motion.ol
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
<ol
|
||||
ref={parent}
|
||||
style={{
|
||||
width: WIDTH,
|
||||
left: center,
|
||||
}}
|
||||
variants={{
|
||||
visible: {
|
||||
transition: {
|
||||
delayChildren: 0.1,
|
||||
staggerChildren: 0.2,
|
||||
},
|
||||
},
|
||||
}}
|
||||
className="absolute top-0 z-99 flex flex-col gap-2"
|
||||
>
|
||||
{
|
||||
toastItems.map(k => <Item key={k.id} info={k} />)
|
||||
}
|
||||
</motion.ol>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</ol>
|
||||
)
|
||||
}
|
||||
|
||||
@ -67,30 +54,22 @@ function Item({ info }: { info: ToastItem }) {
|
||||
return () => timer.current?.clear()
|
||||
})
|
||||
|
||||
const ref = useRef(null)
|
||||
const isHoverd = useHoverDirty(ref)
|
||||
useUpdateEffect(() => {
|
||||
if (isHoverd) {
|
||||
const [hoverd, setHoverd] = useState(false)
|
||||
useEffect(() => {
|
||||
if (hoverd) {
|
||||
timer.current?.pause()
|
||||
} else {
|
||||
timer.current?.resume()
|
||||
}
|
||||
}, [isHoverd])
|
||||
}, [hoverd])
|
||||
|
||||
return (
|
||||
<motion.li
|
||||
ref={ref}
|
||||
layout
|
||||
variants={{
|
||||
hidden: { y: 0, opacity: 0 },
|
||||
visible: {
|
||||
y: 15,
|
||||
opacity: 1,
|
||||
},
|
||||
}}
|
||||
<li
|
||||
className={$(
|
||||
"bg-base rounded-lg shadow-xl relative",
|
||||
)}
|
||||
onMouseEnter={() => setHoverd(true)}
|
||||
onMouseLeave={() => setHoverd(false)}
|
||||
>
|
||||
<div className={$(
|
||||
`bg-${color}-500 dark:bg-${color} bg-op-40! p2 backdrop-blur-5 rounded-lg w-full`,
|
||||
@ -98,7 +77,7 @@ function Item({ info }: { info: ToastItem }) {
|
||||
)}
|
||||
>
|
||||
{
|
||||
isHoverd
|
||||
hoverd
|
||||
? <button type="button" className={`i-ph:x-circle color-${color}-500 i-ph:info`} onClick={() => hidden(false)} />
|
||||
: <span className={`i-ph:info color-${color}-500 `} />
|
||||
}
|
||||
@ -117,6 +96,6 @@ function Item({ info }: { info: ToastItem }) {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</motion.li>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { motion } from "framer-motion"
|
||||
import { useHoverDirty } from "react-use"
|
||||
|
||||
function ThemeToggle() {
|
||||
const { isDark, toggleDark } = useDark()
|
||||
@ -16,13 +15,8 @@ function ThemeToggle() {
|
||||
export function Menu() {
|
||||
const { loggedIn, login, logout, userInfo, enableLogin } = useLogin()
|
||||
const [shown, show] = useState(false)
|
||||
const ref = useRef<HTMLElement>(null)
|
||||
const isHover = useHoverDirty(ref)
|
||||
useEffect(() => {
|
||||
show(isHover)
|
||||
}, [shown, isHover])
|
||||
return (
|
||||
<span ref={ref} className="relative">
|
||||
<span className="relative" onMouseEnter={() => show(true)} onMouseLeave={() => show(false)}>
|
||||
<span className="flex items-center scale-90">
|
||||
{
|
||||
enableLogin && loggedIn && userInfo.avatar
|
||||
|
@ -3,15 +3,14 @@ import { defineConfig } from "vite"
|
||||
import react from "@vitejs/plugin-react-swc"
|
||||
import { TanStackRouterVite } from "@tanstack/router-plugin/vite"
|
||||
import unocss from "unocss/vite"
|
||||
import dotenv from "dotenv"
|
||||
import unimport from "unimport/unplugin"
|
||||
import nitro from "./nitro.config"
|
||||
import { projectDir } from "./shared/dir"
|
||||
import pwa from "./pwa.config"
|
||||
|
||||
dotenv.config({
|
||||
path: join(projectDir, ".env.server"),
|
||||
})
|
||||
// dotenv.config({
|
||||
// path: join(projectDir, ".env.server"),
|
||||
// })
|
||||
|
||||
export default defineConfig({
|
||||
resolve: {
|
||||
|
Loading…
x
Reference in New Issue
Block a user