From a89edff8fab1a72466523b7f91101aa4b67ae133 Mon Sep 17 00:00:00 2001 From: Ou Date: Thu, 10 Oct 2024 00:29:59 +0800 Subject: [PATCH] feat: set animation --- package.json | 1 + pnpm-lock.yaml | 24 +++++++++++++ src/atoms.ts | 6 ++-- src/components/section/dnd.tsx | 61 ++++++++++++++++++++++++++------ src/components/section/index.tsx | 14 ++------ 5 files changed, 83 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index 664a96d..ba6a8ca 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "db0": "npm:@ourongxing/db0@latest", "fast-xml-parser": "^4.5.0", "favicons-scraper": "^1.3.2", + "framer-motion": "^11.11.5", "h3": "^1.13.0", "iconv-lite": "^0.6.3", "jotai": "^2.10.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e35be4a..561b4e4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -62,6 +62,9 @@ importers: favicons-scraper: specifier: ^1.3.2 version: 1.3.2 + framer-motion: + specifier: ^11.11.5 + version: 11.11.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) h3: specifier: ^1.13.0 version: 1.13.0 @@ -3000,6 +3003,20 @@ packages: resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} engines: {node: '>=14'} + framer-motion@11.11.5: + resolution: {integrity: sha512-kwnnxRe3fTQyTr90VMBlrjAvKxZhUWQnR2lXrpX98dPBBlOY+JiTqHhlHoyCJskMpyGpiXS84TL0moI/MsS/5Q==} + peerDependencies: + '@emotion/is-prop-valid': '*' + react: ^18.0.0 + react-dom: ^18.0.0 + peerDependenciesMeta: + '@emotion/is-prop-valid': + optional: true + react: + optional: true + react-dom: + optional: true + fresh@0.5.2: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} @@ -7743,6 +7760,13 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 + framer-motion@11.11.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + tslib: 2.7.0 + optionalDependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + fresh@0.5.2: {} front-matter@4.0.2: diff --git a/src/atoms.ts b/src/atoms.ts index 0d7e43f..987ee56 100644 --- a/src/atoms.ts +++ b/src/atoms.ts @@ -22,7 +22,7 @@ export const localSourcesAtom = atomWithLocalStorage { return get(localSourcesAtom).focus -}, (get, set, update: SourceID[] | ((prev: SourceID[]) => SourceID[])) => { +}, (get, set, update: Update) => { const _ = update instanceof Function ? update(get(focusSourcesAtom)) : update set(localSourcesAtom, { ...get(localSourcesAtom), @@ -50,10 +50,12 @@ export const currentSectionIDAtom = atom("focus") export const currentSectionAtom = atom((get) => { const id = get(currentSectionIDAtom) return get(localSourcesAtom)[id] -}, (get, set, update: SourceID[] | ((prev: SourceID[]) => SourceID[])) => { +}, (get, set, update: Update) => { const _ = update instanceof Function ? update(get(currentSectionAtom)) : update set(localSourcesAtom, { ...get(localSourcesAtom), [get(currentSectionIDAtom)]: _, }) }) + +export type Update = T | ((prev: T) => T) diff --git a/src/components/section/dnd.tsx b/src/components/section/dnd.tsx index 523b936..4f28040 100644 --- a/src/components/section/dnd.tsx +++ b/src/components/section/dnd.tsx @@ -1,3 +1,4 @@ +import type { PropsWithChildren } from "react" import { useCallback, useState } from "react" import type { DragEndEvent, DragStartEvent } from "@dnd-kit/core" import { @@ -13,12 +14,56 @@ import { SortableContext, arrayMove, rectSortingStrategy, useSortable } from "@d import { useAtom } from "jotai" import type { SourceID } from "@shared/types" import { CSS } from "@dnd-kit/utilities" +import { motion } from "framer-motion" import type { ItemsProps } from "./card" import { CardWrapper } from "./card" import { currentSectionAtom } from "~/atoms" export function Dnd() { const [items, setItems] = useAtom(currentSectionAtom) + return ( + + + {items.map(id => ( + + + + ))} + + + ) +} + +interface DndProps { + items: SourceID[] + setItems: (update: SourceID[]) => void +} + +export function DndWrapper({ items, setItems, children }: PropsWithChildren) { const [activeId, setActiveId] = useState(null) const sensors = useSensors(useSensor(MouseSensor), useSensor(TouchSensor)) @@ -29,16 +74,14 @@ export function Dnd() { const { active, over } = event if (active.id !== over?.id) { - setItems((items) => { - const oldIndex = items.indexOf(active.id as any) - const newIndex = items.indexOf(over!.id as any) - - return arrayMove(items, oldIndex, newIndex) - }) + const oldIndex = items.indexOf(active.id as any) + const newIndex = items.indexOf(over!.id as any) + setItems(arrayMove(items, oldIndex, newIndex)) } setActiveId(null) - }, [setItems]) + }, [setItems, items]) + const handleDragCancel = useCallback(() => { setActiveId(null) }, []) @@ -52,9 +95,7 @@ export function Dnd() { onDragCancel={handleDragCancel} > - {items.map(id => ( - - ))} + {children} {!!activeId && } diff --git a/src/components/section/index.tsx b/src/components/section/index.tsx index ecfe074..4c8aaee 100644 --- a/src/components/section/index.tsx +++ b/src/components/section/index.tsx @@ -2,13 +2,13 @@ import { metadata, sectionIds } from "@shared/data" import type { SectionID } from "@shared/types" import { Link } from "@tanstack/react-router" import clsx from "clsx" -import { useSetAtom } from "jotai" +import { useAtom } from "jotai" import { useEffect } from "react" import { Dnd } from "./dnd" import { currentSectionIDAtom } from "~/atoms" export function Section({ id }: { id: SectionID }) { - const setCurrentSectionID = useSetAtom(currentSectionIDAtom) + const [currentSectionID, setCurrentSectionID] = useAtom(currentSectionIDAtom) useEffect(() => { setCurrentSectionID(id) }, [id, setCurrentSectionID]) @@ -30,15 +30,7 @@ export function Section({ id }: { id: SectionID }) { ))} - -
- -
+ { currentSectionID === id && } ) }