<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      手寫tabs 組件

       是說,會遇到一個問題,默認值play back很差,而且因為有動畫,切換的時候給人體驗不好

      但是我仍然覺得我寫的很好,所以記錄這里

       

      'use client';
      import { cn } from '@/lib';
      import React, { memo, ReactNode, useEffect, useState } from 'react';
      import { FC } from 'react';
      
      interface contentType {
        currentTabIndex: number;
        setCurrentTabIndex: (index: number) => void;
        tabsLength: number;
      }
      interface MethodClassProps {
        defaultTab: number;
        children: React.ReactNode;
        tabsLength: number;
      }
      
      const TabsContext = React.createContext<contentType | null>(null);
      
      const useTabsContext = () => {
        const context = React.useContext(TabsContext);
        if (!context) {
          throw new Error('useTabsContext must be used within a TabsProvider');
        }
        return context;
      };
      
      // 必須保證TabsContent和triggerList的長度一致
      export const Tabs: FC<MethodClassProps> = ({ ...props }) => {
        const { children, defaultTab, tabsLength } = props;
        const [currentTabIndex, setCurrentTabIndex] = useState<number>(defaultTab);
      
        return (
          <>
            <TabsContext.Provider
              value={{
                currentTabIndex: currentTabIndex,
                setCurrentTabIndex: setCurrentTabIndex,
                tabsLength: tabsLength,
              }}
            >
              {children}
            </TabsContext.Provider>
          </>
        );
      };
      
      export const TabsTrigger = ({
        extraContent,
        children,
        theme = 'Purple',
        onCurrentTabChange,
      }: {
        extraContent?: ReactNode;
        children: ReactNode[];
        theme?: 'Orange' | 'Purple';
        onCurrentTabChange?: (tab: number) => void;
      }) => {
        const { currentTabIndex, setCurrentTabIndex } = useTabsContext();
        const validChildren = React.Children.toArray(children).filter(
          (child) => React.isValidElement(child) && child !== null,
        );
        return (
          <section className=" relative lls-flex-row bg-white border-b shadow-header text-xs px-5 w-full">
            {validChildren.map((trigger, index) => (
              <div
                key={index + 'triggerlist'}
                className={cn(
                  'lls-flex-row gap-3 py-2 pl-3 pr-7 border-b-3 justify-center items-center transition-all duration-500',
                  {
                    'border-b-white': currentTabIndex !== index + 1,
                    'border-b-Purple-1 ':
                      currentTabIndex === index + 1 && theme === 'Purple',
                    'border-b-Orange-1':
                      currentTabIndex === index + 1 && theme === 'Orange',
                  },
                )}
                onClick={() => {
                  setCurrentTabIndex(index + 1);
                  onCurrentTabChange?.(index + 1);
                }}
              >
                {trigger}
              </div>
            ))}
            {extraContent}
          </section>
        );
      };
      
      export const TabsContent = memo(({ children }: { children: ReactNode[] }) => {
        const { currentTabIndex, tabsLength } = useTabsContext();
        const [translateX, setTranslateX] = useState<string>('');
      
        useEffect(() => {
          setTranslateX(
            currentTabIndex > 1
              ? `translateX(-${((currentTabIndex - 1) / tabsLength) * 100}%)`
              : '',
          );
        }, [currentTabIndex, tabsLength]);
      
        const validChildren = React.Children.toArray(children).filter(
          (child) => React.isValidElement(child) && child !== null,
        );
        return (
          <div className="flex-1 overflow-hidden w-full">
            <div
              style={{
                width: `${tabsLength * 100}%`,
                transform: translateX,
              }}
              className={cn(`lls-flex-row  h-full transition-all duration-500`)}
            >
              {validChildren.map((content, index) => (
                <section
                  key={'content-list' + index}
                  className={cn('w-full basis-1/1  px-5 py-3 h-full overflow-y-auto')}
                >
                  {content}
                </section>
              ))}
            </div>
          </div>
        );
      });
      TabsContent.displayName = 'TabsContent';

       

      posted @ 2025-06-16 13:46  send/me/a/cat  閱讀(13)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 日韩精品一区二区三区人| 盐津县| 精品久久丝袜熟女一二三| 亚洲午夜无码久久久久蜜臀av| 国产综合视频一区二区三区| 亚洲国产精品第一区二区| 国模雨珍浓密毛大尺度150p| 国产成人亚洲无码淙合青草| 亚洲成人四虎在线播放| 巴中市| 亚洲精品久久国产高清小说| 国产综合久久99久久| 亳州市| 蜜桃成人无码区免费视频网站| 性欧美vr高清极品| 凤阳县| 自拍视频一区二区三区四区| 国产不卡一区不卡二区| 精品国产中文字幕在线| 亚洲a人片在线观看网址| 久久综合久久美利坚合众国 | 九色综合国产一区二区三区 | 中文无码乱人伦中文视频在线| 东京热人妻丝袜无码AV一二三区观| 亚洲成人精品一区二区中| 夜色福利站WWW国产在线视频| 国产播放91色在线观看| 亚洲成人网在线观看| 亚洲精品乱码久久久久久蜜桃 | 国产不卡一区不卡二区| 中文字幕乱偷无码av先锋蜜桃| 亚洲成人www| 99精品人妻少妇一区| 亚洲午夜福利精品一二飞| 国产在线精品福利91香蕉| 中文字幕自拍偷拍福利视频| 国产精品自在自线视频| 亚洲精品日韩在线观看| 中文字幕日韩一区二区不卡| 成 人色 网 站 欧美大片在线观看 | 国产在线拍揄自揄拍无码|