PageSourceSearch

https://www.joshuawootonn.com/_next/static/chunks/9211-078350cd74db86aa.js

js joshuawootonn.com collected 2026-10-03 22:11:08 UTC 44,253 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[9211],{374:function(n,e,t){t.d(e,{B:function(){return Demo}});var s=t(1527),a=t(1955),r=t(3716),i=t(4875),o=t.n(i),l=t(1315),c=t(959),d=t(8584);let u=(0,c.forwardRef)(function(n,e){let{className:t,...a}=n;return(0,s.jsx)(l.E.button,{ref:e,...a,className:o()(t,"cursor-pointer origin-center flex items-center justify-center select-none flex-shrink-0 bg-transparent")})});function Editor(n){let{className:e,isOpen:t,...r}=n;return(0,s.jsx)("div",{className:o()(t?"h-auto":"h-80","flex flex-col w-full border-1 border-t-0 border-zinc-100 rounded-none","[&>.sp-stack>.sp-tabs]:border-b-1","[&>.sp-stack>.sp-code-editor]:rounded-none","[&>.sp-stack]:h-full [&>div]:grow [&>div]:rounded-none",e),...r,children:(0,s.jsx)(a._V,{})})}function Preview(n){let{className:e,children:t,...r}=n;return(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("div",{className:o()("flex flex-col z-0 relative rounded-none",e),...r,children:(0,s.jsx)(a.Gj,{suppressHydrationWarning:!0,className:o()("h-full border-1 rounded-t-none border-zinc-100 [&_.sp-sides_*]:border-zinc-100","[&>.sp-preview-container]:rounded-none","[&_.sp-cube-wrapper]:opacity-0"),showOpenInCodeSandbox:!1,showRestartButton:!1,showRefreshButton:!1,children:(0,s.jsx)(l.E.div,{className:"absolute bottom-2 right-2 flex space-x-3 items-center justify-end p-1 z-10",children:t})})})})}var m=t(3692),b=t(3944);function RefreshButton(){let{refresh:n}=(0,a.xN)(),e=(0,a.QE)(),t=(0,m.c)(0),r=(0,c.useCallback)(()=>{n()},[n]);return(0,c.useEffect)(()=>{"LOADING"===e?(0,b.j)(t,t.get()-360,{repeat:1/0,ease:"linear",duration:.5}):(0,b.j)(t,t.get(),{duration:0})},[e,t]),(0,s.jsx)(u,{onClick:r,style:{rotate:t},children:(0,s.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor",className:"w-4 h-4 -scale-x-100 scale-y-100 text-black",children:(0,s.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99"})})})}var f=t(60);function Demo(n){var e,t;let{files:i,className:m,previewHeightClassname:b,hideEditor:p,options:x,...h}=n,[v,g]=(0,c.useState)(!1),T=f.a4;return(0,s.jsx)(a.oT,{template:"react-ts",files:i,theme:T,options:{...x,externalResources:["https://cdn.tailwindcss.com",...null!==(e=null==x?void 0:x.externalResources)&&void 0!==e?e:[]],autorun:!0},...h,children:(0,s.jsxs)("div",{className:o()(m,"flex flex-col items-center justify-center space-y-2 not-prose","article-content-lg my-4 md:my-12"),children:[(0,s.jsxs)("div",{className:"flex flex-col w-full mb-2",children:[(0,s.jsxs)(Preview,{className:o()(b),children:[(0,s.jsxs)(r.fC,{children:[(0,s.jsx)(r.xz,{asChild:!0,children:(0,s.jsx)(u,{className:"text-black",children:(0,s.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor",className:"w-4 h-4 -scale-x-100 scale-y-100",children:(0,s.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M2
10.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15"})})})}),(0,s.jsxs)(r.h_,{children:[(0,s.jsx)(r.aV,{className:"bg-foreground/40 dark:bg-background/50 fixed inset-0 z-30"}),(0,s.jsx)(a.oT,{template:"react-ts",files:i,theme:T,options:{...x,externalResources:["https://cdn.tailwindcss.com",...null!==(t=null==x?void 0:x.externalResources)&&void 0!==t?t:[]],autorun:!0},...h,children:(0,s.jsx)(r.VY,{className:"z-40 shadow-md bg-white inset-8 max-w-5xl mx-auto fixed rounded-none",children:(0,s.jsx)(a.Gj,{suppressHydrationWarning:!0,className:o()("z-0 relative h-full border-2 rounded-none [&_.sp-sides_*]:border-black","[&>.sp-preview-container]:rounded-none","[&_.sp-cube-wrapper]:opacity-0"),showOpenInCodeSandbox:!1,showRestartButton:!1,showRefreshButton:!1,children:(0,s.jsxs)(l.E.div,{className:"absolute bottom-2 right-2 flex space-x-3 items-center justify-end p-1 z-10",children:[(0,s.jsx)(r.x8,{asChild:!0,children:(0,s.jsx)(u,{"aria-label":"Close",children:(0,s.jsx)(u,{className:"text-black",children:(0,s.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor",className:"w-4 h-4",children:(0,s.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M9 9V4.5M9 9H4.5M9 9L3.75 3.75M9 15v4.5M9 15H4.5M9 15l-5.25 5.25M15 9h4.5M15 9V4.5M15 9l5.25-5.25M15 15h4.5M15 15v4.5m0-4.5l5.25 5.25"})})})})}),(0,s.jsx)(RefreshButton,{})]})})})})]})]}),(0,s.jsx)(RefreshButton,{})]}),!p&&(0,s.jsx)(Editor,{isOpen:v})]}),!p&&(0,s.jsx)(d.z,{size:"sm",onClick:()=>g(n=>!n),className:"mt-1",children:v?"show less":"show more"})]})})}},60:function(n,e,t){t.d(e,{a4:function(){return s},aI:function(){return a}});let s={colors:{surface1:"#ffffff",surface2:"#F3F3F3",surface3:"#f5f5f5",clickable:"#959da5",base:"#24292e",disabled:"#d1d4d8",hover:"#24292e",accent:"#24292e"},syntax:{keyword:"#666666",property:{color:"#121212"},plain:"#24292e",static:"#121212",string:"#121212",definition:"#666666",punctuation:"#24292e",tag:"#666666",comment:{color:"#6a737d",fontStyle:"normal"}},font:{body:'var(--font-dm-sans), -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"',mono:'var(--font-fira-mono), ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',size:"12px",lineHeight:"18px"}},a={colors:{surface1:"#1a1a1a",surface2:"#2a2a2a",surface3:"#333333",clickable:"#959da5",base:"#ffffff",disabled:"#666666",hover:"#ffffff",accent:"#ffffff"},syntax:{keyword:"#999999",property:{color:"#ffffff"},plain:"#ffffff",static:"#ffffff",string:"#ffffff",definition:"#999999",punctuation:"#ffffff",tag:"#999999",comment:{color:"#888888",fontStyle:"normal"}},font:{body:'var(--font-dm-sans), -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"',mono:'var(--font-fira-mono), ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',size:"12px",lineHeight:"18px"}}},9211:function(n,e,t){t.d(e,{k4:function(){return CSSExample},iE:function(){return FramerExample},_M:function(){return FramerLayoutExample},CG:function(){return SpringExample},L4:function(){return TabsDemo},K1:function(){return TransitionGroupExample}});var s=t(1527);t(959);var a=t(374);let r='import { useState } from "react";\nimport { Framer } from "./framer";\nimport { useTabs } from "./useTabs";\nimport { Circle, Square, Triangle } from "./shapes";\n\nexport default function App() {\n  const [hookProps] = useState({\n    tabs: [\n      {\n        label: "Circle",\n        children: <Circle />,\n        id: "Circle",\n      },\n      {\n        label: "Triangle",\n        children: <Triangle />,\n        id: "Triangle",\n      },\n      {\n        label: "Square",\n        children: <Square />,\n        id: "Square",\n      },\n    ],\n    initialTabId: "Triangle",\n  });\n  const framer = useTabs(hookProps);\n  return (\n    <div className="w-full flex flex-col space-y-24 items-center justify-center">\n      <div className="max-w-6xl">\n        <Framer.Tabs {...framer.tabProps} />\n        <Framer.Content\n          {...framer.contentProps}
1\n          className="text-center rounded-3xl py-9 flex flex-col items-center"\n        >\n          {framer.selectedTab.children}\n        </Framer.Content>\n      </div>\n    </div>\n  );\n}\n',i='import { ReactNode, useState } from "react";\n\nexport type Tab = { label: string; id: string; children: ReactNode };\n\nexport function useTabs({\n  tabs,\n  initialTabId,\n  onChange,\n}: {\n  tabs: Tab[];\n  initialTabId: string;\n  onChange?: (id: string) => void;\n}) {\n  const [[selectedTabIndex, direction], setSelectedTab] = useState(() => {\n    const indexOfInitialTab = tabs.findIndex((tab) => tab.id === initialTabId);\n    return [indexOfInitialTab === -1 ? 0 : indexOfInitialTab, 0];\n  });\n\n  return {\n    tabProps: {\n      tabs,\n      selectedTabIndex,\n      onChange,\n      setSelectedTab,\n    },\n    selectedTab: tabs[selectedTabIndex],\n    contentProps: {\n      direction,\n      selectedTabIndex,\n    },\n  };\n}\n',o='import classNames from "classnames";\nimport React, { ReactNode, useEffect, useRef, useState } from "react";\nimport { AnimatePresence, motion } from "framer-motion";\n\nimport { Tab } from "./useTabs";\n\nconst transition = {\n  type: "tween",\n  ease: "easeOut",\n  duration: 0.15,\n};\n\ntype Props = {\n  selectedTabIndex: number;\n  tabs: Tab[];\n  setSelectedTab: (input: [number, number]) => void;\n};\n\nconst Tabs = ({\n  tabs,\n  selectedTabIndex,\n  setSelectedTab,\n}: Props): JSX.Element => {\n  const [buttonRefs, setButtonRefs] = useState<Array<HTMLButtonElement | null>>(\n    []\n  );\n\n  useEffect(() => {\n    setButtonRefs((prev) => prev.slice(0, tabs.length));\n  }, [tabs.length]);\n\n  const navRef = useRef<HTMLDivElement>(null);\n  const navRect = navRef.current?.getBoundingClientRect();\n\n  const selectedRect = buttonRefs[selectedTabIndex]?.getBoundingClientRect();\n\n  const [hoveredTabIndex, setHoveredTabIndex] = useState<number | null>(null);\n  const hoveredRect =\n    buttonRefs[hoveredTabIndex ?? -1]?.getBoundingClientRect();\n\n  return (\n    <nav\n      ref={navRef}\n      className="flex flex-shrink-0 justify-center items-center relative z-0 py-2"\n      onPointerLeave={(e) => setHoveredTabIndex(null)}\n    >\n      {tabs.map((item, i) => {\n        return (\n          <motion.button\n            key={i}\n            className={classNames(\n              "text-md relative rounded-md flex items-center h-8 px-4 z-20 bg-transparent text-sm text-slate-500 cursor-pointer select-none transition-colors",\n              {\n                "text-slate-700":\n                  hoveredTabIndex === i || selectedTabIndex === i,\n              }\n            )}\n            ref={(el) => (buttonRefs[i] = el)}\n            onPointerEnter={() => {\n              setHoveredTabIndex(i);\n            }}\n            onFocus={() => {\n              setHoveredTabIndex(i);\n            }}\n            onClick={() => {\n              setSelectedTab([i, i > selectedTabIndex ? 1 : -1]);\n            }}\n          >\n            {item.label}\n          </motion.button>\n        );\n      })}\n      <AnimatePresence>\n        {hoveredRect && navRect && (\n          <motion.div\n            key={"hover"}\n            className="absolute z-10 top-0 left-0 rounded-md bg-gray-200"\n            initial={{\n              x: hoveredRect.left - navRect.left,\n              y: hoveredRect.top - navRect.top,\n              width: hoveredRect.width,\n              height: hoveredRect.height,\n              opacity: 0,\n            }}\n            animate={{\n              x: hoveredRect.left - navRect.left,\n              y: hoveredRect.top - navRect.top,\n              width: hoveredRect.width,\n              height: hoveredRect.height,\n              opacity: 1,\n            }}\n            exit={{\n              x: hoveredRect.left - navRect.left,\n              y: hoveredRect.top - navRect.top,\n              width: hoveredRect.width,\n              height: hoveredRect.height,\n              opacity: 0,\n            }}\n            transition={transition}\n          />\n        )}\n      </AnimatePresence>\n      {selectedRect && navRect && (\n        <motion.div\n          className={"absolute z-10 bottom-0 left-0 h-[2px] bg-slate-500"}\n          initial={false}\n          animate={{\n            width: selectedRect.width * 0.8,\n            x: `calc(${selectedRect.left - navRect.left}px + 10%)`,\n            opacity: 1,\n          }}\n          transition={transition}\n        />\n      )}\n    </nav>\n  );\n};\n\nconst Content = ({\n  children,\n  className,\n  selectedTabIndex,\n  direction,\n}: {\n  direction: number;\n  selectedTabIndex: number;\n  children: ReactNode;\n  className?: string;\n}): JSX.Element =>
1 {\n  return (\n    <AnimatePresence exitBeforeEnter={false} custom={direction}>\n      <motion.div\n        key={selectedTabIndex}\n        variants={{\n          enter: (direction) => ({\n            opacity: 0,\n            x: direction > 0 ? 100 : -100,\n            scale: 0.8,\n          }),\n          center: { opacity: 1, x: 0, scale: 1, rotate: 0 },\n          exit: (direction) => ({\n            opacity: 0,\n            x: direction > 0 ? -100 : 100,\n            scale: 0.8,\n            position: "absolute",\n          }),\n        }}\n        transition={{ duration: 0.25 }}\n        initial={"enter"}\n        animate={"center"}\n        exit={"exit"}\n        custom={direction}\n        className={className}\n      >\n        {children}\n      </motion.div>\n    </AnimatePresence>\n  );\n};\n\nexport const Framer = { Tabs, Content };\n',l='export function Circle() {\n    return (\n      <svg\n        width="200"\n        height="200"\n        viewBox="0 0 340 340"\n        fill="none"\n        xmlns="http://www.w3.org/2000/svg"\n      >\n        <path\n          d="M340 170C340 263.888 263.888 340 170 340C76.1116 340 0 263.888 0 170C0 76.1116 76.1116 0 170 0C263.888 0 340 76.1116 340 170Z"\n          fill="#FE65B7"\n        />\n      </svg>\n    );\n  }\n  \n  export function Square() {\n    return (\n      <svg\n        width="200"\n        height="200"\n        viewB
1ox="0 0 412 412"\n        fill="none"\n        xmlns="http://www.w3.org/2000/svg"\n      >\n        <rect\n          x="211.48"\n          y="-6"\n          width="300"\n          height="300"\n          rx="15"\n          transform="rotate(46.4634 211.48 -6)"\n          fill="#446DF6"\n        />\n      </svg>\n    );\n  }\n  \n  export function Triangle() {\n    return (\n      <svg\n        width="200"\n        height="208"\n        viewBox="0 0 349 364"\n        fill="none"\n        xmlns="http://www.w3.org/2000/svg"\n      >\n        <path\n          d="M328.852 1.79834C339.737 -2.05613 350.712 7.31786 348.608 18.6715L287.058 350.766C284.954 362.119 271.348 366.937 262.568 359.438L5.74062 140.087C-3.03979 132.588 -0.409476 118.396 10.4752 114.542L328.852 1.79834Z"\n          fill="#AB87FF"\n        />\n      </svg>\n    );\n  }  \n',CSSExample=()=>(0,s.jsx)(a.B,{previewHeightClassname:"h-100",files:{"/css.tsx":{active:!0,code:'import classNames from "classnames";\nimport {\n  PointerEvent,\n  FocusEvent,\n  useEffect,\n  useRef,\n  useState,\n  CSSProperties,\n} from "react";\n\ntype Tab = { label: string; id: string };\n\ntype Props = {\n  selectedTabIndex: number;\n  tabs: Tab[];\n  setSelectedTab: (input: number) => void;\n};\n\nexport const CSSTabs = ({\n  tabs,\n  selectedTabIndex,\n  setSelectedTab,\n}: Props): JSX.Element => {\n  const [buttonRefs, setButtonRefs] = useState<Array<HTMLButtonElement | null>>(\n    []\n  );\n\n  useEffect(() => {\n    setButtonRefs((prev) => prev.slice(0, tabs.length));\n  }, [tabs.length]);\n\n  const [hoveredTabIndex, setHoveredTabIndex] = useState<number | null>(null);\n  const [hoveredRect, setHoveredRect] = useState<DOMRect | null>(null);\n\n  const navRef = useRef<HTMLDivElement>(null);\n  const navRect = navRef.current?.getBoundingClientRect();\n\n  const selectedRect = buttonRefs[selectedTabIndex]?.getBoundingClientRect();\n\n  const [isInitialHoveredElement, setIsInitialHoveredElement] = useState(true);\n  const isInitialRender = useRef(true);\n\n  const onLeaveTabs = () => {\n    setIsInitialHoveredElement(true);\n    setHoveredTabIndex(null);\n  };\n\n  const onEnterTab = (\n    e: PointerEvent<HTMLButtonElement> | FocusEvent<HTMLButtonElement>,\n    i: number\n  ) => {\n    if (!e.target || !(e.target instanceof HTMLButtonElement)) return;\n\n    setHoveredTabIndex((prev) => {\n      if (prev != null && prev !== i) {\n        setIsInitialHoveredElement(false);\n      }\n\n      return i;\n    });\n    setHoveredRect(e.target.getBoundingClientRect());\n  };\n\n  const onSelectTab = (i: number) => {\n    setSelectedTab(i);\n  };\n\n  let hoverStyles: CSSProperties = { opacity: 0 };\n  if (navRect && hoveredRect) {\n    hoverStyles.transform = `translate3d(${hoveredRect.left - navRect.left}px,${\n      hoveredRect.top - navRect.top\n    }px,0px)`;\n    hoverStyles.width = hoveredRect.width;\n    hoverStyles.height = hoveredRect.height;\n    hoverStyles.opacity = hoveredTabIndex != null ? 1 : 0;\n    hoverStyles.transition = isInitialHoveredElement\n      ? `opacity 150ms`\n      : `transform 150ms 0ms, opacity 150ms 0ms, width 150ms`;\n  }\n\n  let selectStyles: CSSProperties = { opacity: 0 };\n  if (navRect && selectedRect) {\n    selectStyles.width = selectedRect.width * 0.8;\n    selectStyles.transform = `translateX(calc(${\n      selectedRect.left - navRect.left\n    }px + 10%))`;\n    selectStyles.opacity = 1;\n    selectStyles.transition = isInitialRender.current\n      ? `opacity 150ms 150ms`\n      : `transform 150ms 0ms, opacity 150ms 150ms, width 150ms`;\n\n    isInitialRender.current = false;\n  }\n\n  return (\n    <nav\n      ref={navRef}\n      className="flex flex-shrink-0 justify-center items-center relative z-0 py-2"\n      onPointerLeave={onLeaveTabs}\n    >\n      {tabs.map((item, i) => {\n        return (\n          <button\n            key={i}\n            className={classNames(\n              "text-md relative rounded-md flex items-center h-8 px-4 z-20 bg-transparent text-sm text-slate-500 cursor-pointer select-none transition-colors",\n              {\n                "text-slate-700":\n                  hoveredTabIndex === i || selectedTabIndex === i,\n              }\n            )}\n            ref={(el) => (buttonRefs[i] = el)}\n            onPointerEnter={(e) => onEnterTab(e, i)}\n            onFocus={(e) => onEnterTab(e, i)}\n            onClick={() => onSelectTab(i)}\n          >\n            {item.label}\n          </button>\n        );\n      })}\n      <div\n        className="absolute z-10 top-0 left-0 rounded-md bg-gray-200 transition-[width]"\n        style={hoverStyles}\n      />\n      <div\n        className={"absolute z-10 bottom-0 left-0 h-0.5 bg-slate-500"}\n        style={selectStyles}\n      />\n    </nav>\n  );\n};\n\n'}
1,"/App.tsx":'import { useState } from "react";\nimport { CSSTabs } from "./css";\nimport { useTabs } from "./useTabs";\nimport { Circle, Square, Triangle } from "./shapes";\n\nexport default function App() {\n  const [hookProps] = useState({\n    tabs: [\n      {\n        label: "Circle",\n        children: <Circle />,\n        id: "Circle",\n      },\n      {\n        label: "Triangle",\n        children: <Triangle />,\n        id: "Triangle",\n      },\n      {\n        label: "Square",\n        children: <Square />,\n        id: "Square",\n      },\n    ],\n    initialTabId: "Triangle",\n  });\n  const css = useTabs(hookProps);\n  return (\n    <div className="w-full flex flex-col space-y-24 items-center justify-center">\n      <div className="max-w-6xl">\n        <CSSTabs {...css.tabProps} />\n        <div className="py-9 flex flex-col items-center">{css.selectedTab.children}</div>\n      </div>\n    </div>\n  );\n}\n',"/shapes.tsx":'export function Circle() {\n    return (\n      <svg\n        width="200"\n        height="200"\n        viewB
1ox="0 0 340 340"\n        fill="none"\n        xmlns="http://www.w3.org/2000/svg"\n      >\n        <path\n          d="M340 170C340 263.888 263.888 340 170 340C76.1116 340 0 263.888 0 170C0 76.1116 76.1116 0 170 0C263.888 0 340 76.1116 340 170Z"\n          fill="#FE65B7"\n        />\n      </svg>\n    );\n  }\n  \n  export function Square() {\n    return (\n      <svg\n        width="200"\n        height="200"\n        viewBox="0 0 412 412"\n        fill="none"\n        xmlns="http://www.w3.org/2000/svg"\n      >\n        <rect\n          x="211.48"\n          y="-6"\n          width="300"\n          height="300"\n          rx="15"\n          transform="rotate(46.4634 211.48 -6)"\n          fill="#446DF6"\n        />\n      </svg>\n    );\n  }\n  \n  export function Triangle() {\n    return (\n      <svg\n        width="200"\n        height="208"\n        viewBox="0 0 349 364"\n        fill="none"\n        xmlns="http://www.w3.org/2000/svg"\n      >\n        <path\n          d="M328.852 1.79834C339.737 -2.05613 350.712 7.31786 348.608 18.6715L287.058 350.766C284.954 362.119 271.348 366.937 262.568 359.438L5.74062 140.087C-3.03979 132.588 -0.409476 118.396 10.4752 114.542L328.852 1.79834Z"\n          fill="#AB87FF"\n        />\n      </svg>\n    );\n  }\n  ',"/useTabs.tsx":'import { ReactNode, useState } from "react";\n\ntype Tab = { label: string; id: string; children: ReactNode };\n\nexport function useTabs({\n  tabs,\n  initialTabId,\n  onChange,\n}: {\n  tabs: Tab[];\n  initialTabId: string;\n  onChange?: (id: string) => void;\n}) {\n  const [selectedTabIndex, setSelectedTab] = useState(() =>
1 {\n    const indexOfInitialTab = tabs.findIndex((tab) => tab.id === initialTabId);\n    return indexOfInitialTab === -1 ? 0 : indexOfInitialTab;\n  });\n\n  return {\n    tabProps: {\n      tabs,\n      selectedTabIndex,\n      onChange,\n      setSelectedTab,\n    },\n    selectedTab: tabs[selectedTabIndex],\n  };\n}\n'},customSetup:{dependencies:{classnames:"^2.3.1"}}}),TransitionGroupExample=()=>(0,s.jsx)(a.B,{previewHeightClassname:"h-100",files:{"/transition-group.tsx":{active:!0,code:'import classNames from "classnames";\nimport {\n  useEffect,\n  useRef,\n  useState,\n  PointerEvent,\n  FocusEvent,\n  CSSProperties,\n} from "react";\nimport { Transition } from "react-transition-group";\n\nimport { Tab } from "./useTabs";\n\ntype Props = {\n  selectedTabIndex: number;\n  tabs: Tab[];\n  setSelectedTab: (input: number) => void;\n};\n\nconst duration = 300;\n\nconst transitionStyles = {\n  entering: {\n    opacity: 1,\n    transition: `transform 0ms, opacity 150ms, width 0ms`,\n  },\n  entered: {\n    opacity: 1,\n    transition: `transform 150ms 0ms, opacity 150ms 0ms, width 150ms`,\n  },\n  exiting: {\n    opacity: 0,\n    transition: `transform 0ms, opacity 150ms, width 0ms`,\n  },\n  exited: { opacity: 0 },\n  unmounted: {},\n};\n\nexport const TransitionGroupTabs = ({\n  tabs,\n  selectedTabIndex,\n  setSelectedTab,\n}: Props): JSX.Element => {\n  const [buttonRefs, setButtonRefs] = useState<Array<HTMLButtonElement | null>>(\n    []\n  );\n\n  useEffect(() => {\n    setButtonRefs((prev) => prev.slice(0, tabs.length));\n  }, [tabs.length]);\n\n  const navRef = useRef<HTMLDivElement>(null);\n  const navRect = navRef.current?.getBoundingClientRect();\n\n  const [hoveredTabIndex, setHoveredTabIndex] = useState<number | null>(null);\n  const [hoveredRect, setHoveredRect] = useState<DOMRect | null>(null);\n\n  const selectedRect = buttonRefs[selectedTabIndex]?.getBoundingClientRect();\n\n  const onLeaveTabs = () => {\n    setHoveredTabIndex(null);\n  };\n\n  const onEnterTab = (\n    e: PointerEvent<HTMLButtonElement> | FocusEvent<HTMLButtonElement>,\n    i: number\n  ) => {\n    if (!e.target || !(e.target instanceof HTMLButtonElement)) return;\n\n    setHoveredTabIndex(i);\n    setHoveredRect(e.target.getBoundingClientRect());\n  };\n\n  const onSelectTab = (i: number) => {\n    setSelectedTab(i);\n  };\n\n  const hoverStyles: CSSProperties =\n    navRect && hoveredRect\n      ? {\n          transform: `translate3d(${hoveredRect.left - navRect.left}px,${\n            hoveredRect.top - navRect.top\n          }px,0px)`,\n          width: hoveredRect.width,\n          height: hoveredRect.height,\n        }\n      : {};\n\n  const selectStyles: CSSProperties =\n    navRect && selectedRect\n      ? {\n          width: selectedRect.width * 0.8,\n          transform: `translateX(calc(${\n            selectedRect.left - navRect.left\n          }px + 10%))`,\n        }\n      : {};\n\n  return (\n    <nav\n      ref={navRef}\n      className="flex flex-shrink-0 justify-center items-center relative z-0 py-2"\n      onPointerLeave={onLeaveTabs}\n    >\n      {tabs.map((item, i) => {\n        return (\n          <button\n            key={i}\n            className={classNames(\n              "text-md relative rounded-md flex items-center h-8 px-4 z-20 bg-transparent text-sm text-slate-500 cursor-pointer select-none transition-colors",\n              {\n                "text-slate-700":\n                  hoveredTabIndex === i || selectedTabIndex === i,\n              }\n            )}\n            ref={(el) => (buttonRefs[i] = el)}\n            onPointerEnter={(e) => onEnterTab(e, i)}\n            onFocus={(e) => onEnterTab(e, i)}\n            onClick={() => onSelectTab(i)}\n          >\n            {item.label}\n          </button>\n        );\n      })}\n\n      <Transition in={hoveredTabIndex != null} timeout={duration}>\n        {(state) => (\n          <div\n            className="absolute z-10 top-0 left-0 rounded-md bg-gray-200 transition-[width]"\n            style={{\n              ...hoverStyles,\n              ...transitionStyles[state],\n            }}\n          />\n        )}\n      </Transition>\n      <Transition in={selectedRect != null} timeout={duration}>\n        {(state) => (\n          <div\n            className={"absolute z-10 bottom-0 left-0 h-0.5 bg-slate-500"}\n            style={{\n              ...selectStyles,\n              ...transitionStyles[state],\n            }}\n          />\n        )}\n      </Transition>\n    </nav>\n  );\n};\n'}
1,"/App.tsx":'import { useState } from "react";\nimport { TransitionGroupTabs } from "./transition-group";\nimport { useTabs } from "./useTabs";\nimport { Circle, Square, Triangle } from "./shapes";\n\nexport default function App() {\n  const [hookProps] = useState({\n    tabs: [\n      {\n        label: "Circle",\n        children: <Circle />,\n        id: "Circle",\n      },\n      {\n        label: "Triangle",\n        children: <Triangle />,\n        id: "Triangle",\n      },\n      {\n        label: "Square",\n        children: <Square />,\n        id: "Square",\n      },\n    ],\n    initialTabId: "Triangle",\n  });\n  const transitionGroup = useTabs(hookProps);\n  return (\n    <div className="w-full flex flex-col space-y-24 items-center justify-center">\n      <div className="max-w-6xl">\n        <TransitionGroupTabs {...transitionGroup.tabProps} />\n        <div className="py-9 flex flex-col items-center">{transitionGroup.selectedTab.children}</div>\n      </div>\n    </div>\n  );\n}\n',"/shapes.tsx":'export function Circle() {\n    return (\n      <svg\n        width="200"\n        height="200"\n        viewB
1ox="0 0 340 340"\n        fill="none"\n        xmlns="http://www.w3.org/2000/svg"\n      >\n        <path\n          d="M340 170C340 263.888 263.888 340 170 340C76.1116 340 0 263.888 0 170C0 76.1116 76.1116 0 170 0C263.888 0 340 76.1116 340 170Z"\n          fill="#FE65B7"\n        />\n      </svg>\n    );\n  }\n  \n  export function Square() {\n    return (\n      <svg\n        width="200"\n        height="200"\n        viewBox="0 0 412 412"\n        fill="none"\n        xmlns="http://www.w3.org/2000/svg"\n      >\n        <rect\n          x="211.48"\n          y="-6"\n          width="300"\n          height="300"\n          rx="15"\n          transform="rotate(46.4634 211.48 -6)"\n          fill="#446DF6"\n        />\n      </svg>\n    );\n  }\n  \n  export function Triangle() {\n    return (\n      <svg\n        width="200"\n        height="208"\n        viewBox="0 0 349 364"\n        fill="none"\n        xmlns="http://www.w3.org/2000/svg"\n      >\n        <path\n          d="M328.852 1.79834C339.737 -2.05613 350.712 7.31786 348.608 18.6715L287.058 350.766C284.954 362.119 271.348 366.937 262.568 359.438L5.74062 140.087C-3.03979 132.588 -0.409476 118.396 10.4752 114.542L328.852 1.79834Z"\n          fill="#AB87FF"\n        />\n      </svg>\n    );\n  }\n  ',"/useTabs.tsx":'import { ReactNode, useState } from "react";\n\nexport type Tab = { label: string; id: string; children: ReactNode };\n\nexport function useTabs({\n  tabs,\n  initialTabId,\n  onChange,\n}: {\n  tabs: Tab[];\n  initialTabId: string;\n  onChange?: (id: string) => void;\n}) {\n  const [selectedTabIndex, setSelectedTab] = useState(() =>
1 {\n    const indexOfInitialTab = tabs.findIndex((tab) => tab.id === initialTabId);\n    return indexOfInitialTab === -1 ? 0 : indexOfInitialTab;\n  });\n\n  return {\n    tabProps: {\n      tabs,\n      selectedTabIndex,\n      onChange,\n      setSelectedTab,\n    },\n    selectedTab: tabs[selectedTabIndex],\n  };\n}\n'},customSetup:{dependencies:{classnames:"^2.3.1","react-transition-group":"^4.4.2"}}}),SpringExample=()=>(0,s.jsx)(a.B,{previewHeightClassname:"h-100",files:{"/spring.tsx":{code:'import classNames from "classnames";\nimport { useEffect, useRef, useState } from "react";\nimport { useTransition, animated, useSpring, easings } from "react-spring";\n\nimport { Tab } from "./useTabs";\n\ntype Props = {\n  selectedTabIndex: number;\n  tabs: Tab[];\n  setSelectedTab: (input: [number, number]) => void;\n};\n\nexport const Tabs = ({\n  tabs,\n  selectedTabIndex,\n  setSelectedTab,\n}: Props): JSX.Element => {\n  const [buttonRefs, setButtonRefs] = useState<Array<HTMLButtonElement | null>>(\n    []\n  );\n\n  useEffect(() => {\n    setButtonRefs((prev) => prev.slice(0, tabs.length));\n  }, [tabs.length]);\n\n  const navRef = useRef<HTMLDivElement>(null);\n  const navRect = navRef.current?.getBoundingClientRect();\n\n  const selectedRect = buttonRefs[selectedTabIndex]?.getBoundingClientRect();\n\n  const [hoveredTabIndex, setHoveredTabIndex] = useState<number | null>(null);\n  const hoveredRect =\n    buttonRefs[hoveredTabIndex ?? -1]?.getBoundingClientRect();\n\n  const onLeaveTabs = () => {\n    setHoveredTabIndex(null);\n  };\n\n  const onEnterTab = (i: number) => {\n    setHoveredTabIndex(i);\n  };\n\n  const onSelectTab = (i: number) => {\n    setSelectedTab([i, i > selectedTabIndex ? 1 : -1]);\n  };\n\n  const stylesChangingOnUpdate =\n    hoveredRect && navRect\n      ? {\n          transform: `translate3d(${hoveredRect.left - navRect.left}px,${\n            hoveredRect.top - navRect.top\n          }px,0px)`,\n          width: hoveredRect.width,\n          height: hoveredRect.height,\n        }\n      : {};\n\n  const bgTransition = useTransition(hoveredTabIndex != null, {\n    from: () => ({\n      ...stylesChangingOnUpdate,\n      opacity: 0,\n    }),\n    enter: {\n      ...stylesChangingOnUpdate,\n      opacity: 1,\n    },\n    update: stylesChangingOnUpdate,\n    leave: { opacity: 0 },\n    config: {\n      duration: 150,\n      easing: easings.easeOutCubic,\n    },\n  });\n\n  const underlineStyles = useSpring({\n    to:\n      selectedRect && navRect\n        ? {\n            width: selectedRect.width * 0.8,\n            transform: `translateX(calc(${\n              selectedRect.left - navRect.left\n            }px + 10%))`,\n            opacity: 1,\n          }\n        : { opacity: 0 },\n    config: {\n      duration: 150,\n      easing: easings.easeOutCubic,\n    },\n  });\n\n  return (\n    <nav\n      ref={navRef}\n      className="flex flex-shrink-0 justify-center items-center relative z-0 py-2"\n      onPointerLeave={onLeaveTabs}\n    >\n      {tabs.map((item, i) => {\n        return (\n          <button\n            key={i}\n            className={classNames(\n              "text-md relative rounded-md flex items-center h-8 px-4 z-20 bg-transparent text-sm text-slate-500 cursor-pointer select-none transition-colors",\n              {\n                "text-slate-700":\n                  hoveredTabIndex === i || selectedTabIndex === i,\n              }\n            )}\n            ref={(el) => (buttonRefs[i] = el)}\n            onPointerEnter={() => onEnterTab(i)}\n            onFocus={() => onEnterTab(i)}\n            onClick={() => onSelectTab(i)}\n          >\n            {item.label}\n          </button>\n        );\n      })}\n      {bgTransition((styles) => (\n        <animated.div\n          className="absolute z-10 rounded-md top-0 left-0 bg-gray-200"\n          style={styles}\n        />\n      ))}\n\n      <animated.div\n        className="absolute bottom-0 left-0 z-10 h-0.5 bg-slate-500"\n        style={underlineStyles}\n      />\n    </nav>\n  );\n};\n\nconst Content = ({\n  selectedTabIndex,\n  direction,\n  tabs,\n  className,\n}: {\n  selectedTabIndex: number;\n  direction: number;\n  tabs: Tab[];\n\n  className?: string;\n}): JSX.Element => {\n  const transitions = useTransition(selectedTabIndex, {\n    exitBeforeEnter: false,\n    keys: null,\n    from: {\n      opacity: 0,\n      transform: `translate3d(${\n        direction > 0 ? "100" : "-100"\n      }px,0,0) scale(0.8)`,\n    },\n    enter: { opacity: 1, transform: "translate3d(0px,0,0) scale(1)" },\n    leave: {\n      opacity: 0,\n      transform: `translate3d(${\n        direction > 0 ? "-100" : "100"\n      }px,0,0) scale(0.8)`,\n      position: "absolute",\n    }
1,\n    config: {\n      duration: 250,\n      easing: easings.easeOutCubic,\n    },\n  });\n\n  return transitions((styles, item) => (\n    <animated.div key={selectedTabIndex} style={styles} className={className}>\n      {tabs[item].children}\n    </animated.div>\n  ));\n};\n\nexport const Spring = { Tabs, Content };\n',active:!0},"/App.tsx":'import { useState } from "react";\nimport { Spring } from "./spring";\nimport { useTabs } from "./useTabs";\nimport { Circle, Square, Triangle } from "./shapes";\n\nexport default function App() {\n  const [hookProps] = useState({\n    tabs: [\n      {\n        label: "Circle",\n        children: <Circle />,\n        id: "Circle",\n      },\n      {\n        label: "Triangle",\n        children: <Triangle />,\n        id: "Triangle",\n      },\n      {\n        label: "Square",\n        children: <Square />,\n        id: "Square",\n      },\n    ],\n    initialTabId: "Triangle",\n  });\n  const spring = useTabs(hookProps);\n  return (\n    <div className="w-full flex flex-col space-y-24 items-center justify-center">\n      <div className="max-w-6xl">\n        <Spring.Tabs {...spring.tabProps} />\n        <Spring.Content {...spring.contentProps} className="py-9 flex flex-col items-center" />\n      </div>\n    </div>\n  );\n}\n\n',"/shapes.tsx":'export function Circle() {\n    return (\n      <svg\n        width="200"\n        height="200"\n        viewB
1ox="0 0 340 340"\n        fill="none"\n        xmlns="http://www.w3.org/2000/svg"\n      >\n        <path\n          d="M340 170C340 263.888 263.888 340 170 340C76.1116 340 0 263.888 0 170C0 76.1116 76.1116 0 170 0C263.888 0 340 76.1116 340 170Z"\n          fill="#FE65B7"\n        />\n      </svg>\n    );\n  }\n  \n  export function Square() {\n    return (\n      <svg\n        width="200"\n        height="200"\n        viewBox="0 0 412 412"\n        fill="none"\n        xmlns="http://www.w3.org/2000/svg"\n      >\n        <rect\n          x="211.48"\n          y="-6"\n          width="300"\n          height="300"\n          rx="15"\n          transform="rotate(46.4634 211.48 -6)"\n          fill="#446DF6"\n        />\n      </svg>\n    );\n  }\n  \n  export function Triangle() {\n    return (\n      <svg\n        width="200"\n        height="208"\n        viewBox="0 0 349 364"\n        fill="none"\n        xmlns="http://www.w3.org/2000/svg"\n      >\n        <path\n          d="M328.852 1.79834C339.737 -2.05613 350.712 7.31786 348.608 18.6715L287.058 350.766C284.954 362.119 271.348 366.937 262.568 359.438L5.74062 140.087C-3.03979 132.588 -0.409476 118.396 10.4752 114.542L328.852 1.79834Z"\n          fill="#AB87FF"\n        />\n      </svg>\n    );\n  }\n  ',"/useTabs.tsx":'import { ReactNode, useState } from "react";\n\nexport type Tab = { label: string; id: string; children: ReactNode };\n\nexport function useTabs({\n  tabs,\n  initialTabId,\n  onChange,\n}: {\n  tabs: Tab[];\n  initialTabId: string;\n  onChange?: (id: string) => void;\n}) {\n  const [[selectedTabIndex, direction], setSelectedTab] = useState(() =>
1 {\n    const indexOfInitialTab = tabs.findIndex((tab) => tab.id === initialTabId);\n    return [indexOfInitialTab === -1 ? 0 : indexOfInitialTab, 0];\n  });\n\n  return {\n    tabProps: {\n      tabs,\n      selectedTabIndex,\n      onChange,\n      setSelectedTab,\n    },\n    selectedTab: tabs[selectedTabIndex],\n    contentProps: {\n      direction,\n      selectedTabIndex,\n      tabs,\n    },\n  };\n}\n'},customSetup:{dependencies:{classnames:"^2.3.1","react-spring":"^9.5.0"}}}),FramerExample=n=>(0,s.jsx)(a.B,{previewHeightClassname:"h-100",files:{"/framer.tsx":{code:o,active:!0},"/App.tsx":r,"/shapes.tsx":l,"/useTabs.tsx":i},customSetup:{dependencies:{classnames:"^2.3.1","framer-motion":"^6.4.3"}}}),FramerLayoutExample=()=>(0,s.jsx)(a.B,{previewHeightClassname:"h-100",files:{"/framer-layout.tsx":{code:'import classNames from "classnames";\nimport { AnimatePresence, LayoutGroup, motion } from "framer-motion";\nimport { ReactNode, useState } from "react";\n\nimport { Tab } from "./useTabs";\n\nconst transition = {\n  type: "tween",\n  ease: "easeOut",\n  duration: 0.15,\n};\n\ntype Props = {\n  selectedTabIndex: number;\n  tabs: Tab[];\n  setSelectedTab: (input: [number, number]) => void;\n};\n\nexport const Tabs = ({\n  tabs,\n  selectedTabIndex,\n  setSelectedTab,\n}: Props): JSX.Element => {\n  const [hoveredTab, setHoveredTab] = useState<number | null>(null);\n  return (\n    <motion.nav\n      className="flex flex-shrink-0 justify-center items-center relative z-0 py-2"\n      onHoverEnd={() => setHoveredTab(null)}\n    >\n      <LayoutGroup id="tabs">\n        {tabs.map((item, i) => {\n          return (\n            <motion.button\n              key={i}\n              className={classNames(\n                "text-md relative rounded-md flex items-center h-8 px-4 text-sm text-slate-500 cursor-pointer select-none transition-colors",\n                {\n                  "text-slate-700": hoveredTab === i || selectedTabIndex === i,\n                }\n              )}\n              onHoverStart={() => setHoveredTab(i)}\n              onFocus={() => setHoveredTab(i)}\n              onClick={() => {\n                setSelectedTab([i, i > selectedTabIndex ? 1 : -1]);\n              }}\n            >\n              <span className="z-20">{item.label}</span>\n              {i === selectedTabIndex ? (\n                <motion.div\n                  transition={transition}\n                  layoutId="underline"\n                  className={\n                    "absolute z-10 h-0.5 left-2 right-2 -bottom-2 bg-slate-500"\n                  }\n                />\n              ) : null}\n              <AnimatePresence>\n                {i === hoveredTab ? (\n                  <motion.div\n                    className="absolute bottom-0 left-0 right-0 top-0 z-10 rounded-md bg-gray-200"\n                    initial={{\n                      opacity: 0,\n                    }}\n                    animate={{\n                      opacity: 1,\n                    }}\n                    exit={{\n                      opacity: 0,\n                    }}\n                    transition={transition}\n                    layoutId="hover"\n                  />\n                ) : null}\n              </AnimatePresence>\n            </motion.button>\n          );\n        })}\n      </LayoutGroup>\n    </motion.nav>\n  );\n};\n\nconst Content = ({\n  children,\n  className,\n  selectedTabIndex,\n  direction,\n}: {\n  direction: number;\n  selectedTabIndex: number;\n  children: ReactNode;\n  className?: string;\n}): JSX.Element => {\n  return (\n    <AnimatePresence exitBeforeEnter={false} custom={direction}>\n      <motion.div\n        key={selectedTabIndex}\n        variants={{\n          enter: (direction) => ({\n            opacity: 0,\n            x: direction > 0 ? 100 : -100,\n            scale: 0.8,\n          }),\n          center: { opacity: 1, x: 0, scale: 1, rotate: 0 },\n          exit: (direction) => ({\n            opacity: 0,\n            x: direction > 0 ? -100 : 100,\n            scale: 0.8,\n            position: "absolute",\n          }),\n        }}\n        transition={{ duration: 0.25 }}\n        initial={"enter"}\n        animate={"center"}\n        exit={"exit"}\n        custom={direction}\n        className={className}\n      >\n        {children}\n      </motion.div>\n    </AnimatePresence>\n  );\n};\n\nexport const FramerLayout = { Tabs, Content };\n',active:!0}
1,"/App.tsx":'import { useState } from "react";\nimport { FramerLayout } from "./framer-layout";\nimport { useTabs } from "./useTabs";\nimport { Circle, Square, Triangle } from "./shapes";\n\nexport default function App() {\n  const [hookProps] = useState({\n    tabs: [\n      {\n        label: "Circle",\n        children: <Circle />,\n        id: "Circle",\n      },\n      {\n        label: "Triangle",\n        children: <Triangle />,\n        id: "Triangle",\n      },\n      {\n        label: "Square",\n        children: <Square />,\n        id: "Square",\n      },\n    ],\n    initialTabId: "Triangle",\n  });\n  const framer = useTabs(hookProps);\n  return (\n    <div className="w-full flex flex-col space-y-24 items-center justify-center">\n      <div className="max-w-6xl">\n        <FramerLayout.Tabs {...framer.tabProps} />\n        <FramerLayout.Content\n          {...framer.contentProps}\n          className="text-center rounded-3xl py-9 flex flex-col items-center"\n        >\n          {framer.selectedTab.children}\n        </FramerLayout.Content>\n      </div>\n    </div>\n  );\n}\n',"/shapes.tsx":'export function Circle() {\n    return (\n      <svg\n        width="200"\n        height="200"\n        viewB
1ox="0 0 340 340"\n        fill="none"\n        xmlns="http://www.w3.org/2000/svg"\n      >\n        <path\n          d="M340 170C340 263.888 263.888 340 170 340C76.1116 340 0 263.888 0 170C0 76.1116 76.1116 0 170 0C263.888 0 340 76.1116 340 170Z"\n          fill="#FE65B7"\n        />\n      </svg>\n    );\n  }\n  \n  export function Square() {\n    return (\n      <svg\n        width="200"\n        height="200"\n        viewBox="0 0 412 412"\n        fill="none"\n        xmlns="http://www.w3.org/2000/svg"\n      >\n        <rect\n          x="211.48"\n          y="-6"\n          width="300"\n          height="300"\n          rx="15"\n          transform="rotate(46.4634 211.48 -6)"\n          fill="#446DF6"\n        />\n      </svg>\n    );\n  }\n  \n  export function Triangle() {\n    return (\n      <svg\n        width="200"\n        height="208"\n        viewBox="0 0 349 364"\n        fill="none"\n        xmlns="http://www.w3.org/2000/svg"\n      >\n        <path\n          d="M328.852 1.79834C339.737 -2.05613 350.712 7.31786 348.608 18.6715L287.058 350.766C284.954 362.119 271.348 366.937 262.568 359.438L5.74062 140.087C-3.03979 132.588 -0.409476 118.396 10.4752 114.542L328.852 1.79834Z"\n          fill="#AB87FF"\n        />\n      </svg>\n    );\n  }\n  ',"/useTabs.tsx":'import { ReactNode, useState } from "react";\n\nexport type Tab = { label: string; id: string; children: ReactNode };\n\nexport function useTabs({\n  tabs,\n  initialTabId,\n  onChange,\n}: {\n  tabs: Tab[];\n  initialTabId: string;\n  onChange?: (id: string) => void;\n}) {\n  const [[selectedTabIndex, direction], setSelectedTab] = useState(() =>
1 {\n    const indexOfInitialTab = tabs.findIndex((tab) => tab.id === initialTabId);\n    return [indexOfInitialTab === -1 ? 0 : indexOfInitialTab, 0];\n  });\n\n  return {\n    tabProps: {\n      tabs,\n      selectedTabIndex,\n      onChange,\n      setSelectedTab,\n    },\n    selectedTab: tabs[selectedTabIndex],\n    contentProps: {\n      direction,\n      selectedTabIndex,\n    },\n  };\n}\n'},customSetup:{dependencies:{classnames:"^2.3.1","framer-motion":"^6.4.3"}}}),TabsDemo=n=>(0,s.jsx)(a.B,{...n,hideEditor:!0,previewHeightClassname:"h-100",files:{"/framer.tsx":{code:o,active:!0},"/App.tsx":r,"/shapes.tsx":l,"/useTabs.tsx":i},customSetup:{dependencies:{classnames:"^2.3.1","framer-motion":"^6.4.3"}}})}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.