From ec06f87284db9a371eabaf7939477e65593f4905 Mon Sep 17 00:00:00 2001 From: mango Date: Mon, 7 Oct 2024 21:44:32 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96picker=E7=BB=84?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 3 +- pnpm-lock.yaml | 22 ++++---------- src/components/widgets/wheel/helpers/index.ts | 12 +++++++- src/components/widgets/wheel/index.scss | 14 +++++---- src/components/widgets/wheel/index.tsx | 29 ++++++++----------- src/components/widgets/wheel/models/index.tsx | 1 + 6 files changed, 39 insertions(+), 42 deletions(-) diff --git a/package.json b/package.json index 1cc619a3..cbff7e4c 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "change-case": "^5.4.4", "classnames": "^2.5.1", "dayjs": "^1.11.13", - "framer-motion": "^11.5.4", + "framer-motion": "^11.11.1", "i18next": "^23.15.1", "immer": "^10.1.1", "js-cookie": "^3.0.5", @@ -84,7 +84,6 @@ "rc-cascader": "^3.27.0", "react": "^18.3.1", "react-dom": "^18.3.1", - "react-geiger": "^1.2.0", "react-i18next": "^15.0.0", "react-router-dom": "^6.26.2", "smooth-scroll-into-view-if-needed": "^2.0.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bfeb2cf8..d3db2754 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -42,8 +42,8 @@ importers: specifier: ^1.11.13 version: 1.11.13 framer-motion: - specifier: ^11.5.4 - version: 11.5.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^11.11.1 + version: 11.11.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) i18next: specifier: ^23.15.1 version: 23.15.1 @@ -68,9 +68,6 @@ importers: react-dom: specifier: ^18.3.1 version: 18.3.1(react@18.3.1) - react-geiger: - specifier: ^1.2.0 - version: 1.2.0(react@18.3.1) react-i18next: specifier: ^15.0.0 version: 15.0.0(i18next@23.15.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -3004,8 +3001,8 @@ packages: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} - framer-motion@11.5.4: - resolution: {integrity: sha512-E+tb3/G6SO69POkdJT+3EpdMuhmtCh9EWuK4I1DnIC23L7tFPrl8vxP+LSovwaw6uUr73rUbpb4FgK011wbRJQ==} + framer-motion@11.11.1: + resolution: {integrity: sha512-Ucr9eHSrk0d+l6vyl9fvq6omh/PAWHjS+PlczpsoUdhJo1TuF3ULWJNuAMnpWQ1dGyPOyoUVuYlUKjE/s8dyCA==} peerDependencies: '@emotion/is-prop-valid': '*' react: ^18.0.0 @@ -4363,11 +4360,6 @@ packages: react-fast-compare@3.2.2: resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} - react-geiger@1.2.0: - resolution: {integrity: sha512-8DYxEWIE66Rb+8A9rVd+Z7a1lQtGxFoRObOz+UC+elvskNQqp5y5PdpS9u/4XOiG903ZuPVMReTJ3bJdLfaLnA==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-helmet-async@1.3.0: resolution: {integrity: sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==} peerDependencies: @@ -8996,7 +8988,7 @@ snapshots: forwarded@0.2.0: {} - framer-motion@11.5.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + framer-motion@11.11.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: tslib: 2.6.2 optionalDependencies: @@ -10652,10 +10644,6 @@ snapshots: react-fast-compare@3.2.2: {} - react-geiger@1.2.0(react@18.3.1): - dependencies: - react: 18.3.1 - react-helmet-async@1.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.24.8 diff --git a/src/components/widgets/wheel/helpers/index.ts b/src/components/widgets/wheel/helpers/index.ts index bc06d829..06693027 100644 --- a/src/components/widgets/wheel/helpers/index.ts +++ b/src/components/widgets/wheel/helpers/index.ts @@ -1,5 +1,5 @@ import { isNumber, isString } from '@busymango/is-esm'; -import { compact } from '@busymango/utils'; +import { and, compact } from '@busymango/utils'; import type { ReactTargetType } from '@/models'; import { iFindElement } from '@/utils'; @@ -47,3 +47,13 @@ export const iScrollIntoView = (target?: ReactTargetType) => { inline: 'center', }); }; + +export const isSupportSnape = () => + and( + [ + ['scroll-snap-type', 'y mandatory'], + ['scroll-snap-stop', 'normal'], + ['scroll-snap-align', 'center'], + ] satisfies [string, string][], + (args) => CSS.supports(...args) + ); diff --git a/src/components/widgets/wheel/index.scss b/src/components/widgets/wheel/index.scss index 603ffb28..d1d7a981 100644 --- a/src/components/widgets/wheel/index.scss +++ b/src/components/widgets/wheel/index.scss @@ -13,12 +13,18 @@ align-items: center; justify-content: center; - // scroll-snap-stop: normal; - // scroll-snap-align: center; - // transform-style: preserve-3d; } +.is-scroll-snap { + scroll-snap-type: y mandatory; + + & > .option { + scroll-snap-stop: normal; + scroll-snap-align: center; + } +} + .wheel { width: 100%; height: 100%; @@ -35,8 +41,6 @@ transform-style: preserve-3d; scroll-behavior: smooth; - // scroll-snap-type: y mandatory; - -webkit-overflow-scrolling: touch; &::-webkit-scrollbar { diff --git a/src/components/widgets/wheel/index.tsx b/src/components/widgets/wheel/index.tsx index 2be41402..8ed37d05 100644 --- a/src/components/widgets/wheel/index.tsx +++ b/src/components/widgets/wheel/index.tsx @@ -13,6 +13,7 @@ import { useControlState } from '../control'; import { identified, iScrollIntoView, + isSupportSnape, iTarget, WHEEL_ITEM_ID_NAME, } from './helpers'; @@ -62,7 +63,7 @@ const IWheelOption: ReactCFC = (props) => { }; export const IWheel: React.FC = (props) => { - const { options } = props; + const { options, isScrollSnape = isSupportSnape() } = props; const view = useRef(); @@ -81,11 +82,11 @@ export const IWheel: React.FC = (props) => { iScrollIntoView(element); } } - }, 10 * FRAME2MS); + }, 0); useEffect(() => { const { current } = container; - if (current) { + if (current && !isScrollSnape) { const { starer, cancel } = iEventListener; current?.addEventListener('scrollend', starer); return () => { @@ -93,7 +94,7 @@ export const IWheel: React.FC = (props) => { current?.removeEventListener('scrollend', starer); }; } - }, [container, iEventListener]); + }, [container, iEventListener, isScrollSnape]); const iScroll = useDebounceFunc(() => { const index = options?.findIndex((option, index) => { @@ -124,7 +125,13 @@ export const IWheel: React.FC = (props) => { ); return ( -
+
@@ -147,15 +154,3 @@ export const IWheel: React.FC = (props) => {
); }; - -// useEffect(() => { -// const { current } = refs.floating; -// if (open && current) { -// value?.forEach((e, i) => { -// const id = identified(e, i); -// const selector = `[${DATA_ID_NAME}="${id}"]`; -// const element = current.querySelector(selector); -// isHTMLElement(element) && iScrollIntoView(element); -// }); -// } -// }, [open, value, refs.floating]); diff --git a/src/components/widgets/wheel/models/index.tsx b/src/components/widgets/wheel/models/index.tsx index e1ec6331..bcd8b2dd 100644 --- a/src/components/widgets/wheel/models/index.tsx +++ b/src/components/widgets/wheel/models/index.tsx @@ -7,6 +7,7 @@ export interface IWheelOptionProps { export interface IWheelProps { options?: ControlOption[]; + isScrollSnape?: boolean; value?: ControlOption['value']; onChange?: (value?: ControlOption['value']) => void; }